xref: /onnv-gate/usr/src/uts/sun4u/starfire/io/idn.c (revision 11311:639e7bc0b42f)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
52973Sgovinda  * Common Development and Distribution License (the "License").
62973Sgovinda  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
2211066Srafael.vanoni@sun.com  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #include <sys/types.h>
270Sstevel@tonic-gate #include <sys/sysmacros.h>
280Sstevel@tonic-gate #include <sys/open.h>
290Sstevel@tonic-gate #include <sys/param.h>
300Sstevel@tonic-gate #include <sys/machparam.h>
310Sstevel@tonic-gate #include <sys/systm.h>
320Sstevel@tonic-gate #include <sys/signal.h>
330Sstevel@tonic-gate #include <sys/cred.h>
340Sstevel@tonic-gate #include <sys/user.h>
350Sstevel@tonic-gate #include <sys/proc.h>
360Sstevel@tonic-gate #include <sys/vnode.h>
370Sstevel@tonic-gate #include <sys/uio.h>
380Sstevel@tonic-gate #include <sys/buf.h>
390Sstevel@tonic-gate #include <sys/file.h>
400Sstevel@tonic-gate #include <sys/kmem.h>
410Sstevel@tonic-gate #include <sys/stat.h>
420Sstevel@tonic-gate #include <sys/stream.h>
430Sstevel@tonic-gate #include <sys/stropts.h>
440Sstevel@tonic-gate #include <sys/strsubr.h>
450Sstevel@tonic-gate #include <sys/strsun.h>
460Sstevel@tonic-gate #include <inet/common.h>
470Sstevel@tonic-gate #include <inet/mi.h>
480Sstevel@tonic-gate #include <inet/nd.h>
490Sstevel@tonic-gate #include <sys/poll.h>
500Sstevel@tonic-gate #include <sys/utsname.h>
510Sstevel@tonic-gate #include <sys/debug.h>
520Sstevel@tonic-gate #include <sys/conf.h>
530Sstevel@tonic-gate #include <sys/ddi.h>
540Sstevel@tonic-gate #include <sys/sunddi.h>
550Sstevel@tonic-gate #include <sys/errno.h>
560Sstevel@tonic-gate #include <sys/modctl.h>
570Sstevel@tonic-gate #include <sys/machsystm.h>
580Sstevel@tonic-gate #include <sys/promif.h>
590Sstevel@tonic-gate #include <sys/prom_plat.h>
600Sstevel@tonic-gate #include <sys/obpdefs.h>
610Sstevel@tonic-gate #include <vm/seg_kmem.h>
620Sstevel@tonic-gate #include <vm/seg_kp.h>
630Sstevel@tonic-gate #include <sys/kstat.h>
640Sstevel@tonic-gate #include <sys/membar.h>
650Sstevel@tonic-gate #include <sys/ivintr.h>
660Sstevel@tonic-gate #include <sys/vm_machparam.h>
670Sstevel@tonic-gate #include <sys/x_call.h>
680Sstevel@tonic-gate #include <sys/cpuvar.h>
690Sstevel@tonic-gate #include <sys/archsystm.h>
700Sstevel@tonic-gate #include <sys/dmv.h>
710Sstevel@tonic-gate 
720Sstevel@tonic-gate #include <sys/idn.h>
730Sstevel@tonic-gate #include <sys/idn_xf.h>
740Sstevel@tonic-gate #include <sys/cpu_sgnblk_defs.h>
750Sstevel@tonic-gate #include <sys/cpu_sgn.h>
760Sstevel@tonic-gate 
770Sstevel@tonic-gate struct idn_gkstat	sg_kstat;
780Sstevel@tonic-gate 
790Sstevel@tonic-gate #define	MBXTBL_PART_REPORT	((caddr_t)1)
800Sstevel@tonic-gate #define	MBXTBL_FULL_REPORT	((caddr_t)2)
810Sstevel@tonic-gate 
820Sstevel@tonic-gate idn_domain_t	idn_domain[MAX_DOMAINS];
830Sstevel@tonic-gate idn_global_t	idn;
840Sstevel@tonic-gate int		idn_debug;
850Sstevel@tonic-gate int		idn_snoop;
860Sstevel@tonic-gate int		idn_history;
870Sstevel@tonic-gate 
880Sstevel@tonic-gate typedef enum {
890Sstevel@tonic-gate 	IDN_GPROPS_OKAY,
900Sstevel@tonic-gate 	IDN_GPROPS_UNCHECKED,
910Sstevel@tonic-gate 	IDN_GPROPS_ERROR
920Sstevel@tonic-gate } idn_gprops_t;
930Sstevel@tonic-gate 
940Sstevel@tonic-gate struct idn_history	idnhlog;
950Sstevel@tonic-gate 
960Sstevel@tonic-gate /*
970Sstevel@tonic-gate  * IDN "tunables".
980Sstevel@tonic-gate  */
990Sstevel@tonic-gate int		idn_smr_size;
1000Sstevel@tonic-gate int		idn_nwr_size;
1010Sstevel@tonic-gate int		idn_lowat;
1020Sstevel@tonic-gate int		idn_hiwat;
1030Sstevel@tonic-gate int		idn_protocol_nservers;
1040Sstevel@tonic-gate int		idn_awolmsg_interval;
1050Sstevel@tonic-gate int		idn_smr_bufsize;
1060Sstevel@tonic-gate int		idn_slab_bufcount;
1070Sstevel@tonic-gate int		idn_slab_prealloc;
1080Sstevel@tonic-gate int		idn_slab_maxperdomain;
1090Sstevel@tonic-gate int		idn_slab_mintotal;
1100Sstevel@tonic-gate int		idn_window_max;
1110Sstevel@tonic-gate int		idn_window_incr;
1120Sstevel@tonic-gate int		idn_window_emax;
1130Sstevel@tonic-gate int		idn_reclaim_min;
1140Sstevel@tonic-gate int		idn_reclaim_max;
1150Sstevel@tonic-gate int		idn_mbox_per_net;
1160Sstevel@tonic-gate int		idn_max_nets;
1170Sstevel@tonic-gate 
1180Sstevel@tonic-gate int		idn_netsvr_spin_count;
1190Sstevel@tonic-gate int		idn_netsvr_wait_min;
1200Sstevel@tonic-gate int		idn_netsvr_wait_max;
1210Sstevel@tonic-gate int		idn_netsvr_wait_shift;
1220Sstevel@tonic-gate 
1230Sstevel@tonic-gate int		idn_checksum;
1240Sstevel@tonic-gate 
1250Sstevel@tonic-gate int		idn_msgwait_nego;
1260Sstevel@tonic-gate int		idn_msgwait_cfg;
1270Sstevel@tonic-gate int		idn_msgwait_con;
1280Sstevel@tonic-gate int		idn_msgwait_fin;
1290Sstevel@tonic-gate int		idn_msgwait_cmd;
1300Sstevel@tonic-gate int		idn_msgwait_data;
1310Sstevel@tonic-gate 
1320Sstevel@tonic-gate int		idn_retryfreq_nego;
1330Sstevel@tonic-gate int		idn_retryfreq_con;
1340Sstevel@tonic-gate int		idn_retryfreq_fin;
1350Sstevel@tonic-gate 
1360Sstevel@tonic-gate int		idn_window_emax;	/* calculated */
1370Sstevel@tonic-gate int		idn_slab_maxperdomain;	/* calculated */
1380Sstevel@tonic-gate 
1390Sstevel@tonic-gate /*
1400Sstevel@tonic-gate  * DMV interrupt support.
1410Sstevel@tonic-gate  */
1420Sstevel@tonic-gate int		idn_pil;
1430Sstevel@tonic-gate int		idn_dmv_pending_max;
1440Sstevel@tonic-gate idn_dmv_msg_t	*idn_iv_queue[NCPU];
1450Sstevel@tonic-gate int		idn_intr_index[NCPU];	/* idn_handler ONLY */
1460Sstevel@tonic-gate static idn_dmv_data_t	*idn_dmv_data;
1470Sstevel@tonic-gate 
1480Sstevel@tonic-gate int		idn_sigbpil;
1490Sstevel@tonic-gate 
1500Sstevel@tonic-gate idnparam_t	idn_param_arr[] = {
1510Sstevel@tonic-gate { 0,		1,		0,		/* 0 */ "idn_modunloadable" },
1520Sstevel@tonic-gate };
1530Sstevel@tonic-gate 
1540Sstevel@tonic-gate /*
1550Sstevel@tonic-gate  * Parameters that are only accessible in a DEBUG driver.
1560Sstevel@tonic-gate  */
1570Sstevel@tonic-gate static char *idn_param_debug_only[] = {
1580Sstevel@tonic-gate #if 0
1590Sstevel@tonic-gate 	"idn_checksum",
1600Sstevel@tonic-gate #endif /* 0 */
1610Sstevel@tonic-gate 	0
1620Sstevel@tonic-gate };
1630Sstevel@tonic-gate 
1640Sstevel@tonic-gate /*
1650Sstevel@tonic-gate  * Parameters that are READ-ONLY.
1660Sstevel@tonic-gate  */
1670Sstevel@tonic-gate static char *idn_param_read_only[] = {
1680Sstevel@tonic-gate #if 0
1690Sstevel@tonic-gate 	"idn_window_emax",
1700Sstevel@tonic-gate 	"idn_slab_maxperdomain",
1710Sstevel@tonic-gate #endif /* 0 */
1720Sstevel@tonic-gate 	0
1730Sstevel@tonic-gate };
1740Sstevel@tonic-gate 
1750Sstevel@tonic-gate static struct idn_global_props {
1760Sstevel@tonic-gate 	int		p_min, p_max, p_def;
1770Sstevel@tonic-gate 	char		*p_string;
1780Sstevel@tonic-gate 	int		*p_var;
1790Sstevel@tonic-gate } idn_global_props[] = {
1800Sstevel@tonic-gate { 0,	0,	0,	"idn_debug",		&idn_debug		},
1810Sstevel@tonic-gate { 0,	1,	0,	"idn_history",		&idn_history		},
1820Sstevel@tonic-gate { 0,	IDN_SMR_MAXSIZE,
1830Sstevel@tonic-gate 		0,	"idn_smr_size",		&idn_smr_size		},
1840Sstevel@tonic-gate { 0,	IDN_SMR_MAXSIZE,
1850Sstevel@tonic-gate 		0,	"idn_nwr_size",		&idn_nwr_size		},
1860Sstevel@tonic-gate { 1,	512*1024,
1870Sstevel@tonic-gate 		1,	"idn_lowat",		&idn_lowat		},
1880Sstevel@tonic-gate { 1*1024,
1890Sstevel@tonic-gate 	1*1024*1024,
1900Sstevel@tonic-gate 		256*1024,
1910Sstevel@tonic-gate 			"idn_hiwat",		&idn_hiwat		},
1920Sstevel@tonic-gate { IDN_SMR_BUFSIZE_MIN,
1930Sstevel@tonic-gate 	IDN_SMR_BUFSIZE_MAX,
1940Sstevel@tonic-gate 		IDN_SMR_BUFSIZE_DEF,
1950Sstevel@tonic-gate 			"idn_smr_bufsize",	&idn_smr_bufsize	},
1960Sstevel@tonic-gate { 4,	1024,	32,	"idn_slab_bufcount",	&idn_slab_bufcount	},
1970Sstevel@tonic-gate { 0,	10,	0,	"idn_slab_prealloc",	&idn_slab_prealloc	},
1980Sstevel@tonic-gate { 2,	MAX_DOMAINS,
1990Sstevel@tonic-gate 		8,	"idn_slab_mintotal",	&idn_slab_mintotal	},
2000Sstevel@tonic-gate { 8,	256,	64,	"idn_window_max",	&idn_window_max		},
2010Sstevel@tonic-gate { 0,	32,	8,	"idn_window_incr",	&idn_window_incr	},
2020Sstevel@tonic-gate { 1,	128,	5,	"idn_reclaim_min",	&idn_reclaim_min	},
2030Sstevel@tonic-gate { 0,	128,	0,	"idn_reclaim_max",	&idn_reclaim_max	},
2040Sstevel@tonic-gate { 1,	IDN_MAXMAX_NETS,
2050Sstevel@tonic-gate 		8,	"idn_max_nets",		&idn_max_nets		},
2060Sstevel@tonic-gate { 31,	511,	127,	"idn_mbox_per_net",	&idn_mbox_per_net	},
2070Sstevel@tonic-gate { 0,	1,	1,	"idn_checksum",		&idn_checksum		},
2080Sstevel@tonic-gate { 0,	10000,	500,	"idn_netsvr_spin_count",
2090Sstevel@tonic-gate 						&idn_netsvr_spin_count	},
2100Sstevel@tonic-gate { 0,	30*100,	40,	"idn_netsvr_wait_min",	&idn_netsvr_wait_min	},
2110Sstevel@tonic-gate { 0,	60*100,	16*100,	"idn_netsvr_wait_max",	&idn_netsvr_wait_max	},
2120Sstevel@tonic-gate { 1,	5,	1,	"idn_netsvr_wait_shift",
2130Sstevel@tonic-gate 						&idn_netsvr_wait_shift	},
2140Sstevel@tonic-gate { 1,	MAX_DOMAINS,
2150Sstevel@tonic-gate 		IDN_PROTOCOL_NSERVERS,
2160Sstevel@tonic-gate 			"idn_protocol_nservers",
2170Sstevel@tonic-gate 						&idn_protocol_nservers	},
2180Sstevel@tonic-gate { 0,	3600,	IDN_AWOLMSG_INTERVAL,
2190Sstevel@tonic-gate 			"idn_awolmsg_interval",	&idn_awolmsg_interval	},
2200Sstevel@tonic-gate { 10,	300,	IDN_MSGWAIT_NEGO,
2210Sstevel@tonic-gate 			"idn_msgwait_nego",	&idn_msgwait_nego	},
2220Sstevel@tonic-gate { 10,	300,	IDN_MSGWAIT_CFG,
2230Sstevel@tonic-gate 			"idn_msgwait_cfg",	&idn_msgwait_cfg	},
2240Sstevel@tonic-gate { 10,	300,	IDN_MSGWAIT_CON,
2250Sstevel@tonic-gate 			"idn_msgwait_con",	&idn_msgwait_con	},
2260Sstevel@tonic-gate { 10,	300,	IDN_MSGWAIT_FIN,
2270Sstevel@tonic-gate 			"idn_msgwait_fin",	&idn_msgwait_fin	},
2280Sstevel@tonic-gate { 10,	300,	IDN_MSGWAIT_CMD,
2290Sstevel@tonic-gate 			"idn_msgwait_cmd",	&idn_msgwait_cmd	},
2300Sstevel@tonic-gate { 10,	300,	IDN_MSGWAIT_DATA,
2310Sstevel@tonic-gate 			"idn_msgwait_data",	&idn_msgwait_data	},
2320Sstevel@tonic-gate { 1,	60,	IDN_RETRYFREQ_NEGO,
2330Sstevel@tonic-gate 			"idn_retryfreq_nego",	&idn_retryfreq_nego	},
2340Sstevel@tonic-gate { 1,	60,	IDN_RETRYFREQ_CON,
2350Sstevel@tonic-gate 			"idn_retryfreq_con",	&idn_retryfreq_con	},
2360Sstevel@tonic-gate { 1,	60,	IDN_RETRYFREQ_FIN,
2370Sstevel@tonic-gate 			"idn_retryfreq_fin",	&idn_retryfreq_fin	},
2380Sstevel@tonic-gate { 1,	9,	IDN_PIL,
2390Sstevel@tonic-gate 			"idn_pil",		&idn_pil		},
2400Sstevel@tonic-gate { 1,	9,	IDN_SIGBPIL,
2410Sstevel@tonic-gate 			"idn_sigbpil",		&idn_sigbpil		},
2420Sstevel@tonic-gate { 8,	512,	IDN_DMV_PENDING_MAX,
2430Sstevel@tonic-gate 			"idn_dmv_pending_max",	&idn_dmv_pending_max	},
2440Sstevel@tonic-gate { 0,	0,	0,	NULL,			NULL			}
2450Sstevel@tonic-gate };
2460Sstevel@tonic-gate 
2470Sstevel@tonic-gate struct idn	*idn_i2s_table[IDN_MAXMAX_NETS << 1];
2480Sstevel@tonic-gate clock_t		idn_msg_waittime[IDN_NUM_MSGTYPES];
2490Sstevel@tonic-gate clock_t		idn_msg_retrytime[(int)IDN_NUM_RETRYTYPES];
2500Sstevel@tonic-gate 
2510Sstevel@tonic-gate static caddr_t	idn_ndlist;	/* head of 'named dispatch' var list */
2520Sstevel@tonic-gate 
2530Sstevel@tonic-gate static int	idnattach(dev_info_t *, ddi_attach_cmd_t);
2540Sstevel@tonic-gate static int	idndetach(dev_info_t *, ddi_detach_cmd_t);
2550Sstevel@tonic-gate static int	idnopen(register queue_t *, dev_t *, int, int, cred_t *);
2560Sstevel@tonic-gate static int	idnclose(queue_t *, int, cred_t *);
2570Sstevel@tonic-gate static int	idnwput(queue_t *, mblk_t *);
2580Sstevel@tonic-gate static int	idnwsrv(queue_t *);
2590Sstevel@tonic-gate static int	idnrput(queue_t *, mblk_t *);
2600Sstevel@tonic-gate static void	idnioctl(queue_t *, mblk_t *);
2610Sstevel@tonic-gate static idn_gprops_t	idn_check_conf(dev_info_t *dip, processorid_t *cpuid);
2620Sstevel@tonic-gate static int	idn_size_check();
2630Sstevel@tonic-gate static void	idn_xmit_monitor_init();
2640Sstevel@tonic-gate static void	idn_xmit_monitor_deinit();
2650Sstevel@tonic-gate static void	idn_init_msg_waittime();
2660Sstevel@tonic-gate static void	idn_init_msg_retrytime();
2670Sstevel@tonic-gate static void	idn_sigb_setup(cpu_sgnblk_t *sigbp, void *arg);
2680Sstevel@tonic-gate static int	idn_init(dev_info_t *dip);
2690Sstevel@tonic-gate static int	idn_deinit();
2700Sstevel@tonic-gate static void	idn_sigbhandler_create();
2710Sstevel@tonic-gate static void	idn_sigbhandler_kill();
2720Sstevel@tonic-gate static uint_t	idn_sigbhandler_wakeup(caddr_t arg1, caddr_t arg2);
2730Sstevel@tonic-gate static void	idn_sigbhandler_thread(struct sigbintr **sbpp);
2740Sstevel@tonic-gate static void	idn_sigbhandler(processorid_t cpuid, cpu_sgnblk_t *sgnblkp);
2750Sstevel@tonic-gate static int	idn_info(idnsb_info_t *sfp);
2760Sstevel@tonic-gate static int	idn_init_smr();
2770Sstevel@tonic-gate static void	idn_deinit_smr();
2780Sstevel@tonic-gate static int	idn_prom_getsmr(uint_t *smrsz, uint64_t *paddrp,
2790Sstevel@tonic-gate 				uint64_t *sizep);
2800Sstevel@tonic-gate static int	idn_init_handler();
2810Sstevel@tonic-gate static void	idn_deinit_handler();
2820Sstevel@tonic-gate static uint_t	idn_handler(caddr_t unused, caddr_t unused2);
2830Sstevel@tonic-gate /*
2840Sstevel@tonic-gate  * ioctl services
2850Sstevel@tonic-gate  */
2860Sstevel@tonic-gate static int	idnioc_link(idnop_t *idnop);
2870Sstevel@tonic-gate static int	idnioc_unlink(idnop_t *idnop);
2880Sstevel@tonic-gate static int	idn_rw_mem(idnop_t *idnop);
2890Sstevel@tonic-gate static int	idn_send_ping(idnop_t *idnop);
2900Sstevel@tonic-gate 
2910Sstevel@tonic-gate static void 	idn_domains_init(struct hwconfig *local_hw);
2920Sstevel@tonic-gate static void 	idn_domains_deinit();
2930Sstevel@tonic-gate static void	idn_retrytask_init();
2940Sstevel@tonic-gate static void	idn_retrytask_deinit();
2950Sstevel@tonic-gate static void	idn_gkstat_init();
2960Sstevel@tonic-gate static void	idn_gkstat_deinit();
2970Sstevel@tonic-gate static int	idn_gkstat_update();
2980Sstevel@tonic-gate static void	idn_timercache_init();
2990Sstevel@tonic-gate static void	idn_timercache_deinit();
3000Sstevel@tonic-gate static void	idn_dopers_init();
3010Sstevel@tonic-gate static void	idn_dopers_deinit();
3020Sstevel@tonic-gate 
3030Sstevel@tonic-gate static void	idn_param_cleanup();
3040Sstevel@tonic-gate static int	idn_param_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *cr);
3050Sstevel@tonic-gate static int	idn_param_set(queue_t *q, mblk_t *mp, char *value, caddr_t cp,
3060Sstevel@tonic-gate 					cred_t *cr);
3070Sstevel@tonic-gate static int	idn_param_register(register idnparam_t *idnpa, int count);
3080Sstevel@tonic-gate static int	idn_slabpool_report(queue_t *wq, mblk_t *mp, caddr_t cp,
3090Sstevel@tonic-gate 					cred_t *cr);
3100Sstevel@tonic-gate static int	idn_buffer_report(queue_t *wq, mblk_t *mp, caddr_t cp,
3110Sstevel@tonic-gate 					cred_t *cr);
3120Sstevel@tonic-gate static int	idn_mboxtbl_report(queue_t *wq, mblk_t *mp, caddr_t cp,
3130Sstevel@tonic-gate 					cred_t *cr);
3140Sstevel@tonic-gate static int	idn_mainmbox_report(queue_t *wq, mblk_t *mp, caddr_t cp,
3150Sstevel@tonic-gate 					cred_t *cr);
3160Sstevel@tonic-gate static void	idn_mainmbox_domain_report(queue_t *wq, mblk_t *mp, int domid,
3170Sstevel@tonic-gate 					idn_mainmbox_t *mmp, char *mbxtype);
3180Sstevel@tonic-gate static int	idn_global_report(queue_t *wq, mblk_t *mp, caddr_t cp,
3190Sstevel@tonic-gate 					cred_t *cr);
3200Sstevel@tonic-gate static int	idn_domain_report(queue_t *wq, mblk_t *mp, caddr_t cp,
3210Sstevel@tonic-gate 					cred_t *cr);
3220Sstevel@tonic-gate static int	idn_get_net_binding(queue_t *wq, mblk_t *mp, caddr_t cp,
3230Sstevel@tonic-gate 					cred_t *cr);
3240Sstevel@tonic-gate static int	idn_set_net_binding(queue_t *wq, mblk_t *mp, char *value,
3250Sstevel@tonic-gate 					caddr_t cp, cred_t *cr);
3260Sstevel@tonic-gate 
3270Sstevel@tonic-gate /*
3280Sstevel@tonic-gate  * String definitions used for DEBUG and non-DEBUG.
3290Sstevel@tonic-gate  */
3300Sstevel@tonic-gate const char	*idnm_str[] = {
3310Sstevel@tonic-gate /*  0 */	"null",
3320Sstevel@tonic-gate /*  1 */	"nego",
3330Sstevel@tonic-gate /*  2 */	"con",
3340Sstevel@tonic-gate /*  3 */	"cfg",
3350Sstevel@tonic-gate /*  4 */	"fin",
3360Sstevel@tonic-gate /*  5 */	"cmd",
3370Sstevel@tonic-gate /*  6 */	"data",
3380Sstevel@tonic-gate };
3390Sstevel@tonic-gate 
3400Sstevel@tonic-gate const char	*idnds_str[] = {
3410Sstevel@tonic-gate /*  0 */	"CLOSED",
3420Sstevel@tonic-gate /*  1 */	"NEGO_PEND",
3430Sstevel@tonic-gate /*  2 */	"NEGO_SENT",
3440Sstevel@tonic-gate /*  3 */	"NEGO_RCVD",
3450Sstevel@tonic-gate /*  4 */	"CONFIG",
3460Sstevel@tonic-gate /*  5 */	"CON_PEND",
3470Sstevel@tonic-gate /*  6 */	"CON_SENT",
3480Sstevel@tonic-gate /*  7 */	"CON_RCVD",
3490Sstevel@tonic-gate /*  8 */	"CON_READY",
3500Sstevel@tonic-gate /*  9 */	"CONNECTED",
3510Sstevel@tonic-gate /* 10 */	"FIN_PEND",
3520Sstevel@tonic-gate /* 11 */	"FIN_SENT",
3530Sstevel@tonic-gate /* 12 */	"FIN_RCVD",
3540Sstevel@tonic-gate /* 13 */	"DMAP"
3550Sstevel@tonic-gate };
3560Sstevel@tonic-gate 
3570Sstevel@tonic-gate const char	*idnxs_str[] = {
3580Sstevel@tonic-gate /* 0 */		"PEND",
3590Sstevel@tonic-gate /* 1 */		"SENT",
3600Sstevel@tonic-gate /* 2 */		"RCVD",
3610Sstevel@tonic-gate /* 3 */		"FINAL",
3620Sstevel@tonic-gate /* 4 */		"NIL"
3630Sstevel@tonic-gate };
3640Sstevel@tonic-gate 
3650Sstevel@tonic-gate const char	*idngs_str[] = {
3660Sstevel@tonic-gate /*  0 */	"OFFLINE",
3670Sstevel@tonic-gate /*  1 */	"CONNECT",
3680Sstevel@tonic-gate /*  2 */	"ONLINE",
3690Sstevel@tonic-gate /*  3 */	"DISCONNECT",
3700Sstevel@tonic-gate /*  4 */	"RECONFIG",
3710Sstevel@tonic-gate /*  5 */	"unknown",
3720Sstevel@tonic-gate /*  6 */	"unknown",
3730Sstevel@tonic-gate /*  7 */	"unknown",
3740Sstevel@tonic-gate /*  8 */	"unknown",
3750Sstevel@tonic-gate /*  9 */	"unknown",
3760Sstevel@tonic-gate /* 10 */	"IGNORE"
3770Sstevel@tonic-gate };
3780Sstevel@tonic-gate 
3790Sstevel@tonic-gate const char	*idncmd_str[] = {
3800Sstevel@tonic-gate /*  0 */	"unknown",
3810Sstevel@tonic-gate /*  1 */	"SLABALLOC",
3820Sstevel@tonic-gate /*  2 */	"SLABFREE",
3830Sstevel@tonic-gate /*  3 */	"SLABREAP",
3840Sstevel@tonic-gate /*  4 */	"NODENAME"
3850Sstevel@tonic-gate };
3860Sstevel@tonic-gate 
3870Sstevel@tonic-gate const char	*idncon_str[] = {
3880Sstevel@tonic-gate /*  0 */	"OFF",
3890Sstevel@tonic-gate /*  1 */	"NORMAL",
3900Sstevel@tonic-gate /*  2 */	"QUERY"
3910Sstevel@tonic-gate };
3920Sstevel@tonic-gate 
3930Sstevel@tonic-gate const char	*idnfin_str[] = {
3940Sstevel@tonic-gate /*  0 */	"OFF",
3950Sstevel@tonic-gate /*  1 */	"NORMAL",
3960Sstevel@tonic-gate /*  2 */	"FORCE_SOFT",
3970Sstevel@tonic-gate /*  3 */	"FORCE_HARD",
3980Sstevel@tonic-gate /*  4 */	"QUERY"
3990Sstevel@tonic-gate };
4000Sstevel@tonic-gate 
4010Sstevel@tonic-gate const char	*idnfinopt_str[] = {
4020Sstevel@tonic-gate /*  0 */	"NONE",
4030Sstevel@tonic-gate /*  1 */	"UNLINK",
4040Sstevel@tonic-gate /*  2 */	"RELINK"
4050Sstevel@tonic-gate };
4060Sstevel@tonic-gate 
4070Sstevel@tonic-gate const char	*idnfinarg_str[] = {
4080Sstevel@tonic-gate /*  0 */	"NONE",
4090Sstevel@tonic-gate /*  1 */	"SMRBAD",
4100Sstevel@tonic-gate /*  2 */	"CPUCFG",
4110Sstevel@tonic-gate /*  3 */	"HWERR",
4120Sstevel@tonic-gate /*  4 */	"CFGERR_FATAL",
4130Sstevel@tonic-gate /*  5 */	"CFGERR_MTU",
4140Sstevel@tonic-gate /*  6 */	"CFGERR_BUF",
4150Sstevel@tonic-gate /*  7 */	"CFGERR_SLAB",
4160Sstevel@tonic-gate /*  8 */	"CFGERR_NWR",
4170Sstevel@tonic-gate /*  9 */	"CFGERR_NETS",
4180Sstevel@tonic-gate /* 10 */	"CFGERR_MBOX",
4190Sstevel@tonic-gate /* 11 */	"CFGERR_NMCADR",
4200Sstevel@tonic-gate /* 12 */	"CFGERR_MCADR",
4210Sstevel@tonic-gate /* 13 */	"CFGERR_CKSUM",
4220Sstevel@tonic-gate /* 14 */	"CFGERR_SMR",
4230Sstevel@tonic-gate };
4240Sstevel@tonic-gate 
4250Sstevel@tonic-gate const char	*idnsync_str[] = {
4260Sstevel@tonic-gate /*  0 */	"NIL",
4270Sstevel@tonic-gate /*  1 */	"CONNECT",
4280Sstevel@tonic-gate /*  2 */	"DISCONNECT"
4290Sstevel@tonic-gate };
4300Sstevel@tonic-gate 
4310Sstevel@tonic-gate const char	*idnreg_str[] = {
4320Sstevel@tonic-gate /*  0 */	"REG",
4330Sstevel@tonic-gate /*  1 */	"NEW",
4340Sstevel@tonic-gate /*  2 */	"QUERY"
4350Sstevel@tonic-gate };
4360Sstevel@tonic-gate 
4370Sstevel@tonic-gate const char	*idnnack_str[] = {
4380Sstevel@tonic-gate /*  0 */	"unknown",
4390Sstevel@tonic-gate /*  1 */	"NOCONN",
4400Sstevel@tonic-gate /*  2 */	"BADCHAN",
4410Sstevel@tonic-gate /*  3 */	"BADCFG",
4420Sstevel@tonic-gate /*  4 */	"BADCMD",
4430Sstevel@tonic-gate /*  5 */	"RETRY",
4440Sstevel@tonic-gate /*  6 */	"DUP",
4450Sstevel@tonic-gate /*  7 */	"EXIT",
4460Sstevel@tonic-gate /*  8 */	"--reserved1",
4470Sstevel@tonic-gate /*  9 */	"--reserved2",
4480Sstevel@tonic-gate /* 10 */	"--reserved3"
4490Sstevel@tonic-gate };
4500Sstevel@tonic-gate 
4510Sstevel@tonic-gate const char	*idnop_str[] = {
4520Sstevel@tonic-gate /*  0 */	"DISCONNECTED",
4530Sstevel@tonic-gate /*  1 */	"CONNECTED",
4540Sstevel@tonic-gate /*  2 */	"ERROR"
4550Sstevel@tonic-gate };
4560Sstevel@tonic-gate 
4570Sstevel@tonic-gate const char	*chanop_str[] = {
4580Sstevel@tonic-gate /*  0 */	"OPEN",
4590Sstevel@tonic-gate /*  1 */	"SOFT_CLOSE",
4600Sstevel@tonic-gate /*  2 */	"HARD_CLOSE",
4610Sstevel@tonic-gate /*  3 */	"OFFLINE",
4620Sstevel@tonic-gate /*  4 */	"ONLINE"
4630Sstevel@tonic-gate };
4640Sstevel@tonic-gate 
4650Sstevel@tonic-gate const char	*chanaction_str[] = {
4660Sstevel@tonic-gate /*  0 */	"DETACH",
4670Sstevel@tonic-gate /*  1 */	"STOP",
4680Sstevel@tonic-gate /*  2 */	"SUSPEND",
4690Sstevel@tonic-gate /*  3 */	"RESUME",
4700Sstevel@tonic-gate /*  4 */	"RESTART",
4710Sstevel@tonic-gate /*  5 */	"ATTACH"
4720Sstevel@tonic-gate };
4730Sstevel@tonic-gate 
4740Sstevel@tonic-gate const char	*timer_str[] = {
4750Sstevel@tonic-gate /* 0 */		"NIL",
4760Sstevel@tonic-gate /* 1 */		"MSG"
4770Sstevel@tonic-gate };
4780Sstevel@tonic-gate 
4790Sstevel@tonic-gate static struct module_info idnrinfo = {
4800Sstevel@tonic-gate 	IDNIDNUM,		/* mi_idnum */
4810Sstevel@tonic-gate 	IDNNAME,		/* mi_idname */
4820Sstevel@tonic-gate 	IDNMINPSZ,		/* mi_minpsz */
4830Sstevel@tonic-gate 	IDNMAXPSZ,		/* mi_maxpsz */
4840Sstevel@tonic-gate 	0,			/* mi_hiwat - see IDN_HIWAT */
4850Sstevel@tonic-gate 	0			/* mi_lowat - see IDN_LOWAT */
4860Sstevel@tonic-gate };
4870Sstevel@tonic-gate 
4880Sstevel@tonic-gate static struct module_info idnwinfo = {
4890Sstevel@tonic-gate 	IDNIDNUM,		/* mi_idnum */
4900Sstevel@tonic-gate 	IDNNAME,		/* mi_idname */
4910Sstevel@tonic-gate 	IDNMINPSZ,		/* mi_minpsz */
4920Sstevel@tonic-gate 	IDNMAXPSZ,		/* mi_maxpsz */
4930Sstevel@tonic-gate 	0,			/* mi_hiwat - see IDN_HIWAT */
4940Sstevel@tonic-gate 	0			/* mi_lowat - see IDN_LOWAT */
4950Sstevel@tonic-gate };
4960Sstevel@tonic-gate 
4970Sstevel@tonic-gate static struct qinit idnrinit = {
4980Sstevel@tonic-gate 	idnrput,		/* qi_putp */
4990Sstevel@tonic-gate 	NULL,			/* qi_srvp */
5000Sstevel@tonic-gate 	idnopen,		/* qi_qopen */
5010Sstevel@tonic-gate 	idnclose,		/* qi_qclose */
5020Sstevel@tonic-gate 	NULL,			/* qi_qadmin */
5030Sstevel@tonic-gate 	&idnrinfo,		/* qi_minfo */
5040Sstevel@tonic-gate 	NULL,			/* qi_mstat */
5050Sstevel@tonic-gate 	NULL,			/* qi_rwp */
5060Sstevel@tonic-gate 	NULL,			/* qi_infop */
5070Sstevel@tonic-gate 	STRUIOT_DONTCARE	/* qi_struiot */
5080Sstevel@tonic-gate };
5090Sstevel@tonic-gate 
5100Sstevel@tonic-gate static struct qinit idnwinit = {
5110Sstevel@tonic-gate 	idnwput,		/* qi_putp */
5120Sstevel@tonic-gate 	idnwsrv,		/* qi_srvp */
5130Sstevel@tonic-gate 	NULL,			/* qi_qopen */
5140Sstevel@tonic-gate 	NULL,			/* qi_qclose */
5150Sstevel@tonic-gate 	NULL,			/* qi_qadmin */
5160Sstevel@tonic-gate 	&idnwinfo,		/* qi_minfo */
5170Sstevel@tonic-gate 	NULL,			/* qi_mstat */
5180Sstevel@tonic-gate 	NULL,			/* qi_rwp */
5190Sstevel@tonic-gate 	NULL,			/* qi_infop */
5200Sstevel@tonic-gate 	STRUIOT_DONTCARE	/* qi_struiot */
5210Sstevel@tonic-gate };
5220Sstevel@tonic-gate 
5230Sstevel@tonic-gate struct streamtab idninfo = {
5240Sstevel@tonic-gate 	&idnrinit,		/* st_rdinit */
5250Sstevel@tonic-gate 	&idnwinit,		/* st_wrinit */
5260Sstevel@tonic-gate 	NULL,			/* st_muxrinit */
5270Sstevel@tonic-gate 	NULL,			/* st_muxwinit */
5280Sstevel@tonic-gate };
5290Sstevel@tonic-gate 
5300Sstevel@tonic-gate /*
5310Sstevel@tonic-gate  * Module linkage information (cb_ops & dev_ops) for the kernel.
5320Sstevel@tonic-gate  */
5330Sstevel@tonic-gate 
5340Sstevel@tonic-gate static struct cb_ops cb_idnops = {
5350Sstevel@tonic-gate 	nulldev,		/* cb_open */
5360Sstevel@tonic-gate 	nulldev,		/* cb_close */
5370Sstevel@tonic-gate 	nodev,			/* cb_strategy */
5380Sstevel@tonic-gate 	nodev,			/* cb_print */
5390Sstevel@tonic-gate 	nodev,			/* cb_dump */
5400Sstevel@tonic-gate 	nodev,			/* cb_read */
5410Sstevel@tonic-gate 	nodev,			/* cb_write */
5420Sstevel@tonic-gate 	nodev,			/* cb_ioctl */
5430Sstevel@tonic-gate 	nodev,			/* cb_devmap */
5440Sstevel@tonic-gate 	nodev,			/* cb_mmap */
5450Sstevel@tonic-gate 	nodev,			/* cb_segmap */
5460Sstevel@tonic-gate 	nochpoll,		/* cb_chpoll */
5470Sstevel@tonic-gate 	ddi_prop_op,		/* cb_prop_op */
5480Sstevel@tonic-gate 	&idninfo,		/* cb_stream */
5490Sstevel@tonic-gate 	D_MP,			/* cb_flag */
5500Sstevel@tonic-gate 	CB_REV,			/* cb_rev */
5510Sstevel@tonic-gate 	nodev,			/* cb_aread */
5520Sstevel@tonic-gate 	nodev,			/* cb_awrite */
5530Sstevel@tonic-gate };
5540Sstevel@tonic-gate 
5550Sstevel@tonic-gate static struct dev_ops idnops = {
5560Sstevel@tonic-gate 	DEVO_REV,		/* devo_rev */
5570Sstevel@tonic-gate 	0,			/* devo_refcnt */
5580Sstevel@tonic-gate 	ddi_no_info,		/* devo_getinfo */
5590Sstevel@tonic-gate 	nulldev,		/* devo_identify */
5600Sstevel@tonic-gate 	nulldev,		/* devo_probe */
5610Sstevel@tonic-gate 	idnattach,		/* devo_attach */
5620Sstevel@tonic-gate 	idndetach,		/* devo_detach */
5630Sstevel@tonic-gate 	nodev,			/* devo_reset */
5640Sstevel@tonic-gate 	&cb_idnops,		/* devo_cb_ops */
5650Sstevel@tonic-gate 	(struct bus_ops *)NULL,	/* devo_bus_ops */
5667656SSherry.Moore@Sun.COM 	NULL,			/* devo_power */
5677656SSherry.Moore@Sun.COM 	ddi_quiesce_not_needed,		/* quiesce */
5680Sstevel@tonic-gate };
5690Sstevel@tonic-gate 
5700Sstevel@tonic-gate extern cpuset_t	cpu_ready_set;
5710Sstevel@tonic-gate 
5720Sstevel@tonic-gate static struct modldrv modldrv = {
5730Sstevel@tonic-gate 	&mod_driverops,		/* This module is a pseudo driver */
5747656SSherry.Moore@Sun.COM 	IDNDESC " 1.58",
5750Sstevel@tonic-gate 	&idnops
5760Sstevel@tonic-gate };
5770Sstevel@tonic-gate 
5780Sstevel@tonic-gate static struct modlinkage modlinkage = {
5790Sstevel@tonic-gate 	MODREV_1,
5800Sstevel@tonic-gate 	&modldrv,
5810Sstevel@tonic-gate 	NULL
5820Sstevel@tonic-gate };
5830Sstevel@tonic-gate 
5840Sstevel@tonic-gate /*
5850Sstevel@tonic-gate  * --------------------------------------------------
5860Sstevel@tonic-gate  */
5870Sstevel@tonic-gate int
_init(void)5880Sstevel@tonic-gate _init(void)
5890Sstevel@tonic-gate {
5900Sstevel@tonic-gate 	idn.version = IDN_VERSION;
5910Sstevel@tonic-gate 
5920Sstevel@tonic-gate 	return (mod_install(&modlinkage));
5930Sstevel@tonic-gate }
5940Sstevel@tonic-gate 
5950Sstevel@tonic-gate int
_fini(void)5960Sstevel@tonic-gate _fini(void)
5970Sstevel@tonic-gate {
5980Sstevel@tonic-gate 	return (mod_remove(&modlinkage));
5990Sstevel@tonic-gate }
6000Sstevel@tonic-gate 
6010Sstevel@tonic-gate int
_info(struct modinfo * modinfop)6020Sstevel@tonic-gate _info(struct modinfo *modinfop)
6030Sstevel@tonic-gate {
6040Sstevel@tonic-gate 	return (mod_info(&modlinkage, modinfop));
6050Sstevel@tonic-gate }
6060Sstevel@tonic-gate 
6070Sstevel@tonic-gate /*
6080Sstevel@tonic-gate  * ----------------------------------------------
6090Sstevel@tonic-gate  */
6100Sstevel@tonic-gate static int
idnattach(dev_info_t * dip,ddi_attach_cmd_t cmd)6110Sstevel@tonic-gate idnattach(dev_info_t *dip, ddi_attach_cmd_t cmd)
6120Sstevel@tonic-gate {
6130Sstevel@tonic-gate 	int		instance;
6140Sstevel@tonic-gate 	int		doinit = 0;
6150Sstevel@tonic-gate 	processorid_t	bcpuid;
6160Sstevel@tonic-gate 	struct idn	*sip;
6170Sstevel@tonic-gate 	struct idnstr	*stp;
6180Sstevel@tonic-gate 	procname_t	proc = "idnattach";
6190Sstevel@tonic-gate 
6200Sstevel@tonic-gate 
6210Sstevel@tonic-gate #ifndef	lint
6220Sstevel@tonic-gate 	ASSERT(sizeof (idnsb_t) == IDNSB_SIZE);
6230Sstevel@tonic-gate 	ASSERT((uint_t)&((struct idnsb *)0)->id_hwchkpt[0] == 0x40);
6240Sstevel@tonic-gate #endif	/* lint */
6250Sstevel@tonic-gate 
6260Sstevel@tonic-gate 	switch (cmd) {
6270Sstevel@tonic-gate 	case DDI_RESUME:
6280Sstevel@tonic-gate 		sip = ddi_get_driver_private(dip);
6290Sstevel@tonic-gate 		/*
6300Sstevel@tonic-gate 		 * sip may have not yet been set if the
6310Sstevel@tonic-gate 		 * OBP environment variable (idn-smr-size)
6320Sstevel@tonic-gate 		 * was not set.
6330Sstevel@tonic-gate 		 */
6340Sstevel@tonic-gate 		if (sip == NULL)
6350Sstevel@tonic-gate 			return (DDI_FAILURE);
6360Sstevel@tonic-gate 		/*
6370Sstevel@tonic-gate 		 * RESUME IDN services.
6380Sstevel@tonic-gate 		 */
6390Sstevel@tonic-gate 		IDN_GLOCK_SHARED();
6400Sstevel@tonic-gate 		if (idn.state != IDNGS_OFFLINE) {
6410Sstevel@tonic-gate 			cmn_err(CE_WARN,
6427656SSherry.Moore@Sun.COM 			    "IDN: 101: not in expected OFFLINE state "
6437656SSherry.Moore@Sun.COM 			    "for DDI_RESUME");
6440Sstevel@tonic-gate 			ASSERT(0);
6450Sstevel@tonic-gate 		}
6460Sstevel@tonic-gate 		IDN_GUNLOCK();
6470Sstevel@tonic-gate 
6480Sstevel@tonic-gate 		/*
6490Sstevel@tonic-gate 		 * RESUME DLPI services.
6500Sstevel@tonic-gate 		 */
6510Sstevel@tonic-gate 		sip->si_flags &= ~IDNSUSPENDED;
6520Sstevel@tonic-gate 
6530Sstevel@tonic-gate 		rw_enter(&idn.struprwlock, RW_READER);
6540Sstevel@tonic-gate 		for (stp = idn.strup; stp; stp = stp->ss_nextp)
6550Sstevel@tonic-gate 			if (stp->ss_sip == sip) {
6560Sstevel@tonic-gate 				doinit = 1;
6570Sstevel@tonic-gate 				break;
6580Sstevel@tonic-gate 			}
6590Sstevel@tonic-gate 		rw_exit(&idn.struprwlock);
6600Sstevel@tonic-gate 		if (doinit)
6610Sstevel@tonic-gate 			(void) idndl_init(sip);
6620Sstevel@tonic-gate 
6630Sstevel@tonic-gate 		return (DDI_SUCCESS);
6640Sstevel@tonic-gate 
6650Sstevel@tonic-gate 	case DDI_ATTACH:
6660Sstevel@tonic-gate 		break;
6670Sstevel@tonic-gate 
6680Sstevel@tonic-gate 	default:
6690Sstevel@tonic-gate 		return (DDI_FAILURE);
6700Sstevel@tonic-gate 	}
6710Sstevel@tonic-gate 
6720Sstevel@tonic-gate 	instance = ddi_get_instance(dip);
6730Sstevel@tonic-gate 
6740Sstevel@tonic-gate 	PR_DRV("%s: instance = %d\n", proc, instance);
6750Sstevel@tonic-gate 
6760Sstevel@tonic-gate 	if (idn_check_conf(dip, &bcpuid) == IDN_GPROPS_ERROR)
6770Sstevel@tonic-gate 		return (DDI_FAILURE);
6780Sstevel@tonic-gate 
6790Sstevel@tonic-gate 	mutex_enter(&idn.siplock);
6800Sstevel@tonic-gate 
6810Sstevel@tonic-gate 	if (ddi_create_minor_node(dip, IDNNAME, S_IFCHR, instance,
6827656SSherry.Moore@Sun.COM 	    DDI_NT_NET, CLONE_DEV) == DDI_FAILURE) {
6830Sstevel@tonic-gate 		mutex_exit(&idn.siplock);
6840Sstevel@tonic-gate 		return (DDI_FAILURE);
6850Sstevel@tonic-gate 	}
6860Sstevel@tonic-gate 
6870Sstevel@tonic-gate 	if (idn.smr.ready == 0) {
6880Sstevel@tonic-gate 		if (idn_init_smr() == 0) {
6890Sstevel@tonic-gate 			idn.enabled = 1;
6900Sstevel@tonic-gate #ifdef DEBUG
6910Sstevel@tonic-gate 			cmn_err(CE_NOTE, "!IDN: Driver enabled");
6920Sstevel@tonic-gate #endif /* DEBUG */
6930Sstevel@tonic-gate 		} else {
6940Sstevel@tonic-gate 			cmn_err(CE_NOTE,
6957656SSherry.Moore@Sun.COM 			    "!IDN: 102: driver disabled "
6967656SSherry.Moore@Sun.COM 			    "- check OBP environment "
6977656SSherry.Moore@Sun.COM 			    "(idn-smr-size)");
6980Sstevel@tonic-gate 			mutex_exit(&idn.siplock);
6990Sstevel@tonic-gate 			return (DDI_SUCCESS);
7000Sstevel@tonic-gate 		}
7010Sstevel@tonic-gate 	}
7020Sstevel@tonic-gate 
7030Sstevel@tonic-gate 	ASSERT(idn.smr.ready || idn.enabled);
7040Sstevel@tonic-gate 
7050Sstevel@tonic-gate 	if (idn.dip == NULL) {
7060Sstevel@tonic-gate 		doinit = 1;
7070Sstevel@tonic-gate 
7080Sstevel@tonic-gate 		if (idn_size_check()) {
7090Sstevel@tonic-gate 			idn_deinit_smr();
7100Sstevel@tonic-gate 			ddi_remove_minor_node(dip, NULL);
7110Sstevel@tonic-gate 			mutex_exit(&idn.siplock);
7120Sstevel@tonic-gate 			return (DDI_FAILURE);
7130Sstevel@tonic-gate 		}
7140Sstevel@tonic-gate 
7150Sstevel@tonic-gate 		if (idn_init(dip)) {
7160Sstevel@tonic-gate 			idn_deinit_smr();
7170Sstevel@tonic-gate 			ddi_remove_minor_node(dip, NULL);
7180Sstevel@tonic-gate 			mutex_exit(&idn.siplock);
7190Sstevel@tonic-gate 			return (DDI_FAILURE);
7200Sstevel@tonic-gate 		}
7210Sstevel@tonic-gate 	}
7220Sstevel@tonic-gate 
7230Sstevel@tonic-gate 	ASSERT(idn.dip);
7240Sstevel@tonic-gate 
7250Sstevel@tonic-gate 	/*
7260Sstevel@tonic-gate 	 * This must occur _after_ idn_init() since
7270Sstevel@tonic-gate 	 * it assumes idn_chanservers_init() has been
7280Sstevel@tonic-gate 	 * called.
7290Sstevel@tonic-gate 	 */
7300Sstevel@tonic-gate 	idn_chanserver_bind(ddi_get_instance(dip), bcpuid);
7310Sstevel@tonic-gate 
7320Sstevel@tonic-gate 	/*
7330Sstevel@tonic-gate 	 * DLPI supporting stuff.
7340Sstevel@tonic-gate 	 */
7350Sstevel@tonic-gate 	sip = GETSTRUCT(struct idn, 1);
7360Sstevel@tonic-gate 	sip->si_dip = dip;
7370Sstevel@tonic-gate 	ddi_set_driver_private(dip, sip);
7380Sstevel@tonic-gate 	sip->si_nextp = idn.sip;
7390Sstevel@tonic-gate 	idn.sip = sip;
7400Sstevel@tonic-gate 	IDN_SET_INST2SIP(instance, sip);
7410Sstevel@tonic-gate 	mutex_exit(&idn.siplock);
7420Sstevel@tonic-gate 
7430Sstevel@tonic-gate 	if (doinit)
7440Sstevel@tonic-gate 		idndl_dlpi_init();	/* initializes idninfoack */
7450Sstevel@tonic-gate 	/*
7460Sstevel@tonic-gate 	 * Get our local IDN ethernet address.
7470Sstevel@tonic-gate 	 */
7480Sstevel@tonic-gate 	idndl_localetheraddr(sip, &sip->si_ouraddr);
7490Sstevel@tonic-gate 	idndl_statinit(sip);
7500Sstevel@tonic-gate 
7510Sstevel@tonic-gate 	if (doinit) {
7520Sstevel@tonic-gate 		idn_gkstat_init();
7530Sstevel@tonic-gate 		/*
7540Sstevel@tonic-gate 		 * Add our sigblock SSP interrupt handler.
7550Sstevel@tonic-gate 		 */
7560Sstevel@tonic-gate 		mutex_enter(&idn.sigbintr.sb_mutex);
7570Sstevel@tonic-gate 		idn_sigbhandler_create();
7580Sstevel@tonic-gate 		mutex_exit(&idn.sigbintr.sb_mutex);
7590Sstevel@tonic-gate 
7600Sstevel@tonic-gate 		if (sgnblk_poll_register(idn_sigbhandler) == 0) {
7610Sstevel@tonic-gate 			mutex_enter(&idn.sigbintr.sb_mutex);
7620Sstevel@tonic-gate 			idn_sigbhandler_kill();
7630Sstevel@tonic-gate 			idn.sigbintr.sb_cpuid = (uchar_t)-1;
7640Sstevel@tonic-gate 			idn.sigbintr.sb_busy = IDNSIGB_INACTIVE;
7650Sstevel@tonic-gate 			mutex_exit(&idn.sigbintr.sb_mutex);
7660Sstevel@tonic-gate 
7670Sstevel@tonic-gate 			idn_gkstat_deinit();
7680Sstevel@tonic-gate 
7690Sstevel@tonic-gate 			mutex_enter(&idn.siplock);
7700Sstevel@tonic-gate 			(void) idn_deinit();
7710Sstevel@tonic-gate 			IDN_SET_INST2SIP(instance, NULL);
7720Sstevel@tonic-gate 			idn.sip = sip->si_nextp;
7730Sstevel@tonic-gate 			mutex_exit(&idn.siplock);
7740Sstevel@tonic-gate 
7750Sstevel@tonic-gate 			ddi_remove_minor_node(dip, NULL);
7760Sstevel@tonic-gate 
7770Sstevel@tonic-gate 			return (DDI_FAILURE);
7780Sstevel@tonic-gate 		}
7790Sstevel@tonic-gate 		/*
7800Sstevel@tonic-gate 		 * We require sigblkp[cpu0] to be mapped for hardware
7810Sstevel@tonic-gate 		 * configuration determination and also auto-linking
7820Sstevel@tonic-gate 		 * on bootup.
7830Sstevel@tonic-gate 		 */
7840Sstevel@tonic-gate 		if (sgnblk_poll_reference(idn_sigb_setup, NULL) != 0) {
785*11311SSurya.Prakki@Sun.COM 			(void) sgnblk_poll_unregister(idn_sigbhandler);
7860Sstevel@tonic-gate 			mutex_enter(&idn.sigbintr.sb_mutex);
7870Sstevel@tonic-gate 			idn_sigbhandler_kill();
7880Sstevel@tonic-gate 			idn.sigbintr.sb_cpuid = (uchar_t)-1;
7890Sstevel@tonic-gate 			idn.sigbintr.sb_busy = IDNSIGB_INACTIVE;
7900Sstevel@tonic-gate 			mutex_exit(&idn.sigbintr.sb_mutex);
7910Sstevel@tonic-gate 
7920Sstevel@tonic-gate 			idn_gkstat_deinit();
7930Sstevel@tonic-gate 
7940Sstevel@tonic-gate 			mutex_enter(&idn.siplock);
7950Sstevel@tonic-gate 			(void) idn_deinit();
7960Sstevel@tonic-gate 			IDN_SET_INST2SIP(instance, NULL);
7970Sstevel@tonic-gate 			idn.sip = sip->si_nextp;
7980Sstevel@tonic-gate 			mutex_exit(&idn.siplock);
7990Sstevel@tonic-gate 
8000Sstevel@tonic-gate 			ddi_remove_minor_node(dip, NULL);
8010Sstevel@tonic-gate 
8020Sstevel@tonic-gate 			cmn_err(CE_WARN,
8037656SSherry.Moore@Sun.COM 			    "IDN: 103: unable to reference sigblock area");
8040Sstevel@tonic-gate 
8050Sstevel@tonic-gate 			return (DDI_FAILURE);
8060Sstevel@tonic-gate 		}
8070Sstevel@tonic-gate 
8080Sstevel@tonic-gate 		idn_init_autolink();
8090Sstevel@tonic-gate 	}
8100Sstevel@tonic-gate 
8110Sstevel@tonic-gate 	ddi_report_dev(dip);
8120Sstevel@tonic-gate 
8130Sstevel@tonic-gate 	return (DDI_SUCCESS);
8140Sstevel@tonic-gate }
8150Sstevel@tonic-gate 
8160Sstevel@tonic-gate /*
8170Sstevel@tonic-gate  * ----------------------------------------------
8180Sstevel@tonic-gate  */
8190Sstevel@tonic-gate static int
idndetach(dev_info_t * dip,ddi_detach_cmd_t cmd)8200Sstevel@tonic-gate idndetach(dev_info_t *dip, ddi_detach_cmd_t cmd)
8210Sstevel@tonic-gate {
8220Sstevel@tonic-gate 	int		err = 0;
8230Sstevel@tonic-gate 	int		instance;
8240Sstevel@tonic-gate 	struct idn	*sip, *hsip, *tsip;
8250Sstevel@tonic-gate 	procname_t	proc = "idndetach";
8260Sstevel@tonic-gate 
8270Sstevel@tonic-gate 	sip = ddi_get_driver_private(dip);
8280Sstevel@tonic-gate 	instance = ddi_get_instance(dip);
8290Sstevel@tonic-gate 
8300Sstevel@tonic-gate 	switch (cmd) {
8310Sstevel@tonic-gate 	case DDI_SUSPEND:
8320Sstevel@tonic-gate 		if (sip == NULL)
8330Sstevel@tonic-gate 			return (DDI_FAILURE);
8340Sstevel@tonic-gate 		/*
8350Sstevel@tonic-gate 		 * SUSPEND IDN services.
8360Sstevel@tonic-gate 		 * - Actually don't suspend anything, we just
8370Sstevel@tonic-gate 		 *   make sure we're not connected per DR protocol.
8380Sstevel@tonic-gate 		 *   If we really wanted to suspend it should
8390Sstevel@tonic-gate 		 *   be done _after_ DLPI is suspended so that
8400Sstevel@tonic-gate 		 *   we're not competing with that traffic.
8410Sstevel@tonic-gate 		 */
8420Sstevel@tonic-gate 		IDN_GLOCK_SHARED();
8430Sstevel@tonic-gate 
8440Sstevel@tonic-gate 		if (idn.state != IDNGS_OFFLINE) {
8450Sstevel@tonic-gate 			int	d;
8460Sstevel@tonic-gate 
8470Sstevel@tonic-gate 			cmn_err(CE_WARN,
8487656SSherry.Moore@Sun.COM 			    "IDN: 104: cannot suspend while active "
8497656SSherry.Moore@Sun.COM 			    "(state = %s)",
8507656SSherry.Moore@Sun.COM 			    idngs_str[idn.state]);
8510Sstevel@tonic-gate 
8520Sstevel@tonic-gate 			for (d = 0; d < MAX_DOMAINS; d++) {
8530Sstevel@tonic-gate 				idn_domain_t	*dp;
8540Sstevel@tonic-gate 
8550Sstevel@tonic-gate 				dp = &idn_domain[d];
8560Sstevel@tonic-gate 				if (dp->dcpu < 0)
8570Sstevel@tonic-gate 					continue;
8580Sstevel@tonic-gate 
8590Sstevel@tonic-gate 				cmn_err(CE_CONT,
8607656SSherry.Moore@Sun.COM 				    "IDN: 121: domain %d (CPU %d, name "
8617656SSherry.Moore@Sun.COM 				    "\"%s\", state %s)\n",
8627656SSherry.Moore@Sun.COM 				    d, dp->dcpu, dp->dname,
8637656SSherry.Moore@Sun.COM 				    idnds_str[dp->dstate]);
8640Sstevel@tonic-gate 			}
8650Sstevel@tonic-gate 			err = 1;
8660Sstevel@tonic-gate 		}
8670Sstevel@tonic-gate 
8680Sstevel@tonic-gate 		IDN_GUNLOCK();
8690Sstevel@tonic-gate 
8700Sstevel@tonic-gate 		if (err)
8710Sstevel@tonic-gate 			return (DDI_FAILURE);
8720Sstevel@tonic-gate 		/*
8730Sstevel@tonic-gate 		 * SUSPEND DLPI services.
8740Sstevel@tonic-gate 		 */
8750Sstevel@tonic-gate 		sip->si_flags |= IDNSUSPENDED;
8760Sstevel@tonic-gate 
8770Sstevel@tonic-gate 		idndl_uninit(sip);
8780Sstevel@tonic-gate 
8790Sstevel@tonic-gate 		return (DDI_FAILURE);
8800Sstevel@tonic-gate 
8810Sstevel@tonic-gate 	case DDI_DETACH:
8820Sstevel@tonic-gate 		if (idn.enabled == 0) {
8830Sstevel@tonic-gate 			ddi_remove_minor_node(dip, NULL);
8840Sstevel@tonic-gate 			ASSERT(idn.dip == NULL);
8850Sstevel@tonic-gate 			return (DDI_SUCCESS);
8860Sstevel@tonic-gate 		}
8870Sstevel@tonic-gate 		if (!IDN_MODUNLOADABLE)
8880Sstevel@tonic-gate 			return (DDI_FAILURE);
8890Sstevel@tonic-gate 		break;
8900Sstevel@tonic-gate 
8910Sstevel@tonic-gate 	default:
8920Sstevel@tonic-gate 		return (DDI_FAILURE);
8930Sstevel@tonic-gate 	}
8940Sstevel@tonic-gate 
8950Sstevel@tonic-gate 	PR_DRV("%s: instance = %d\n", proc, instance);
8960Sstevel@tonic-gate 
8970Sstevel@tonic-gate 	if (sip == NULL) {
8980Sstevel@tonic-gate 		/*
8990Sstevel@tonic-gate 		 * No resources allocated.
9000Sstevel@tonic-gate 		 */
9010Sstevel@tonic-gate 		return (DDI_SUCCESS);
9020Sstevel@tonic-gate 	}
9030Sstevel@tonic-gate 
9040Sstevel@tonic-gate 	mutex_enter(&idn.siplock);
9050Sstevel@tonic-gate 	if (idn.sip && (idn.sip->si_nextp == NULL)) {
9060Sstevel@tonic-gate 		/*
9070Sstevel@tonic-gate 		 * This is our last stream connection
9080Sstevel@tonic-gate 		 * going away.  Time to deinit and flag
9090Sstevel@tonic-gate 		 * the SSP we're (IDN) DOWN.
9100Sstevel@tonic-gate 		 */
9110Sstevel@tonic-gate 		if (idn_deinit()) {
9120Sstevel@tonic-gate 			/*
9130Sstevel@tonic-gate 			 * Must still be active.
9140Sstevel@tonic-gate 			 */
9150Sstevel@tonic-gate 			mutex_exit(&idn.siplock);
9160Sstevel@tonic-gate 			return (DDI_FAILURE);
9170Sstevel@tonic-gate 		}
9180Sstevel@tonic-gate 		idn_deinit_autolink();
9190Sstevel@tonic-gate 		/*
9200Sstevel@tonic-gate 		 * Remove our sigblock SSP interrupt handler.
9210Sstevel@tonic-gate 		 */
922*11311SSurya.Prakki@Sun.COM 		(void) sgnblk_poll_unregister(idn_sigbhandler);
9230Sstevel@tonic-gate 		mutex_enter(&idn.sigbintr.sb_mutex);
9240Sstevel@tonic-gate 		idn_sigbhandler_kill();
9250Sstevel@tonic-gate 		idn.sigbintr.sb_cpuid = (uchar_t)-1;
9260Sstevel@tonic-gate 		idn.sigbintr.sb_busy = IDNSIGB_NOTREADY;
9270Sstevel@tonic-gate 		mutex_exit(&idn.sigbintr.sb_mutex);
9280Sstevel@tonic-gate 		/*
9290Sstevel@tonic-gate 		 * Remove our reference to the sigblock area.
9300Sstevel@tonic-gate 		 */
9310Sstevel@tonic-gate 		sgnblk_poll_unreference(idn_sigb_setup);
9320Sstevel@tonic-gate 		idn_gkstat_deinit();
9330Sstevel@tonic-gate 	}
9340Sstevel@tonic-gate 
9350Sstevel@tonic-gate 	ddi_remove_minor_node(dip, NULL);
9360Sstevel@tonic-gate 
9370Sstevel@tonic-gate 	/*
9380Sstevel@tonic-gate 	 * Remove this instance from our linked list.
9390Sstevel@tonic-gate 	 */
9400Sstevel@tonic-gate 	IDN_SET_INST2SIP(instance, NULL);
9410Sstevel@tonic-gate 	if ((hsip = tsip = idn.sip) == sip) {
9420Sstevel@tonic-gate 		idn.sip = sip->si_nextp;
9430Sstevel@tonic-gate 	} else {
9440Sstevel@tonic-gate 		for (; hsip && (sip != hsip); tsip = hsip,
9457656SSherry.Moore@Sun.COM 		    hsip = hsip->si_nextp)
9460Sstevel@tonic-gate 			;
9470Sstevel@tonic-gate 		if (hsip)
9480Sstevel@tonic-gate 			tsip->si_nextp = hsip->si_nextp;
9490Sstevel@tonic-gate 	}
9500Sstevel@tonic-gate 	mutex_exit(&idn.siplock);
9510Sstevel@tonic-gate 	if (sip->si_ksp)
9520Sstevel@tonic-gate 		kstat_delete(sip->si_ksp);
9530Sstevel@tonic-gate 
9540Sstevel@tonic-gate 	ddi_set_driver_private(dip, NULL);
9550Sstevel@tonic-gate 
9560Sstevel@tonic-gate 	FREESTRUCT(sip, struct idn, 1);
9570Sstevel@tonic-gate 
9580Sstevel@tonic-gate 	return (DDI_SUCCESS);
9590Sstevel@tonic-gate }
9600Sstevel@tonic-gate 
9610Sstevel@tonic-gate /*
9620Sstevel@tonic-gate  * ----------------------------------------------
9630Sstevel@tonic-gate  */
9640Sstevel@tonic-gate static idn_gprops_t
idn_check_conf(dev_info_t * dip,processorid_t * cpuid)9650Sstevel@tonic-gate idn_check_conf(dev_info_t *dip, processorid_t *cpuid)
9660Sstevel@tonic-gate {
9670Sstevel@tonic-gate 	static idn_gprops_t	global_props = IDN_GPROPS_UNCHECKED;
9680Sstevel@tonic-gate 
9690Sstevel@tonic-gate 	if (global_props == IDN_GPROPS_UNCHECKED) {
9700Sstevel@tonic-gate 		int		p;
9710Sstevel@tonic-gate 
9720Sstevel@tonic-gate 		global_props = IDN_GPROPS_OKAY;
9730Sstevel@tonic-gate 
9740Sstevel@tonic-gate 		for (p = 0; idn_global_props[p].p_string; p++) {
9750Sstevel@tonic-gate 			char	*str;
9760Sstevel@tonic-gate 			int	*var;
9770Sstevel@tonic-gate 			int	val, v_min, v_max, v_def;
9780Sstevel@tonic-gate 
9790Sstevel@tonic-gate 			str = idn_global_props[p].p_string;
9800Sstevel@tonic-gate 			var = (int *)idn_global_props[p].p_var;
9810Sstevel@tonic-gate 			v_min = idn_global_props[p].p_min;
9820Sstevel@tonic-gate 			v_max = idn_global_props[p].p_max;
9830Sstevel@tonic-gate 			v_def = idn_global_props[p].p_def;
9840Sstevel@tonic-gate 			ASSERT(str && var);
9850Sstevel@tonic-gate 
9860Sstevel@tonic-gate 			val = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
9877656SSherry.Moore@Sun.COM 			    DDI_PROP_DONTPASS |
9887656SSherry.Moore@Sun.COM 			    DDI_PROP_NOTPROM,
9897656SSherry.Moore@Sun.COM 			    str, v_def);
9900Sstevel@tonic-gate 			if ((v_min != v_max) &&
9917656SSherry.Moore@Sun.COM 			    ((val < v_min) || (val > v_max))) {
9920Sstevel@tonic-gate 				cmn_err(CE_WARN,
9937656SSherry.Moore@Sun.COM 				    "IDN: 105: driver parameter "
9947656SSherry.Moore@Sun.COM 				    "(%s) specified (%d) out of "
9957656SSherry.Moore@Sun.COM 				    "range [%d - %d]",
9967656SSherry.Moore@Sun.COM 				    str, val, v_min, v_max);
9970Sstevel@tonic-gate 				global_props = IDN_GPROPS_ERROR;
9980Sstevel@tonic-gate 			} else {
9990Sstevel@tonic-gate 				*var = val;
10000Sstevel@tonic-gate 			}
10010Sstevel@tonic-gate 		}
10020Sstevel@tonic-gate 	}
10030Sstevel@tonic-gate 
10040Sstevel@tonic-gate 	*cpuid = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
10057656SSherry.Moore@Sun.COM 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
10067656SSherry.Moore@Sun.COM 	    "bind_cpu", -1);
10070Sstevel@tonic-gate 
10080Sstevel@tonic-gate 	return (global_props);
10090Sstevel@tonic-gate }
10100Sstevel@tonic-gate 
10110Sstevel@tonic-gate static int
idn_size_check()10120Sstevel@tonic-gate idn_size_check()
10130Sstevel@tonic-gate {
10140Sstevel@tonic-gate 	int		i, cnt;
10150Sstevel@tonic-gate 	int		rv = 0;
10160Sstevel@tonic-gate 	ulong_t		mboxareasize;
10170Sstevel@tonic-gate 	int		max_num_slabs;
10180Sstevel@tonic-gate 	procname_t	proc = "idn_size_check";
10190Sstevel@tonic-gate 
10200Sstevel@tonic-gate 	if (IDN_NWR_SIZE == 0)
10210Sstevel@tonic-gate 		IDN_NWR_SIZE = IDN_SMR_SIZE;
10220Sstevel@tonic-gate 
10230Sstevel@tonic-gate 	if (IDN_NWR_SIZE > IDN_SMR_SIZE) {
10240Sstevel@tonic-gate 		cmn_err(CE_WARN,
10257656SSherry.Moore@Sun.COM 		    "IDN: 106: idn_nwr_size(%d) > idn_smr_size(%d)"
10267656SSherry.Moore@Sun.COM 		    " - Limiting to %d MB",
10277656SSherry.Moore@Sun.COM 		    IDN_NWR_SIZE, IDN_SMR_SIZE, IDN_SMR_SIZE);
10280Sstevel@tonic-gate 		IDN_NWR_SIZE = IDN_SMR_SIZE;
10290Sstevel@tonic-gate 	}
10300Sstevel@tonic-gate 
10310Sstevel@tonic-gate 	if (MB2B(IDN_NWR_SIZE) < IDN_SLAB_SIZE) {
10320Sstevel@tonic-gate 		cmn_err(CE_WARN,
10337656SSherry.Moore@Sun.COM 		    "IDN: 107: memory region(%lu) < slab size(%u)",
10347656SSherry.Moore@Sun.COM 		    MB2B(IDN_NWR_SIZE), IDN_SLAB_SIZE);
10350Sstevel@tonic-gate 		rv = -1;
10360Sstevel@tonic-gate 	}
10370Sstevel@tonic-gate 
10380Sstevel@tonic-gate 	if (IDN_LOWAT >= IDN_HIWAT) {
10390Sstevel@tonic-gate 		cmn_err(CE_WARN,
10407656SSherry.Moore@Sun.COM 		    "IDN: 108: idn_lowat(%d) >= idn_hiwat(%d)",
10417656SSherry.Moore@Sun.COM 		    IDN_LOWAT, IDN_HIWAT);
10420Sstevel@tonic-gate 		rv = -1;
10430Sstevel@tonic-gate 	}
10440Sstevel@tonic-gate 
10450Sstevel@tonic-gate 	mboxareasize = (ulong_t)(IDN_MBOXAREA_SIZE + (IDN_SMR_BUFSIZE - 1));
10460Sstevel@tonic-gate 	mboxareasize &= ~((ulong_t)IDN_SMR_BUFSIZE - 1);
10470Sstevel@tonic-gate #ifdef DEBUG
10480Sstevel@tonic-gate 	if ((ulong_t)IDN_SLAB_SIZE < mboxareasize) {
1049931Smathue 		PR_DRV("%s: slab size(%d) < mailbox area(%ld)",
10507656SSherry.Moore@Sun.COM 		    proc, IDN_SLAB_SIZE, mboxareasize);
10510Sstevel@tonic-gate 		/* not fatal */
10520Sstevel@tonic-gate 	}
10530Sstevel@tonic-gate #endif /* DEBUG */
10540Sstevel@tonic-gate 
10550Sstevel@tonic-gate 	if ((mboxareasize + (ulong_t)IDN_SLAB_SIZE) > MB2B(IDN_NWR_SIZE)) {
10560Sstevel@tonic-gate 		cmn_err(CE_WARN,
10577656SSherry.Moore@Sun.COM 		    "IDN: 109: mailbox area(%lu) + slab size(%u) "
10587656SSherry.Moore@Sun.COM 		    "> nwr region(%lu)",
10597656SSherry.Moore@Sun.COM 		    mboxareasize, IDN_SLAB_SIZE,
10607656SSherry.Moore@Sun.COM 		    MB2B(IDN_NWR_SIZE));
10610Sstevel@tonic-gate 		rv = -1;
10620Sstevel@tonic-gate 	}
10630Sstevel@tonic-gate 
10640Sstevel@tonic-gate 	max_num_slabs = (int)((MB2B(IDN_NWR_SIZE) - mboxareasize) /
10657656SSherry.Moore@Sun.COM 	    (ulong_t)IDN_SLAB_SIZE);
10660Sstevel@tonic-gate 	if (max_num_slabs < IDN_SLAB_MINTOTAL) {
10670Sstevel@tonic-gate 		cmn_err(CE_WARN,
10687656SSherry.Moore@Sun.COM 		    "IDN: 110: maximum number of slabs(%d) < "
10697656SSherry.Moore@Sun.COM 		    "minimum required(%d)",
10707656SSherry.Moore@Sun.COM 		    max_num_slabs, IDN_SLAB_MINTOTAL);
10710Sstevel@tonic-gate 		rv = -1;
10720Sstevel@tonic-gate 	} else {
10730Sstevel@tonic-gate 		IDN_SLAB_MAXPERDOMAIN = max_num_slabs / IDN_SLAB_MINTOTAL;
10740Sstevel@tonic-gate 	}
10750Sstevel@tonic-gate 
10760Sstevel@tonic-gate #if 0
10770Sstevel@tonic-gate 	if ((IDN_MTU + sizeof (struct ether_header)) > IDN_DATA_SIZE) {
10780Sstevel@tonic-gate 		cmn_err(CE_WARN,
10797656SSherry.Moore@Sun.COM 		    "IDN: (IDN_MTU(%d) + ether_header(%d)) "
10807656SSherry.Moore@Sun.COM 		    "> IDN_DATA_SIZE(%lu)",
10817656SSherry.Moore@Sun.COM 		    IDN_MTU, sizeof (struct ether_header),
10827656SSherry.Moore@Sun.COM 		    IDN_DATA_SIZE);
10830Sstevel@tonic-gate 		rv = -1;
10840Sstevel@tonic-gate 	}
10850Sstevel@tonic-gate #endif /* 0 */
10860Sstevel@tonic-gate 
10870Sstevel@tonic-gate 	if (IDN_SMR_BUFSIZE & (IDN_ALIGNSIZE - 1)) {
10880Sstevel@tonic-gate 		cmn_err(CE_WARN,
10897656SSherry.Moore@Sun.COM 		    "IDN: 111: idn_smr_bufsize(%d) not on a "
10907656SSherry.Moore@Sun.COM 		    "64 byte boundary", IDN_SMR_BUFSIZE);
10910Sstevel@tonic-gate 		rv = -1;
10920Sstevel@tonic-gate 	}
10930Sstevel@tonic-gate 
10940Sstevel@tonic-gate 	for (i = cnt = 0;
10957656SSherry.Moore@Sun.COM 	    (cnt <= 1) && (((ulong_t)1 << i) < MB2B(IDN_NWR_SIZE));
10967656SSherry.Moore@Sun.COM 	    i++)
10970Sstevel@tonic-gate 		if ((1 << i) & IDN_SMR_BUFSIZE)
10980Sstevel@tonic-gate 			cnt++;
10990Sstevel@tonic-gate 	if ((i > 0) && (!cnt || (cnt > 1))) {
11000Sstevel@tonic-gate 		cmn_err(CE_WARN,
11017656SSherry.Moore@Sun.COM 		    "IDN: 112: idn_smr_bufsize(%d) not a power of 2",
11027656SSherry.Moore@Sun.COM 		    IDN_SMR_BUFSIZE);
11030Sstevel@tonic-gate 		rv = -1;
11040Sstevel@tonic-gate 	}
11050Sstevel@tonic-gate 
11060Sstevel@tonic-gate 	if ((IDN_MBOX_PER_NET & 1) == 0) {
11070Sstevel@tonic-gate 		cmn_err(CE_WARN,
11087656SSherry.Moore@Sun.COM 		    "IDN: 113: idn_mbox_per_net(%d) must be an "
11097656SSherry.Moore@Sun.COM 		    "odd number", IDN_MBOX_PER_NET);
11100Sstevel@tonic-gate 		rv = -1;
11110Sstevel@tonic-gate 	}
11120Sstevel@tonic-gate 
11130Sstevel@tonic-gate 	if (idn.nchannels > 0)
11140Sstevel@tonic-gate 		IDN_WINDOW_EMAX = IDN_WINDOW_MAX +
11157656SSherry.Moore@Sun.COM 		    ((idn.nchannels - 1) * IDN_WINDOW_INCR);
11160Sstevel@tonic-gate 
11170Sstevel@tonic-gate 	if (IDN_NETSVR_WAIT_MIN > IDN_NETSVR_WAIT_MAX) {
11180Sstevel@tonic-gate 		cmn_err(CE_WARN,
11197656SSherry.Moore@Sun.COM 		    "IDN: 115: idn_netsvr_wait_min(%d) cannot be "
11207656SSherry.Moore@Sun.COM 		    "greater than idn_netsvr_wait_max(%d)",
11217656SSherry.Moore@Sun.COM 		    IDN_NETSVR_WAIT_MIN,
11227656SSherry.Moore@Sun.COM 		    IDN_NETSVR_WAIT_MAX);
11230Sstevel@tonic-gate 		rv = -1;
11240Sstevel@tonic-gate 	}
11250Sstevel@tonic-gate 
11260Sstevel@tonic-gate 	return (rv);
11270Sstevel@tonic-gate }
11280Sstevel@tonic-gate 
11290Sstevel@tonic-gate static int
idn_init_smr()11300Sstevel@tonic-gate idn_init_smr()
11310Sstevel@tonic-gate {
11320Sstevel@tonic-gate 	uint64_t	obp_paddr;
11330Sstevel@tonic-gate 	uint64_t	obp_size;	/* in Bytes */
11340Sstevel@tonic-gate 	uint_t		smr_size;	/* in MBytes */
11350Sstevel@tonic-gate 	pgcnt_t		npages;
11360Sstevel@tonic-gate 	procname_t	proc = "idn_init_smr";
11370Sstevel@tonic-gate 
11380Sstevel@tonic-gate 	if (idn.smr.ready)
11390Sstevel@tonic-gate 		return (0);
11400Sstevel@tonic-gate 
11410Sstevel@tonic-gate 	if (idn_prom_getsmr(&smr_size, &obp_paddr, &obp_size) < 0)
11420Sstevel@tonic-gate 		return (-1);
11430Sstevel@tonic-gate 
1144931Smathue 	PR_PROTO("%s: smr_size = %d, obp_paddr = 0x%lx, obp_size = 0x%lx\n",
11457656SSherry.Moore@Sun.COM 	    proc, smr_size, obp_paddr, obp_size);
11460Sstevel@tonic-gate 
11470Sstevel@tonic-gate 	if (IDN_SMR_SIZE)
11480Sstevel@tonic-gate 		smr_size = MIN(smr_size, IDN_SMR_SIZE);
11490Sstevel@tonic-gate 
11500Sstevel@tonic-gate 	npages = btopr(MB2B(smr_size));
11510Sstevel@tonic-gate 
11520Sstevel@tonic-gate 	idn.smr.prom_paddr = obp_paddr;
11530Sstevel@tonic-gate 	idn.smr.prom_size = obp_size;
11540Sstevel@tonic-gate 	idn.smr.vaddr = vmem_alloc(heap_arena, ptob(npages), VM_SLEEP);
11550Sstevel@tonic-gate 	ASSERT(((ulong_t)idn.smr.vaddr & MMU_PAGEOFFSET) == 0);
11560Sstevel@tonic-gate 	idn.smr.locpfn = (pfn_t)(obp_paddr >> MMU_PAGESHIFT);
11570Sstevel@tonic-gate 	idn.smr.rempfn = idn.smr.rempfnlim = PFN_INVALID;
11580Sstevel@tonic-gate 	IDN_SMR_SIZE = smr_size;
11590Sstevel@tonic-gate 
1160*11311SSurya.Prakki@Sun.COM 	PR_PROTO("%s: smr vaddr = %p\n", proc, (void *)idn.smr.vaddr);
11610Sstevel@tonic-gate 
11620Sstevel@tonic-gate 	smr_remap(&kas, idn.smr.vaddr, idn.smr.locpfn, IDN_SMR_SIZE);
11630Sstevel@tonic-gate 
11640Sstevel@tonic-gate 	idn.localid = PADDR_TO_DOMAINID(obp_paddr);
11650Sstevel@tonic-gate 
11660Sstevel@tonic-gate 	idn.smr.ready = 1;
11670Sstevel@tonic-gate 
11680Sstevel@tonic-gate 	return (0);
11690Sstevel@tonic-gate }
11700Sstevel@tonic-gate 
11710Sstevel@tonic-gate static void
idn_deinit_smr()11720Sstevel@tonic-gate idn_deinit_smr()
11730Sstevel@tonic-gate {
11740Sstevel@tonic-gate 	pgcnt_t		npages;
11750Sstevel@tonic-gate 
11760Sstevel@tonic-gate 	if (idn.smr.ready == 0)
11770Sstevel@tonic-gate 		return;
11780Sstevel@tonic-gate 
11790Sstevel@tonic-gate 	smr_remap(&kas, idn.smr.vaddr, PFN_INVALID, IDN_SMR_SIZE);
11800Sstevel@tonic-gate 
11810Sstevel@tonic-gate 	npages = btopr(MB2B(IDN_SMR_SIZE));
11820Sstevel@tonic-gate 
11830Sstevel@tonic-gate 	vmem_free(heap_arena, idn.smr.vaddr, ptob(npages));
11840Sstevel@tonic-gate 
11850Sstevel@tonic-gate 	idn.localid = IDN_NIL_DOMID;
11860Sstevel@tonic-gate 
11870Sstevel@tonic-gate 	IDN_SMR_SIZE = 0;
11880Sstevel@tonic-gate 
11890Sstevel@tonic-gate 	idn.smr.ready = 0;
11900Sstevel@tonic-gate }
11910Sstevel@tonic-gate 
11920Sstevel@tonic-gate /*ARGSUSED1*/
11930Sstevel@tonic-gate static void
idn_sigb_setup(cpu_sgnblk_t * sigbp,void * arg)11940Sstevel@tonic-gate idn_sigb_setup(cpu_sgnblk_t *sigbp, void *arg)
11950Sstevel@tonic-gate {
11960Sstevel@tonic-gate 	procname_t	proc = "idn_sigb_setup";
11970Sstevel@tonic-gate 
1198*11311SSurya.Prakki@Sun.COM 	PR_PROTO("%s: Setting sigb to %p\n", proc, (void *)sigbp);
11990Sstevel@tonic-gate 
12000Sstevel@tonic-gate 	mutex_enter(&idn.idnsb_mutex);
12010Sstevel@tonic-gate 	if (sigbp == NULL) {
12020Sstevel@tonic-gate 		idn.idnsb = NULL;
12030Sstevel@tonic-gate 		idn.idnsb_eventp = NULL;
12040Sstevel@tonic-gate 		mutex_exit(&idn.idnsb_mutex);
12050Sstevel@tonic-gate 		return;
12060Sstevel@tonic-gate 	}
12070Sstevel@tonic-gate 	idn.idnsb_eventp = (idnsb_event_t *)sigbp->sigb_idn;
12080Sstevel@tonic-gate 	idn.idnsb = (idnsb_t *)&idn.idnsb_eventp->idn_reserved1;
12090Sstevel@tonic-gate 	mutex_exit(&idn.idnsb_mutex);
12100Sstevel@tonic-gate }
12110Sstevel@tonic-gate 
12120Sstevel@tonic-gate static int
idn_init(dev_info_t * dip)12130Sstevel@tonic-gate idn_init(dev_info_t *dip)
12140Sstevel@tonic-gate {
12150Sstevel@tonic-gate 	struct hwconfig	local_hw;
12160Sstevel@tonic-gate 	procname_t	proc = "idn_init";
12170Sstevel@tonic-gate 
12180Sstevel@tonic-gate 
12190Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&idn.siplock));
12200Sstevel@tonic-gate 
12210Sstevel@tonic-gate 	if (!idn.enabled) {
12220Sstevel@tonic-gate 		cmn_err(CE_WARN,
12237656SSherry.Moore@Sun.COM 		    "IDN: 117: IDN not enabled");
12240Sstevel@tonic-gate 		return (-1);
12250Sstevel@tonic-gate 	}
12260Sstevel@tonic-gate 
12270Sstevel@tonic-gate 	if (idn.dip != NULL) {
1228931Smathue 		PR_DRV("%s: already initialized (dip = 0x%p)\n",
1229*11311SSurya.Prakki@Sun.COM 		    proc, (void *)idn.dip);
12300Sstevel@tonic-gate 		return (0);
12310Sstevel@tonic-gate 	}
12320Sstevel@tonic-gate 
12330Sstevel@tonic-gate 	/*
12340Sstevel@tonic-gate 	 * Determine our local domain's hardware configuration.
12350Sstevel@tonic-gate 	 */
12360Sstevel@tonic-gate 	if (get_hw_config(&local_hw)) {
12370Sstevel@tonic-gate 		cmn_err(CE_WARN,
12387656SSherry.Moore@Sun.COM 		    "IDN: 118: hardware config not appropriate");
12390Sstevel@tonic-gate 		return (-1);
12400Sstevel@tonic-gate 	}
12410Sstevel@tonic-gate 
12420Sstevel@tonic-gate 	PR_DRV("%s: locpfn = 0x%lx\n", proc, idn.smr.locpfn);
12430Sstevel@tonic-gate 	PR_DRV("%s: rempfn = 0x%lx\n", proc, idn.smr.rempfn);
12440Sstevel@tonic-gate 	PR_DRV("%s: smrsize = %d MB\n", proc, IDN_SMR_SIZE);
12450Sstevel@tonic-gate 
12460Sstevel@tonic-gate 	rw_init(&idn.grwlock, NULL, RW_DEFAULT, NULL);
12470Sstevel@tonic-gate 	rw_init(&idn.struprwlock, NULL, RW_DEFAULT, NULL);
12480Sstevel@tonic-gate 	mutex_init(&idn.sync.sz_mutex, NULL, MUTEX_DEFAULT, NULL);
12490Sstevel@tonic-gate 	mutex_init(&idn.sipwenlock, NULL, MUTEX_DEFAULT, NULL);
12500Sstevel@tonic-gate 
12510Sstevel@tonic-gate 	/*
12520Sstevel@tonic-gate 	 * Calculate proper value for idn.bframe_shift.
12530Sstevel@tonic-gate 	 * Kind of hokey as it assume knowledge of the format
12540Sstevel@tonic-gate 	 * of the idnparam_t structure.
12550Sstevel@tonic-gate 	 */
12560Sstevel@tonic-gate 	{
12570Sstevel@tonic-gate 		int		s;
12580Sstevel@tonic-gate 
12590Sstevel@tonic-gate 		for (s = 0; (1 << s) < IDN_SMR_BUFSIZE_MIN; s++)
12600Sstevel@tonic-gate 			;
12610Sstevel@tonic-gate 		idn.bframe_shift = s;
1262931Smathue 		PR_DRV("%s: idn.bframe_shift = %d, minbuf = %d\n",
12637656SSherry.Moore@Sun.COM 		    proc, idn.bframe_shift, IDN_SMR_BUFSIZE_MIN);
12640Sstevel@tonic-gate 
12650Sstevel@tonic-gate 		ASSERT((uint_t)IDN_OFFSET2BFRAME(MB2B(idn_smr_size)) <
12667656SSherry.Moore@Sun.COM 		    (1 << 24));
12670Sstevel@tonic-gate 	}
12680Sstevel@tonic-gate 
12690Sstevel@tonic-gate 	idn_xmit_monitor_init();
12700Sstevel@tonic-gate 
12710Sstevel@tonic-gate 	/*
12720Sstevel@tonic-gate 	 * Initialize the domain op (dopers) stuff.
12730Sstevel@tonic-gate 	 */
12740Sstevel@tonic-gate 	idn_dopers_init();
12750Sstevel@tonic-gate 
12760Sstevel@tonic-gate 	/*
12770Sstevel@tonic-gate 	 * Initialize the timer (kmem) cache used for timeout
12780Sstevel@tonic-gate 	 * structures.
12790Sstevel@tonic-gate 	 */
12800Sstevel@tonic-gate 	idn_timercache_init();
12810Sstevel@tonic-gate 
12820Sstevel@tonic-gate 	/*
12830Sstevel@tonic-gate 	 * Initialize the slab waiting areas.
12840Sstevel@tonic-gate 	 */
12850Sstevel@tonic-gate 	(void) smr_slabwaiter_init();
12860Sstevel@tonic-gate 
12870Sstevel@tonic-gate 	/*
12880Sstevel@tonic-gate 	 * Initialize retryjob kmem cache.
12890Sstevel@tonic-gate 	 */
12900Sstevel@tonic-gate 	idn_retrytask_init();
12910Sstevel@tonic-gate 
12920Sstevel@tonic-gate 	idn_init_msg_waittime();
12930Sstevel@tonic-gate 	idn_init_msg_retrytime();
12940Sstevel@tonic-gate 
12950Sstevel@tonic-gate 	/*
12960Sstevel@tonic-gate 	 * Initialize idn_domains[] and local domains information
12970Sstevel@tonic-gate 	 * include idn_global information.
12980Sstevel@tonic-gate 	 */
12990Sstevel@tonic-gate 	idn_domains_init(&local_hw);
13000Sstevel@tonic-gate 
13010Sstevel@tonic-gate 	/*
13020Sstevel@tonic-gate 	 * Start up IDN protocol servers.
13030Sstevel@tonic-gate 	 */
13040Sstevel@tonic-gate 	if (idn_protocol_init(idn_protocol_nservers) <= 0) {
13050Sstevel@tonic-gate 		cmn_err(CE_WARN,
13067656SSherry.Moore@Sun.COM 		    "IDN: 119: failed to initialize %d protocol servers",
13077656SSherry.Moore@Sun.COM 		    idn_protocol_nservers);
13080Sstevel@tonic-gate 		idn_domains_deinit();
13090Sstevel@tonic-gate 		idn_retrytask_deinit();
13100Sstevel@tonic-gate 		smr_slabwaiter_deinit();
13110Sstevel@tonic-gate 		idn_timercache_deinit();
13120Sstevel@tonic-gate 		idn_dopers_deinit();
13130Sstevel@tonic-gate 		idn_xmit_monitor_deinit();
13140Sstevel@tonic-gate 		mutex_destroy(&idn.sipwenlock);
13150Sstevel@tonic-gate 		mutex_destroy(&idn.sync.sz_mutex);
13160Sstevel@tonic-gate 		rw_destroy(&idn.grwlock);
13170Sstevel@tonic-gate 		rw_destroy(&idn.struprwlock);
13180Sstevel@tonic-gate 		return (-1);
13190Sstevel@tonic-gate 	}
13200Sstevel@tonic-gate 
13210Sstevel@tonic-gate 	/*
13220Sstevel@tonic-gate 	 * Initialize chan_servers array.
13230Sstevel@tonic-gate 	 */
13240Sstevel@tonic-gate 	(void) idn_chanservers_init();
13250Sstevel@tonic-gate 
13260Sstevel@tonic-gate 	/*
13270Sstevel@tonic-gate 	 * Need to register the IDN handler with the DMV subsystem.
13280Sstevel@tonic-gate 	 *
13290Sstevel@tonic-gate 	 * Need to prevent the IDN driver from being unloaded
13300Sstevel@tonic-gate 	 * once loaded since DMV's may come in at any time.
13310Sstevel@tonic-gate 	 * If the driver is not loaded and the idn_dmv_handler
13320Sstevel@tonic-gate 	 * has been registered with the DMV, system will crash.
13330Sstevel@tonic-gate 	 */
13340Sstevel@tonic-gate 	(void) idn_init_handler();
13350Sstevel@tonic-gate 
13360Sstevel@tonic-gate 	idn.dip = dip;
13370Sstevel@tonic-gate 	IDN_GLOCK_EXCL();
13380Sstevel@tonic-gate 	IDN_GSTATE_TRANSITION(IDNGS_OFFLINE);
13390Sstevel@tonic-gate 	IDN_GUNLOCK();
13400Sstevel@tonic-gate 
13410Sstevel@tonic-gate 	return (0);
13420Sstevel@tonic-gate }
13430Sstevel@tonic-gate 
13440Sstevel@tonic-gate static int
idn_deinit()13450Sstevel@tonic-gate idn_deinit()
13460Sstevel@tonic-gate {
13470Sstevel@tonic-gate 	procname_t	proc = "idn_deinit";
13480Sstevel@tonic-gate 
13490Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&idn.siplock));
13500Sstevel@tonic-gate 
13510Sstevel@tonic-gate 	IDN_GLOCK_EXCL();
13520Sstevel@tonic-gate 
13530Sstevel@tonic-gate 	if (idn.state != IDNGS_OFFLINE) {
13540Sstevel@tonic-gate 		int	d;
13550Sstevel@tonic-gate 
13560Sstevel@tonic-gate 		cmn_err(CE_WARN,
13577656SSherry.Moore@Sun.COM 		    "IDN: 120: cannot deinit while active "
13587656SSherry.Moore@Sun.COM 		    "(state = %s)", idngs_str[idn.state]);
13590Sstevel@tonic-gate 
13600Sstevel@tonic-gate 		for (d = 0; d < MAX_DOMAINS; d++) {
13610Sstevel@tonic-gate 			idn_domain_t	*dp;
13620Sstevel@tonic-gate 
13630Sstevel@tonic-gate 			dp = &idn_domain[d];
13640Sstevel@tonic-gate 			if (dp->dcpu < 0)
13650Sstevel@tonic-gate 				continue;
13660Sstevel@tonic-gate 
13670Sstevel@tonic-gate 			cmn_err(CE_CONT,
13687656SSherry.Moore@Sun.COM 			    "IDN: 121: domain %d (CPU %d, "
13697656SSherry.Moore@Sun.COM 			    "name \"%s\", state %s)\n",
13707656SSherry.Moore@Sun.COM 			    d, dp->dcpu, dp->dname,
13717656SSherry.Moore@Sun.COM 			    idnds_str[dp->dstate]);
13720Sstevel@tonic-gate 		}
13730Sstevel@tonic-gate 		IDN_GUNLOCK();
13740Sstevel@tonic-gate 		return (-1);
13750Sstevel@tonic-gate 	}
13760Sstevel@tonic-gate 
13770Sstevel@tonic-gate 	if (idn.dip == NULL) {
13780Sstevel@tonic-gate 		PR_DRV("%s: already deinitialized\n", proc);
13790Sstevel@tonic-gate 		IDN_GUNLOCK();
13800Sstevel@tonic-gate 		return (0);
13810Sstevel@tonic-gate 	}
13820Sstevel@tonic-gate 
13830Sstevel@tonic-gate 	IDN_GSTATE_TRANSITION(IDNGS_IGNORE);
13840Sstevel@tonic-gate 
13850Sstevel@tonic-gate 	IDN_GUNLOCK();
13860Sstevel@tonic-gate 
13870Sstevel@tonic-gate 	idn_xmit_monitor_deinit();
13880Sstevel@tonic-gate 
13890Sstevel@tonic-gate 	idn_deinit_handler();
13900Sstevel@tonic-gate 
13910Sstevel@tonic-gate 	idn_chanservers_deinit();
13920Sstevel@tonic-gate 
13930Sstevel@tonic-gate 	idn.nchannels = 0;
13940Sstevel@tonic-gate 	ASSERT(idn.chan_servers == NULL);
13950Sstevel@tonic-gate 
13960Sstevel@tonic-gate 	smr_slabpool_deinit();
13970Sstevel@tonic-gate 
13980Sstevel@tonic-gate 	idn_protocol_deinit();
13990Sstevel@tonic-gate 
14000Sstevel@tonic-gate 	idn_domains_deinit();
14010Sstevel@tonic-gate 
14020Sstevel@tonic-gate 	smr_slabwaiter_deinit();
14030Sstevel@tonic-gate 
14040Sstevel@tonic-gate 	idn_retrytask_deinit();
14050Sstevel@tonic-gate 
14060Sstevel@tonic-gate 	idn_timercache_deinit();
14070Sstevel@tonic-gate 
14080Sstevel@tonic-gate 	idn_dopers_deinit();
14090Sstevel@tonic-gate 
14100Sstevel@tonic-gate 	ASSERT(idn.localid == IDN_NIL_DOMID);
14110Sstevel@tonic-gate 
14120Sstevel@tonic-gate 	IDN_SET_MASTERID(IDN_NIL_DOMID);
14130Sstevel@tonic-gate 
14140Sstevel@tonic-gate 	idn_deinit_smr();
14150Sstevel@tonic-gate 
14160Sstevel@tonic-gate 	mutex_destroy(&idn.sipwenlock);
14170Sstevel@tonic-gate 	mutex_destroy(&idn.sync.sz_mutex);
14180Sstevel@tonic-gate 	rw_destroy(&idn.grwlock);
14190Sstevel@tonic-gate 	rw_destroy(&idn.struprwlock);
14200Sstevel@tonic-gate 
14210Sstevel@tonic-gate 	idn.dip = NULL;
14220Sstevel@tonic-gate 
14230Sstevel@tonic-gate 	return (0);
14240Sstevel@tonic-gate }
14250Sstevel@tonic-gate 
14260Sstevel@tonic-gate static void
idn_xmit_monitor_init()14270Sstevel@tonic-gate idn_xmit_monitor_init()
14280Sstevel@tonic-gate {
14290Sstevel@tonic-gate 	mutex_init(&idn.xmit_lock, NULL, MUTEX_DEFAULT, NULL);
14300Sstevel@tonic-gate 	idn.xmit_tid = (timeout_id_t)NULL;
14310Sstevel@tonic-gate 	CHANSET_ZERO(idn.xmit_chanset_wanted);
14320Sstevel@tonic-gate }
14330Sstevel@tonic-gate 
14340Sstevel@tonic-gate static void
idn_xmit_monitor_deinit()14350Sstevel@tonic-gate idn_xmit_monitor_deinit()
14360Sstevel@tonic-gate {
14370Sstevel@tonic-gate 	timeout_id_t	tid;
14380Sstevel@tonic-gate 
14390Sstevel@tonic-gate 	mutex_enter(&idn.xmit_lock);
14400Sstevel@tonic-gate 	CHANSET_ZERO(idn.xmit_chanset_wanted);
14410Sstevel@tonic-gate 	if ((tid = idn.xmit_tid) != (timeout_id_t)NULL) {
14420Sstevel@tonic-gate 		idn.xmit_tid = (timeout_id_t)NULL;
14430Sstevel@tonic-gate 		mutex_exit(&idn.xmit_lock);
14440Sstevel@tonic-gate 		(void) untimeout(tid);
14450Sstevel@tonic-gate 	} else {
14460Sstevel@tonic-gate 		mutex_exit(&idn.xmit_lock);
14470Sstevel@tonic-gate 	}
14480Sstevel@tonic-gate 	mutex_destroy(&idn.xmit_lock);
14490Sstevel@tonic-gate }
14500Sstevel@tonic-gate 
14510Sstevel@tonic-gate static void
idn_init_msg_waittime()14520Sstevel@tonic-gate idn_init_msg_waittime()
14530Sstevel@tonic-gate {
14540Sstevel@tonic-gate 	idn_msg_waittime[IDNP_NULL] = -1;
14550Sstevel@tonic-gate 	idn_msg_waittime[IDNP_NEGO] = idn_msgwait_nego * hz;
14560Sstevel@tonic-gate 	idn_msg_waittime[IDNP_CFG]  = idn_msgwait_cfg * hz;
14570Sstevel@tonic-gate 	idn_msg_waittime[IDNP_CON]  = idn_msgwait_con * hz;
14580Sstevel@tonic-gate 	idn_msg_waittime[IDNP_FIN]  = idn_msgwait_fin * hz;
14590Sstevel@tonic-gate 	idn_msg_waittime[IDNP_CMD]  = idn_msgwait_cmd * hz;
14600Sstevel@tonic-gate 	idn_msg_waittime[IDNP_DATA] = idn_msgwait_data * hz;
14610Sstevel@tonic-gate }
14620Sstevel@tonic-gate 
14630Sstevel@tonic-gate static void
idn_init_msg_retrytime()14640Sstevel@tonic-gate idn_init_msg_retrytime()
14650Sstevel@tonic-gate {
14660Sstevel@tonic-gate 	idn_msg_retrytime[(int)IDNRETRY_NIL]	 = -1;
14670Sstevel@tonic-gate 	idn_msg_retrytime[(int)IDNRETRY_NEGO]	 = idn_retryfreq_nego * hz;
14680Sstevel@tonic-gate 	idn_msg_retrytime[(int)IDNRETRY_CON]	 = idn_retryfreq_con * hz;
14690Sstevel@tonic-gate 	idn_msg_retrytime[(int)IDNRETRY_CONQ]	 = idn_retryfreq_con * hz;
14700Sstevel@tonic-gate 	idn_msg_retrytime[(int)IDNRETRY_FIN]	 = idn_retryfreq_fin * hz;
14710Sstevel@tonic-gate 	idn_msg_retrytime[(int)IDNRETRY_FINQ]	 = idn_retryfreq_fin * hz;
14720Sstevel@tonic-gate }
14730Sstevel@tonic-gate 
14740Sstevel@tonic-gate /*
14750Sstevel@tonic-gate  * ----------------------------------------------
14760Sstevel@tonic-gate  */
14770Sstevel@tonic-gate /*ARGSUSED*/
14780Sstevel@tonic-gate static int
idnopen(register queue_t * rq,dev_t * devp,int flag,int sflag,cred_t * crp)14790Sstevel@tonic-gate idnopen(register queue_t *rq, dev_t *devp, int flag, int sflag, cred_t *crp)
14800Sstevel@tonic-gate {
14810Sstevel@tonic-gate 	register int	err = 0;
14820Sstevel@tonic-gate 	int		minordev;
14830Sstevel@tonic-gate 	struct idnstr	*stp, **pstp;
14840Sstevel@tonic-gate 	procname_t	proc = "idnopen";
14850Sstevel@tonic-gate 
14860Sstevel@tonic-gate 	ASSERT(sflag != MODOPEN);
14870Sstevel@tonic-gate 
14880Sstevel@tonic-gate 	IDN_GLOCK_EXCL();
14890Sstevel@tonic-gate 
14900Sstevel@tonic-gate 	rw_enter(&idn.struprwlock, RW_WRITER);
14910Sstevel@tonic-gate 	mutex_enter(&idn.sipwenlock);
14920Sstevel@tonic-gate 	pstp = &idn.strup;
14930Sstevel@tonic-gate 
14940Sstevel@tonic-gate 	if (idn.enabled == 0) {
14950Sstevel@tonic-gate 		PR_DRV("%s: Driver disabled (check OBP:idn-smr-size)\n",
14967656SSherry.Moore@Sun.COM 		    proc);
14970Sstevel@tonic-gate 		mutex_exit(&idn.sipwenlock);
14980Sstevel@tonic-gate 		rw_exit(&idn.struprwlock);
14990Sstevel@tonic-gate 		IDN_GUNLOCK();
15000Sstevel@tonic-gate 		return (EACCES);
15010Sstevel@tonic-gate 	}
15020Sstevel@tonic-gate 
15030Sstevel@tonic-gate 	if (!idn_ndlist &&
15040Sstevel@tonic-gate 	    idn_param_register(idn_param_arr, A_CNT(idn_param_arr))) {
15050Sstevel@tonic-gate 		PR_DRV("%s: failed to register ndd parameters\n", proc);
15060Sstevel@tonic-gate 		mutex_exit(&idn.sipwenlock);
15070Sstevel@tonic-gate 		rw_exit(&idn.struprwlock);
15080Sstevel@tonic-gate 		IDN_GUNLOCK();
15090Sstevel@tonic-gate 		return (ENOMEM);
15100Sstevel@tonic-gate 	}
15110Sstevel@tonic-gate 	IDN_GUNLOCK();
15120Sstevel@tonic-gate 
15130Sstevel@tonic-gate 	if (sflag == CLONEOPEN) {
15140Sstevel@tonic-gate 		minordev = 0;
15150Sstevel@tonic-gate 		for (stp = *pstp; stp; pstp = &stp->ss_nextp, stp = *pstp) {
15160Sstevel@tonic-gate 			if (minordev < stp->ss_minor)
15170Sstevel@tonic-gate 				break;
15180Sstevel@tonic-gate 			minordev++;
15190Sstevel@tonic-gate 		}
15200Sstevel@tonic-gate 		*devp = makedevice(getmajor(*devp), minordev);
15210Sstevel@tonic-gate 	} else {
15220Sstevel@tonic-gate 		minordev = getminor(*devp);
15230Sstevel@tonic-gate 	}
15240Sstevel@tonic-gate 	if (rq->q_ptr)
15250Sstevel@tonic-gate 		goto done;
15260Sstevel@tonic-gate 
15270Sstevel@tonic-gate 	stp = GETSTRUCT(struct idnstr, 1);
15280Sstevel@tonic-gate 	stp->ss_rq = rq;
15290Sstevel@tonic-gate 	stp->ss_minor = minordev;
15300Sstevel@tonic-gate 	rw_init(&stp->ss_rwlock, NULL, RW_DEFAULT, NULL);
15310Sstevel@tonic-gate 	/*
15320Sstevel@tonic-gate 	 * DLPI stuff
15330Sstevel@tonic-gate 	 */
15340Sstevel@tonic-gate 	stp->ss_sip = NULL;
15350Sstevel@tonic-gate 	stp->ss_state = DL_UNATTACHED;
15360Sstevel@tonic-gate 	stp->ss_sap = 0;
15370Sstevel@tonic-gate 	stp->ss_flags = 0;
15380Sstevel@tonic-gate 	stp->ss_mccount = 0;
15390Sstevel@tonic-gate 	stp->ss_mctab = NULL;
15400Sstevel@tonic-gate 
15410Sstevel@tonic-gate 	/*
15420Sstevel@tonic-gate 	 * Link new entry into list of actives.
15430Sstevel@tonic-gate 	 */
15440Sstevel@tonic-gate 	stp->ss_nextp = *pstp;
15450Sstevel@tonic-gate 	*pstp = stp;
15460Sstevel@tonic-gate 
15470Sstevel@tonic-gate 	WR(rq)->q_ptr = rq->q_ptr = (void *)stp;
15480Sstevel@tonic-gate 	/*
15490Sstevel@tonic-gate 	 * Disable automatic enabling of our write service
15500Sstevel@tonic-gate 	 * procedure.  We control this explicitly.
15510Sstevel@tonic-gate 	 */
15520Sstevel@tonic-gate 	noenable(WR(rq));
15530Sstevel@tonic-gate 
15540Sstevel@tonic-gate 	/*
15550Sstevel@tonic-gate 	 * Set our STREAMs queue maximum packet size that
15560Sstevel@tonic-gate 	 * we'll accept and our high/low water marks.
15570Sstevel@tonic-gate 	 */
15580Sstevel@tonic-gate 	(void) strqset(WR(rq), QMAXPSZ, 0, IDN_DATA_SIZE);
15590Sstevel@tonic-gate 	(void) strqset(WR(rq), QLOWAT,  0, IDN_LOWAT);
15600Sstevel@tonic-gate 	(void) strqset(WR(rq), QHIWAT,  0, IDN_HIWAT);
15610Sstevel@tonic-gate 	(void) strqset(rq, QMAXPSZ, 0, IDN_DATA_SIZE);
15620Sstevel@tonic-gate 	(void) strqset(rq, QLOWAT,  0, IDN_LOWAT);
15630Sstevel@tonic-gate 	(void) strqset(rq, QHIWAT,  0, IDN_HIWAT);
15640Sstevel@tonic-gate 
15650Sstevel@tonic-gate done:
15660Sstevel@tonic-gate 	mutex_exit(&idn.sipwenlock);
15670Sstevel@tonic-gate 	rw_exit(&idn.struprwlock);
15680Sstevel@tonic-gate 
15690Sstevel@tonic-gate 	(void) qassociate(rq, -1);
15700Sstevel@tonic-gate 	qprocson(rq);
15710Sstevel@tonic-gate 
15720Sstevel@tonic-gate 	return (err);
15730Sstevel@tonic-gate }
15740Sstevel@tonic-gate 
15750Sstevel@tonic-gate /*
15760Sstevel@tonic-gate  * ----------------------------------------------
15770Sstevel@tonic-gate  */
15780Sstevel@tonic-gate /*ARGSUSED1*/
15790Sstevel@tonic-gate static int
idnclose(queue_t * rq,int flag,cred_t * crp)15800Sstevel@tonic-gate idnclose(queue_t *rq, int flag, cred_t *crp)
15810Sstevel@tonic-gate {
15820Sstevel@tonic-gate 	struct idnstr	*stp, **pstp;
15830Sstevel@tonic-gate 
15840Sstevel@tonic-gate 	ASSERT(rq->q_ptr);
15850Sstevel@tonic-gate 
15860Sstevel@tonic-gate 	qprocsoff(rq);
15870Sstevel@tonic-gate 	/*
15880Sstevel@tonic-gate 	 * Guaranteed to be single threaded with respect
15890Sstevel@tonic-gate 	 * to this stream at this point.
15900Sstevel@tonic-gate 	 */
15910Sstevel@tonic-gate 
15920Sstevel@tonic-gate 	stp = (struct idnstr *)rq->q_ptr;
15930Sstevel@tonic-gate 
15940Sstevel@tonic-gate 	if (stp->ss_sip)
15950Sstevel@tonic-gate 		idndl_dodetach(stp);
15960Sstevel@tonic-gate 
15970Sstevel@tonic-gate 	rw_enter(&idn.struprwlock, RW_WRITER);
15980Sstevel@tonic-gate 	mutex_enter(&idn.sipwenlock);
15990Sstevel@tonic-gate 	pstp = &idn.strup;
16000Sstevel@tonic-gate 	for (stp = *pstp; stp; pstp = &stp->ss_nextp, stp = *pstp)
16010Sstevel@tonic-gate 		if (stp == (struct idnstr *)rq->q_ptr)
16020Sstevel@tonic-gate 			break;
16030Sstevel@tonic-gate 	ASSERT(stp);
16040Sstevel@tonic-gate 	ASSERT(stp->ss_rq == rq);
16050Sstevel@tonic-gate 	*pstp = stp->ss_nextp;
16060Sstevel@tonic-gate 
16070Sstevel@tonic-gate 	rw_destroy(&stp->ss_rwlock);
16080Sstevel@tonic-gate 	FREESTRUCT(stp, struct idnstr, 1);
16090Sstevel@tonic-gate 
16100Sstevel@tonic-gate 	WR(rq)->q_ptr = rq->q_ptr = NULL;
16110Sstevel@tonic-gate 	mutex_exit(&idn.sipwenlock);
16120Sstevel@tonic-gate 	rw_exit(&idn.struprwlock);
16130Sstevel@tonic-gate 
16140Sstevel@tonic-gate 	idn_param_cleanup();
16150Sstevel@tonic-gate 	(void) qassociate(rq, -1);
16160Sstevel@tonic-gate 
16170Sstevel@tonic-gate 	return (0);
16180Sstevel@tonic-gate }
16190Sstevel@tonic-gate 
16200Sstevel@tonic-gate /*
16210Sstevel@tonic-gate  * ----------------------------------------------
16220Sstevel@tonic-gate  */
16230Sstevel@tonic-gate static int
idnwput(register queue_t * wq,register mblk_t * mp)16240Sstevel@tonic-gate idnwput(register queue_t *wq, register mblk_t *mp)
16250Sstevel@tonic-gate {
16260Sstevel@tonic-gate 	register struct idnstr	*stp;
16270Sstevel@tonic-gate 	struct idn		*sip;
16280Sstevel@tonic-gate 	procname_t	proc = "idnwput";
16290Sstevel@tonic-gate 
16300Sstevel@tonic-gate 	stp = (struct idnstr *)wq->q_ptr;
16310Sstevel@tonic-gate 	sip = stp->ss_sip;
16320Sstevel@tonic-gate 
16330Sstevel@tonic-gate 	switch (DB_TYPE(mp)) {
16340Sstevel@tonic-gate 	case M_IOCTL:
16350Sstevel@tonic-gate 		idnioctl(wq, mp);
16360Sstevel@tonic-gate 		break;
16370Sstevel@tonic-gate 
16380Sstevel@tonic-gate 	case M_DATA:
16390Sstevel@tonic-gate 		if (((stp->ss_flags & (IDNSFAST|IDNSRAW)) == 0) ||
16407656SSherry.Moore@Sun.COM 		    (stp->ss_state != DL_IDLE) ||
16417656SSherry.Moore@Sun.COM 		    (sip == NULL)) {
1642931Smathue 			PR_DLPI("%s: fl=0x%x, st=0x%x, ret(EPROTO)\n",
16437656SSherry.Moore@Sun.COM 			    proc, stp->ss_flags, stp->ss_state);
16440Sstevel@tonic-gate 			merror(wq, mp, EPROTO);
16450Sstevel@tonic-gate 
16460Sstevel@tonic-gate 		} else if (wq->q_first) {
16470Sstevel@tonic-gate 			if (putq(wq, mp) == 0)
16480Sstevel@tonic-gate 				freemsg(mp);
16490Sstevel@tonic-gate 			/*
16500Sstevel@tonic-gate 			 * We're only holding the reader lock,
16510Sstevel@tonic-gate 			 * but that's okay since this field
16520Sstevel@tonic-gate 			 * is just a soft-flag.
16530Sstevel@tonic-gate 			 */
16540Sstevel@tonic-gate 			sip->si_wantw = 1;
16550Sstevel@tonic-gate 			qenable(wq);
16560Sstevel@tonic-gate 
16570Sstevel@tonic-gate 		} else if (sip->si_flags & IDNPROMISC) {
16580Sstevel@tonic-gate 			if (putq(wq, mp) == 0) {
16590Sstevel@tonic-gate 				PR_DLPI("%s: putq failed\n", proc);
16600Sstevel@tonic-gate 				freemsg(mp);
16610Sstevel@tonic-gate 			} else {
16620Sstevel@tonic-gate 				PR_DLPI("%s: putq succeeded\n", proc);
16630Sstevel@tonic-gate 			}
16640Sstevel@tonic-gate 			qenable(wq);
16650Sstevel@tonic-gate 
16660Sstevel@tonic-gate 		} else {
1667931Smathue 			PR_DLPI("%s: idndl_start(sip=0x%p)\n",
1668*11311SSurya.Prakki@Sun.COM 			    proc, (void *)sip);
16690Sstevel@tonic-gate 			rw_enter(&stp->ss_rwlock, RW_READER);
16700Sstevel@tonic-gate 			(void) idndl_start(wq, mp, sip);
16710Sstevel@tonic-gate 			rw_exit(&stp->ss_rwlock);
16720Sstevel@tonic-gate 		}
16730Sstevel@tonic-gate 		break;
16740Sstevel@tonic-gate 
16750Sstevel@tonic-gate 	case M_PROTO:
16760Sstevel@tonic-gate 	case M_PCPROTO:
16770Sstevel@tonic-gate 		/*
16780Sstevel@tonic-gate 		 * Break the association between the current thread
16790Sstevel@tonic-gate 		 * and the thread that calls idndl_proto() to resolve
16800Sstevel@tonic-gate 		 * the problem of idn_chan_server() threads which
16810Sstevel@tonic-gate 		 * loop back around to call idndl_proto and try to
16820Sstevel@tonic-gate 		 * recursively acquire internal locks.
16830Sstevel@tonic-gate 		 */
16840Sstevel@tonic-gate 		if (putq(wq, mp) == 0)
16850Sstevel@tonic-gate 			freemsg(mp);
16860Sstevel@tonic-gate 		qenable(wq);
16870Sstevel@tonic-gate 		break;
16880Sstevel@tonic-gate 
16890Sstevel@tonic-gate 	case M_FLUSH:
16900Sstevel@tonic-gate 		PR_STR("%s: M_FLUSH request (flush = %d)\n",
16917656SSherry.Moore@Sun.COM 		    proc, (int)*mp->b_rptr);
16920Sstevel@tonic-gate 		if (*mp->b_rptr & FLUSHW) {
16930Sstevel@tonic-gate 			flushq(wq, FLUSHALL);
16940Sstevel@tonic-gate 			*mp->b_rptr &= ~FLUSHW;
16950Sstevel@tonic-gate 		}
16960Sstevel@tonic-gate 		if (*mp->b_rptr & FLUSHR)
16970Sstevel@tonic-gate 			qreply(wq, mp);
16980Sstevel@tonic-gate 		else
16990Sstevel@tonic-gate 			freemsg(mp);
17000Sstevel@tonic-gate 		break;
17010Sstevel@tonic-gate 
17020Sstevel@tonic-gate 	default:
17030Sstevel@tonic-gate 		PR_STR("%s: unexpected DB_TYPE 0x%x\n",
17047656SSherry.Moore@Sun.COM 		    proc, DB_TYPE(mp));
17050Sstevel@tonic-gate 		freemsg(mp);
17060Sstevel@tonic-gate 		break;
17070Sstevel@tonic-gate 	}
17080Sstevel@tonic-gate 
17090Sstevel@tonic-gate 	return (0);
17100Sstevel@tonic-gate }
17110Sstevel@tonic-gate 
17120Sstevel@tonic-gate /*
17130Sstevel@tonic-gate  * ----------------------------------------------
17140Sstevel@tonic-gate  */
17150Sstevel@tonic-gate static int
idnwsrv(queue_t * wq)17160Sstevel@tonic-gate idnwsrv(queue_t *wq)
17170Sstevel@tonic-gate {
17180Sstevel@tonic-gate 	mblk_t		*mp;
17190Sstevel@tonic-gate 	int		err = 0;
17200Sstevel@tonic-gate 	struct idnstr	*stp;
17210Sstevel@tonic-gate 	struct idn	*sip;
17220Sstevel@tonic-gate 	procname_t	proc = "idnwsrv";
17230Sstevel@tonic-gate 
17240Sstevel@tonic-gate 	stp = (struct idnstr *)wq->q_ptr;
17250Sstevel@tonic-gate 	sip = stp->ss_sip;
17260Sstevel@tonic-gate 
17270Sstevel@tonic-gate 	while (mp = getq(wq)) {
17280Sstevel@tonic-gate 		switch (DB_TYPE(mp)) {
17290Sstevel@tonic-gate 		case M_DATA:
17300Sstevel@tonic-gate 			if (sip) {
1731931Smathue 				PR_DLPI("%s: idndl_start(sip=0x%p)\n",
1732*11311SSurya.Prakki@Sun.COM 				    proc, (void *)sip);
17330Sstevel@tonic-gate 				rw_enter(&stp->ss_rwlock, RW_READER);
17340Sstevel@tonic-gate 				err = idndl_start(wq, mp, sip);
17350Sstevel@tonic-gate 				rw_exit(&stp->ss_rwlock);
17360Sstevel@tonic-gate 				if (err)
17370Sstevel@tonic-gate 					goto done;
17380Sstevel@tonic-gate 			} else {
17390Sstevel@tonic-gate 				PR_DLPI("%s: NO sip to start msg\n", proc);
17400Sstevel@tonic-gate 				freemsg(mp);
17410Sstevel@tonic-gate 			}
17420Sstevel@tonic-gate 			break;
17430Sstevel@tonic-gate 
17440Sstevel@tonic-gate 		case M_PROTO:
17450Sstevel@tonic-gate 		case M_PCPROTO:
17460Sstevel@tonic-gate 			idndl_proto(wq, mp);
17470Sstevel@tonic-gate 			break;
17480Sstevel@tonic-gate 
17490Sstevel@tonic-gate 		default:
17500Sstevel@tonic-gate 			ASSERT(0);
17510Sstevel@tonic-gate 			PR_STR("%s: unexpected db_type (%d)\n",
17527656SSherry.Moore@Sun.COM 			    proc, DB_TYPE(mp));
17530Sstevel@tonic-gate 			freemsg(mp);
17540Sstevel@tonic-gate 			break;
17550Sstevel@tonic-gate 		}
17560Sstevel@tonic-gate 	}
17570Sstevel@tonic-gate done:
17580Sstevel@tonic-gate 	return (0);
17590Sstevel@tonic-gate }
17600Sstevel@tonic-gate 
17610Sstevel@tonic-gate /*
17620Sstevel@tonic-gate  * ----------------------------------------------
17630Sstevel@tonic-gate  */
17640Sstevel@tonic-gate static int
idnrput(register queue_t * rq,register mblk_t * mp)17650Sstevel@tonic-gate idnrput(register queue_t *rq, register mblk_t *mp)
17660Sstevel@tonic-gate {
17670Sstevel@tonic-gate 	register int	err = 0;
17680Sstevel@tonic-gate 	procname_t	proc = "idnrput";
17690Sstevel@tonic-gate 
17700Sstevel@tonic-gate 	switch (DB_TYPE(mp)) {
17710Sstevel@tonic-gate 	case M_DATA:
17720Sstevel@tonic-gate 		/*
17730Sstevel@tonic-gate 		 * Should not reach here with data packets
17740Sstevel@tonic-gate 		 * if running DLPI.
17750Sstevel@tonic-gate 		 */
17760Sstevel@tonic-gate 		cmn_err(CE_WARN,
17777656SSherry.Moore@Sun.COM 		    "IDN: 123: unexpected M_DATA packets for "
1778*11311SSurya.Prakki@Sun.COM 		    "q_stream 0x%p", (void *)rq->q_stream);
17790Sstevel@tonic-gate 		freemsg(mp);
17800Sstevel@tonic-gate 		err = ENXIO;
17810Sstevel@tonic-gate 		break;
17820Sstevel@tonic-gate 
17830Sstevel@tonic-gate 	case M_FLUSH:
17840Sstevel@tonic-gate 		PR_STR("%s: M_FLUSH request (flush = %d)\n",
17857656SSherry.Moore@Sun.COM 		    proc, (int)*mp->b_rptr);
17860Sstevel@tonic-gate 		if (*mp->b_rptr & FLUSHR)
17870Sstevel@tonic-gate 			flushq(rq, FLUSHALL);
17880Sstevel@tonic-gate 		(void) putnext(rq, mp);
17890Sstevel@tonic-gate 		break;
17900Sstevel@tonic-gate 
17910Sstevel@tonic-gate 	case M_ERROR:
17920Sstevel@tonic-gate 		PR_STR("%s: M_ERROR (error = %d) coming through\n",
17937656SSherry.Moore@Sun.COM 		    proc, (int)*mp->b_rptr);
17940Sstevel@tonic-gate 		(void) putnext(rq, mp);
17950Sstevel@tonic-gate 		break;
17960Sstevel@tonic-gate 	default:
17970Sstevel@tonic-gate 		PR_STR("%s: unexpected DB_TYPE 0x%x\n",
17987656SSherry.Moore@Sun.COM 		    proc, DB_TYPE(mp));
17990Sstevel@tonic-gate 		freemsg(mp);
18000Sstevel@tonic-gate 		err = ENXIO;
18010Sstevel@tonic-gate 		break;
18020Sstevel@tonic-gate 	}
18030Sstevel@tonic-gate 
18040Sstevel@tonic-gate 	return (err);
18050Sstevel@tonic-gate }
18060Sstevel@tonic-gate 
18070Sstevel@tonic-gate /*
18080Sstevel@tonic-gate  * ----------------------------------------------
18090Sstevel@tonic-gate  * Not allowed to enqueue messages!  Only M_DATA messages
18100Sstevel@tonic-gate  * can be enqueued on the write stream.
18110Sstevel@tonic-gate  * ----------------------------------------------
18120Sstevel@tonic-gate  */
18130Sstevel@tonic-gate static void
idnioctl(register queue_t * wq,register mblk_t * mp)18140Sstevel@tonic-gate idnioctl(register queue_t *wq, register mblk_t *mp)
18150Sstevel@tonic-gate {
18160Sstevel@tonic-gate 	register struct iocblk	*iocp;
18170Sstevel@tonic-gate 	register int	cmd;
18180Sstevel@tonic-gate 	idnop_t		*idnop = NULL;
18190Sstevel@tonic-gate 	int		error = 0;
18200Sstevel@tonic-gate 	int		argsize;
18210Sstevel@tonic-gate 	procname_t	proc = "idnioctl";
18220Sstevel@tonic-gate 
18230Sstevel@tonic-gate 	iocp = (struct iocblk *)mp->b_rptr;
18240Sstevel@tonic-gate 	cmd  = iocp->ioc_cmd;
18250Sstevel@tonic-gate 
18260Sstevel@tonic-gate 	/*
18270Sstevel@tonic-gate 	 * Intercept DLPI ioctl's.
18280Sstevel@tonic-gate 	 */
18290Sstevel@tonic-gate 	if (VALID_DLPIOP(cmd)) {
18300Sstevel@tonic-gate 		PR_STR("%s: DLPI ioctl(%d)\n", proc, cmd);
18310Sstevel@tonic-gate 		error = idnioc_dlpi(wq, mp, &argsize);
18320Sstevel@tonic-gate 		goto done;
18330Sstevel@tonic-gate 	}
18340Sstevel@tonic-gate 
18350Sstevel@tonic-gate 	/*
18360Sstevel@tonic-gate 	 * Validate expected arguments.
18370Sstevel@tonic-gate 	 */
18380Sstevel@tonic-gate 	if (!VALID_IDNIOCTL(cmd)) {
18390Sstevel@tonic-gate 		PR_STR("%s: invalid cmd (0x%x)\n", proc, cmd);
18400Sstevel@tonic-gate 		error = EINVAL;
18410Sstevel@tonic-gate 		goto done;
18420Sstevel@tonic-gate 
18430Sstevel@tonic-gate 	} else if (!VALID_NDOP(cmd)) {
18440Sstevel@tonic-gate 		error = miocpullup(mp, sizeof (idnop_t));
18450Sstevel@tonic-gate 		if (error != 0) {
18460Sstevel@tonic-gate 			PR_STR("%s: idnioc(cmd = 0x%x) miocpullup "
18470Sstevel@tonic-gate 			    "failed (%d)\n", proc, cmd, error);
18480Sstevel@tonic-gate 			goto done;
18490Sstevel@tonic-gate 		}
18500Sstevel@tonic-gate 	}
18510Sstevel@tonic-gate 
18520Sstevel@tonic-gate 	argsize = mp->b_cont->b_wptr - mp->b_cont->b_rptr;
18530Sstevel@tonic-gate 	idnop = (idnop_t *)mp->b_cont->b_rptr;
18540Sstevel@tonic-gate 
18550Sstevel@tonic-gate 	switch (cmd) {
18560Sstevel@tonic-gate 	case IDNIOC_LINK:
18570Sstevel@tonic-gate 		error = idnioc_link(idnop);
18580Sstevel@tonic-gate 		break;
18590Sstevel@tonic-gate 
18600Sstevel@tonic-gate 	case IDNIOC_UNLINK:
18610Sstevel@tonic-gate 		error = idnioc_unlink(idnop);
18620Sstevel@tonic-gate 		break;
18630Sstevel@tonic-gate 
18640Sstevel@tonic-gate 	case IDNIOC_MEM_RW:
18650Sstevel@tonic-gate 		error = idn_rw_mem(idnop);
18660Sstevel@tonic-gate 		break;
18670Sstevel@tonic-gate 
18680Sstevel@tonic-gate 	case IDNIOC_PING:
18690Sstevel@tonic-gate 		error = idn_send_ping(idnop);
18700Sstevel@tonic-gate 		break;
18710Sstevel@tonic-gate 
18720Sstevel@tonic-gate 	case ND_SET:
18730Sstevel@tonic-gate 		IDN_GLOCK_EXCL();
18740Sstevel@tonic-gate 		if (!nd_getset(wq, idn_ndlist, mp)) {
18750Sstevel@tonic-gate 			IDN_GUNLOCK();
18760Sstevel@tonic-gate 			error = ENOENT;
18770Sstevel@tonic-gate 			break;
18780Sstevel@tonic-gate 		}
18790Sstevel@tonic-gate 		IDN_GUNLOCK();
18800Sstevel@tonic-gate 		qreply(wq, mp);
18810Sstevel@tonic-gate 		return;
18820Sstevel@tonic-gate 
18830Sstevel@tonic-gate 	case ND_GET:
18840Sstevel@tonic-gate 		IDN_GLOCK_SHARED();
18850Sstevel@tonic-gate 		if (!nd_getset(wq, idn_ndlist, mp)) {
18860Sstevel@tonic-gate 			IDN_GUNLOCK();
18870Sstevel@tonic-gate 			error = ENOENT;
18880Sstevel@tonic-gate 			break;
18890Sstevel@tonic-gate 		}
18900Sstevel@tonic-gate 		IDN_GUNLOCK();
18910Sstevel@tonic-gate 		qreply(wq, mp);
18920Sstevel@tonic-gate 		return;
18930Sstevel@tonic-gate 
18940Sstevel@tonic-gate 	default:
18950Sstevel@tonic-gate 		PR_STR("%s: invalid cmd 0x%x\n", proc, cmd);
18960Sstevel@tonic-gate 		error = EINVAL;
18970Sstevel@tonic-gate 		break;
18980Sstevel@tonic-gate 	}
18990Sstevel@tonic-gate 
19000Sstevel@tonic-gate done:
19010Sstevel@tonic-gate 	if (error == 0)
19020Sstevel@tonic-gate 		miocack(wq, mp, argsize, 0);
19030Sstevel@tonic-gate 	else
19040Sstevel@tonic-gate 		miocnak(wq, mp, 0, error);
19050Sstevel@tonic-gate }
19060Sstevel@tonic-gate 
19070Sstevel@tonic-gate /*
19080Sstevel@tonic-gate  * This thread actually services the SSI_LINK/UNLINK calls
19090Sstevel@tonic-gate  * asynchronously that come via BBSRAM.  This is necessary
19100Sstevel@tonic-gate  * since we can't process them from within the context of
19110Sstevel@tonic-gate  * the interrupt handler in which idn_sigbhandler() is
19120Sstevel@tonic-gate  * called.
19130Sstevel@tonic-gate  */
19140Sstevel@tonic-gate static void
idn_sigbhandler_thread(struct sigbintr ** sbpp)19150Sstevel@tonic-gate idn_sigbhandler_thread(struct sigbintr **sbpp)
19160Sstevel@tonic-gate {
19170Sstevel@tonic-gate 	int		d, pri, rv;
19180Sstevel@tonic-gate 	struct sigbintr	*sbp;
19190Sstevel@tonic-gate 	sigbmbox_t	*mbp;
19200Sstevel@tonic-gate 	idn_fin_t	fintype;
19210Sstevel@tonic-gate 	idnsb_data_t	*sdp;
19220Sstevel@tonic-gate 	idnsb_info_t	*sfp;
19230Sstevel@tonic-gate 	idnsb_error_t	*sep;
19240Sstevel@tonic-gate 	idn_domain_t	*dp;
19250Sstevel@tonic-gate 	procname_t	proc = "idn_sigbhandler_thread";
19260Sstevel@tonic-gate 
19270Sstevel@tonic-gate 
19280Sstevel@tonic-gate 	sbp = *sbpp;
19290Sstevel@tonic-gate 
1930931Smathue 	PR_PROTO("%s: KICKED OFF (sigbintr pointer = 0x%p)\n",
1931*11311SSurya.Prakki@Sun.COM 	    proc, (void *)sbp);
19320Sstevel@tonic-gate 
19330Sstevel@tonic-gate 	ASSERT(sbp == &idn.sigbintr);
19340Sstevel@tonic-gate 
19350Sstevel@tonic-gate 	mutex_enter(&idn.sigbintr.sb_mutex);
19360Sstevel@tonic-gate 
19370Sstevel@tonic-gate 	while (sbp->sb_busy != IDNSIGB_DIE) {
19380Sstevel@tonic-gate 		cpu_sgnblk_t	*sigbp;
19390Sstevel@tonic-gate 
19400Sstevel@tonic-gate 		while ((sbp->sb_busy != IDNSIGB_ACTIVE) &&
19417656SSherry.Moore@Sun.COM 		    (sbp->sb_busy != IDNSIGB_DIE)) {
19420Sstevel@tonic-gate 			cv_wait(&sbp->sb_cv, &idn.sigbintr.sb_mutex);
19430Sstevel@tonic-gate 			PR_PROTO("%s: AWAKENED (busy = %d)\n",
19447656SSherry.Moore@Sun.COM 			    proc, (int)sbp->sb_busy);
19450Sstevel@tonic-gate 		}
19460Sstevel@tonic-gate 		if (sbp->sb_busy == IDNSIGB_DIE) {
19470Sstevel@tonic-gate 			PR_PROTO("%s: DIE REQUESTED\n", proc);
19480Sstevel@tonic-gate 			break;
19490Sstevel@tonic-gate 		}
19500Sstevel@tonic-gate 
19510Sstevel@tonic-gate 		if ((sigbp = cpu_sgnblkp[sbp->sb_cpuid]) == NULL) {
19520Sstevel@tonic-gate 			cmn_err(CE_WARN,
19537656SSherry.Moore@Sun.COM 			    "IDN: 124: sigblk for CPU ID %d "
19547656SSherry.Moore@Sun.COM 			    "is NULL", sbp->sb_cpuid);
19550Sstevel@tonic-gate 			sbp->sb_busy = IDNSIGB_INACTIVE;
19560Sstevel@tonic-gate 			continue;
19570Sstevel@tonic-gate 		}
19580Sstevel@tonic-gate 
19590Sstevel@tonic-gate 		mbp = &sigbp->sigb_host_mbox;
19600Sstevel@tonic-gate 
19610Sstevel@tonic-gate 		if (mbp->flag != SIGB_MBOX_BUSY) {
19620Sstevel@tonic-gate 			PR_PROTO("%s: sigblk mbox flag (%d) != BUSY (%d)\n",
19637656SSherry.Moore@Sun.COM 			    proc, mbp->flag, SIGB_MBOX_BUSY);
19640Sstevel@tonic-gate 			sbp->sb_busy = IDNSIGB_INACTIVE;
19650Sstevel@tonic-gate 			continue;
19660Sstevel@tonic-gate 		}
19670Sstevel@tonic-gate 		/*
19680Sstevel@tonic-gate 		 * The sb_busy bit is set and the mailbox flag
19690Sstevel@tonic-gate 		 * indicates BUSY also, so we effectively have things locked.
19700Sstevel@tonic-gate 		 * So, we can drop the critical sb_mutex which we want to
19710Sstevel@tonic-gate 		 * do since it pushes us to PIL 14 while we hold it and we
19720Sstevel@tonic-gate 		 * don't want to run at PIL 14 across IDN code.
19730Sstevel@tonic-gate 		 */
19740Sstevel@tonic-gate 		mutex_exit(&idn.sigbintr.sb_mutex);
19750Sstevel@tonic-gate 
19760Sstevel@tonic-gate 		sdp = (idnsb_data_t *)mbp->data;
19770Sstevel@tonic-gate 		sep = (idnsb_error_t *)&sdp->ssb_error;
19780Sstevel@tonic-gate 		INIT_IDNKERR(sep);
19790Sstevel@tonic-gate 
19800Sstevel@tonic-gate 		if (mbp->len != sizeof (idnsb_data_t)) {
19810Sstevel@tonic-gate 			PR_PROTO("%s: sigblk mbox length (%d) != "
19827656SSherry.Moore@Sun.COM 			    "expected (%lu)\n", proc, mbp->len,
19837656SSherry.Moore@Sun.COM 			    sizeof (idnsb_data_t));
19840Sstevel@tonic-gate 			SET_IDNKERR_ERRNO(sep, EINVAL);
19850Sstevel@tonic-gate 			SET_IDNKERR_IDNERR(sep, IDNKERR_DATA_LEN);
19860Sstevel@tonic-gate 			SET_IDNKERR_PARAM0(sep, sizeof (idnsb_data_t));
19870Sstevel@tonic-gate 
19880Sstevel@tonic-gate 			goto sberr;
19890Sstevel@tonic-gate 
19900Sstevel@tonic-gate 		}
19910Sstevel@tonic-gate 		if (idn.enabled == 0) {
19920Sstevel@tonic-gate #ifdef DEBUG
19930Sstevel@tonic-gate 			cmn_err(CE_NOTE,
19947656SSherry.Moore@Sun.COM 			    "IDN: 102: driver disabled "
19957656SSherry.Moore@Sun.COM 			    "- check OBP environment "
19967656SSherry.Moore@Sun.COM 			    "(idn-smr-size)");
19970Sstevel@tonic-gate #else /* DEBUG */
19980Sstevel@tonic-gate 			cmn_err(CE_NOTE,
19997656SSherry.Moore@Sun.COM 			    "!IDN: 102: driver disabled "
20007656SSherry.Moore@Sun.COM 			    "- check OBP environment "
20017656SSherry.Moore@Sun.COM 			    "(idn-smr-size)");
20020Sstevel@tonic-gate #endif /* DEBUG */
20030Sstevel@tonic-gate 			SET_IDNKERR_ERRNO(sep, EACCES);
20040Sstevel@tonic-gate 			SET_IDNKERR_IDNERR(sep, IDNKERR_DRV_DISABLED);
20050Sstevel@tonic-gate 
20060Sstevel@tonic-gate 			goto sberr;
20070Sstevel@tonic-gate 
20080Sstevel@tonic-gate 		}
20090Sstevel@tonic-gate 
20100Sstevel@tonic-gate 		switch (mbp->cmd) {
20110Sstevel@tonic-gate 
20120Sstevel@tonic-gate 		case SSI_LINK:
20130Sstevel@tonic-gate 		{
20140Sstevel@tonic-gate 			idnsb_link_t	slp;
20150Sstevel@tonic-gate 
20160Sstevel@tonic-gate 			bcopy(&sdp->ssb_link, &slp, sizeof (slp));
20170Sstevel@tonic-gate 
20180Sstevel@tonic-gate 			if (slp.master_pri < 0) {
20190Sstevel@tonic-gate 				pri = IDNVOTE_MINPRI;
20200Sstevel@tonic-gate 			} else if (slp.master_pri > 0) {
20210Sstevel@tonic-gate 				/*
20220Sstevel@tonic-gate 				 * If I'm already in a IDN network,
20230Sstevel@tonic-gate 				 * then my vote priority is set to
20240Sstevel@tonic-gate 				 * the max, otherwise it's one-less.
20250Sstevel@tonic-gate 				 */
20260Sstevel@tonic-gate 				pri = IDNVOTE_MAXPRI;
20270Sstevel@tonic-gate 				IDN_GLOCK_SHARED();
20280Sstevel@tonic-gate 				if (idn.ndomains <= 1)
20290Sstevel@tonic-gate 					pri--;
20300Sstevel@tonic-gate 				IDN_GUNLOCK();
20310Sstevel@tonic-gate 			} else {
20320Sstevel@tonic-gate 				pri = IDNVOTE_DEFPRI;
20330Sstevel@tonic-gate 			}
20340Sstevel@tonic-gate 
20350Sstevel@tonic-gate 			PR_PROTO("%s: SSI_LINK(cpuid = %d, domid = %d, "
20367656SSherry.Moore@Sun.COM 			    "pri = %d (req = %d), t/o = %d)\n",
20377656SSherry.Moore@Sun.COM 			    proc, slp.cpuid, slp.domid, pri,
20387656SSherry.Moore@Sun.COM 			    slp.master_pri, slp.timeout);
20390Sstevel@tonic-gate 
20400Sstevel@tonic-gate 			rv = idn_link(slp.domid, slp.cpuid, pri,
20417656SSherry.Moore@Sun.COM 			    slp.timeout, sep);
20420Sstevel@tonic-gate 			SET_IDNKERR_ERRNO(sep, rv);
20430Sstevel@tonic-gate 			(void) idn_info(&sdp->ssb_info);
20440Sstevel@tonic-gate 			break;
20450Sstevel@tonic-gate 		}
20460Sstevel@tonic-gate 
20470Sstevel@tonic-gate 		case SSI_UNLINK:
20480Sstevel@tonic-gate 		{
20490Sstevel@tonic-gate 			idnsb_unlink_t	sup;
20500Sstevel@tonic-gate 			idn_domain_t	*xdp;
20510Sstevel@tonic-gate 			domainset_t	domset;
20520Sstevel@tonic-gate 
20530Sstevel@tonic-gate 			bcopy(&sdp->ssb_unlink, &sup, sizeof (sup));
20540Sstevel@tonic-gate 
20550Sstevel@tonic-gate 			PR_PROTO("%s: SSI_UNLINK(c = %d, d = %d, bs = 0x%x, "
20567656SSherry.Moore@Sun.COM 			    "f = %d, is = 0x%x, t/o = %d)\n",
20577656SSherry.Moore@Sun.COM 			    proc, sup.cpuid, sup.domid, sup.boardset,
20587656SSherry.Moore@Sun.COM 			    sup.force, sup.idnset, sup.timeout);
20590Sstevel@tonic-gate 
20600Sstevel@tonic-gate 			domset = idn.domset.ds_trans_on |
20617656SSherry.Moore@Sun.COM 			    idn.domset.ds_connected |
20627656SSherry.Moore@Sun.COM 			    idn.domset.ds_trans_off |
20637656SSherry.Moore@Sun.COM 			    idn.domset.ds_awol |
20647656SSherry.Moore@Sun.COM 			    idn.domset.ds_relink;
20650Sstevel@tonic-gate 
20660Sstevel@tonic-gate 			if (VALID_DOMAINID(sup.domid)) {
20670Sstevel@tonic-gate 				dp = &idn_domain[sup.domid];
20680Sstevel@tonic-gate 			} else if (VALID_CPUID(sup.cpuid)) {
20690Sstevel@tonic-gate 				for (d = 0; d < MAX_DOMAINS; d++) {
20700Sstevel@tonic-gate 					xdp = &idn_domain[d];
20710Sstevel@tonic-gate 
20720Sstevel@tonic-gate 					if ((xdp->dcpu == IDN_NIL_DCPU) &&
20730Sstevel@tonic-gate 					    !DOMAIN_IN_SET(domset, d))
20740Sstevel@tonic-gate 						continue;
20750Sstevel@tonic-gate 
20760Sstevel@tonic-gate 					if (CPU_IN_SET(xdp->dcpuset,
20777656SSherry.Moore@Sun.COM 					    sup.cpuid))
20780Sstevel@tonic-gate 						break;
20790Sstevel@tonic-gate 				}
20800Sstevel@tonic-gate 				dp = (d == MAX_DOMAINS) ? NULL : xdp;
20810Sstevel@tonic-gate 			}
20820Sstevel@tonic-gate 			if ((dp == NULL) && sup.boardset) {
20830Sstevel@tonic-gate 				for (d = 0; d < MAX_DOMAINS; d++) {
20840Sstevel@tonic-gate 					xdp = &idn_domain[d];
20850Sstevel@tonic-gate 
20860Sstevel@tonic-gate 					if ((xdp->dcpu == IDN_NIL_DCPU) &&
20870Sstevel@tonic-gate 					    !DOMAIN_IN_SET(domset, d))
20880Sstevel@tonic-gate 						continue;
20890Sstevel@tonic-gate 
20900Sstevel@tonic-gate 					if (xdp->dhw.dh_boardset &
20917656SSherry.Moore@Sun.COM 					    sup.boardset)
20920Sstevel@tonic-gate 						break;
20930Sstevel@tonic-gate 				}
20940Sstevel@tonic-gate 				dp = (d == MAX_DOMAINS) ? NULL : xdp;
20950Sstevel@tonic-gate 			}
20960Sstevel@tonic-gate 			if (dp == NULL) {
20970Sstevel@tonic-gate 				SET_IDNKERR_ERRNO(sep, EINVAL);
20980Sstevel@tonic-gate 				SET_IDNKERR_IDNERR(sep, IDNKERR_INVALID_DOMAIN);
20990Sstevel@tonic-gate 				SET_IDNKERR_PARAM0(sep, sup.domid);
21000Sstevel@tonic-gate 				SET_IDNKERR_PARAM1(sep, sup.cpuid);
21010Sstevel@tonic-gate 				(void) idn_info(&sdp->ssb_info);
21020Sstevel@tonic-gate 				goto sberr;
21030Sstevel@tonic-gate 			} else {
21040Sstevel@tonic-gate 				sup.domid = dp->domid;
21050Sstevel@tonic-gate 			}
21060Sstevel@tonic-gate 
21070Sstevel@tonic-gate 			switch (sup.force) {
21080Sstevel@tonic-gate 			case SSIFORCE_OFF:
21090Sstevel@tonic-gate 				fintype = IDNFIN_NORMAL;
21100Sstevel@tonic-gate 				break;
21110Sstevel@tonic-gate 
21120Sstevel@tonic-gate 			case SSIFORCE_SOFT:
21130Sstevel@tonic-gate 				fintype = IDNFIN_FORCE_SOFT;
21140Sstevel@tonic-gate 				break;
21150Sstevel@tonic-gate 
21160Sstevel@tonic-gate 			case SSIFORCE_HARD:
21170Sstevel@tonic-gate 				fintype = IDNFIN_FORCE_HARD;
21180Sstevel@tonic-gate 				break;
21190Sstevel@tonic-gate 			default:
21200Sstevel@tonic-gate 				SET_IDNKERR_ERRNO(sep, EINVAL);
21210Sstevel@tonic-gate 				SET_IDNKERR_IDNERR(sep, IDNKERR_INVALID_FORCE);
21220Sstevel@tonic-gate 				SET_IDNKERR_PARAM0(sep, sup.force);
21230Sstevel@tonic-gate 				(void) idn_info(&sdp->ssb_info);
21240Sstevel@tonic-gate 				goto sberr;
21250Sstevel@tonic-gate 			}
21260Sstevel@tonic-gate 
21270Sstevel@tonic-gate 			rv = idn_unlink(sup.domid, sup.idnset, fintype,
21287656SSherry.Moore@Sun.COM 			    IDNFIN_OPT_UNLINK, sup.timeout, sep);
21290Sstevel@tonic-gate 			SET_IDNKERR_ERRNO(sep, rv);
21300Sstevel@tonic-gate 			(void) idn_info(&sdp->ssb_info);
21310Sstevel@tonic-gate 			break;
21320Sstevel@tonic-gate 		}
21330Sstevel@tonic-gate 
21340Sstevel@tonic-gate 		case SSI_INFO:
21350Sstevel@tonic-gate 			sfp = &sdp->ssb_info;
21360Sstevel@tonic-gate 
21370Sstevel@tonic-gate 			PR_PROTO("%s: SSI_INFO\n", proc);
21380Sstevel@tonic-gate 
21390Sstevel@tonic-gate 			rv = idn_info(sfp);
21400Sstevel@tonic-gate 			SET_IDNKERR_ERRNO(sep, rv);
21410Sstevel@tonic-gate 			if (rv != 0) {
21420Sstevel@tonic-gate 				SET_IDNKERR_IDNERR(sep, IDNKERR_INFO_FAILED);
21430Sstevel@tonic-gate 			}
21440Sstevel@tonic-gate 			break;
21450Sstevel@tonic-gate 
21460Sstevel@tonic-gate 		default:
21470Sstevel@tonic-gate 			ASSERT(0);
21480Sstevel@tonic-gate 			SET_IDNKERR_ERRNO(sep, EINVAL);
21490Sstevel@tonic-gate 			SET_IDNKERR_IDNERR(sep, IDNKERR_INVALID_CMD);
21500Sstevel@tonic-gate 			SET_IDNKERR_PARAM0(sep, mbp->cmd);
21510Sstevel@tonic-gate 			break;
21520Sstevel@tonic-gate 		}
21530Sstevel@tonic-gate 
21540Sstevel@tonic-gate sberr:
21550Sstevel@tonic-gate 
21560Sstevel@tonic-gate 		if (GET_IDNKERR_ERRNO(sep) != 0) {
21570Sstevel@tonic-gate 			cmn_err(CE_WARN,
21580Sstevel@tonic-gate #ifdef DEBUG
21597656SSherry.Moore@Sun.COM 			    "IDN: 125: op (%s) failed, returning "
21607656SSherry.Moore@Sun.COM 			    "(%d/0x%x [%d, %d, %d])",
21610Sstevel@tonic-gate #else /* DEBUG */
21627656SSherry.Moore@Sun.COM 			    "!IDN: 125: op (%s) failed, returning "
21637656SSherry.Moore@Sun.COM 			    "(%d/0x%x [%d, %d, %d])",
21640Sstevel@tonic-gate #endif /* DEBUG */
21657656SSherry.Moore@Sun.COM 			    (mbp->cmd == SSI_LINK) ? "LINK" :
21667656SSherry.Moore@Sun.COM 			    (mbp->cmd == SSI_UNLINK) ? "UNLINK" :
21677656SSherry.Moore@Sun.COM 			    (mbp->cmd == SSI_INFO) ?
21687656SSherry.Moore@Sun.COM 			    "INFO" : "UNKNOWN",
21697656SSherry.Moore@Sun.COM 			    GET_IDNKERR_ERRNO(sep),
21707656SSherry.Moore@Sun.COM 			    GET_IDNKERR_IDNERR(sep),
21717656SSherry.Moore@Sun.COM 			    GET_IDNKERR_PARAM0(sep),
21727656SSherry.Moore@Sun.COM 			    GET_IDNKERR_PARAM1(sep),
21737656SSherry.Moore@Sun.COM 			    GET_IDNKERR_PARAM2(sep));
21740Sstevel@tonic-gate 		}
21750Sstevel@tonic-gate 
21760Sstevel@tonic-gate 		PR_PROTO("%s: returning errno = %d, idnerr = %d, "
21777656SSherry.Moore@Sun.COM 		    "params = [%d, %d, %d]\n",
21787656SSherry.Moore@Sun.COM 		    proc, GET_IDNKERR_ERRNO(sep), GET_IDNKERR_IDNERR(sep),
21797656SSherry.Moore@Sun.COM 		    GET_IDNKERR_PARAM0(sep), GET_IDNKERR_PARAM1(sep),
21807656SSherry.Moore@Sun.COM 		    GET_IDNKERR_PARAM2(sep));
21810Sstevel@tonic-gate 
21820Sstevel@tonic-gate 		mutex_enter(&idn.sigbintr.sb_mutex);
21830Sstevel@tonic-gate 		ASSERT((sbp->sb_busy == IDNSIGB_ACTIVE) ||
21847656SSherry.Moore@Sun.COM 		    (sbp->sb_busy == IDNSIGB_DIE));
21850Sstevel@tonic-gate 		mbp->cmd |= SSI_ACK;
21860Sstevel@tonic-gate 		if (sbp->sb_busy == IDNSIGB_ACTIVE)
21870Sstevel@tonic-gate 			sbp->sb_busy = IDNSIGB_INACTIVE;
21880Sstevel@tonic-gate 		/*
21890Sstevel@tonic-gate 		 * Set flag which kicks off response to SSP.
21900Sstevel@tonic-gate 		 */
21910Sstevel@tonic-gate 		membar_stst_ldst();
21920Sstevel@tonic-gate 		mbp->flag = HOST_TO_CBS;
21930Sstevel@tonic-gate 	}
21940Sstevel@tonic-gate 
21950Sstevel@tonic-gate 	/*
21960Sstevel@tonic-gate 	 * Wake up the dude that killed us!
21970Sstevel@tonic-gate 	 */
21980Sstevel@tonic-gate 	idn.sigb_threadp = NULL;
21990Sstevel@tonic-gate 	cv_signal(&sbp->sb_cv);
22000Sstevel@tonic-gate 	mutex_exit(&idn.sigbintr.sb_mutex);
22010Sstevel@tonic-gate 	thread_exit();
22020Sstevel@tonic-gate }
22030Sstevel@tonic-gate 
22040Sstevel@tonic-gate /*
22050Sstevel@tonic-gate  * Create the thread that will service sigb interrupts.
22060Sstevel@tonic-gate  */
22070Sstevel@tonic-gate static void
idn_sigbhandler_create()22080Sstevel@tonic-gate idn_sigbhandler_create()
22090Sstevel@tonic-gate {
22100Sstevel@tonic-gate 	struct sigbintr	*sbp;
22110Sstevel@tonic-gate 
22120Sstevel@tonic-gate 	if (idn.sigb_threadp) {
22130Sstevel@tonic-gate 		cmn_err(CE_WARN,
22147656SSherry.Moore@Sun.COM 		    "IDN: 126: sigbhandler thread already "
2215*11311SSurya.Prakki@Sun.COM 		    "exists (0x%p)", (void *)idn.sigb_threadp);
22160Sstevel@tonic-gate 		return;
22170Sstevel@tonic-gate 	}
22180Sstevel@tonic-gate 	cv_init(&idn.sigbintr.sb_cv, NULL, CV_DEFAULT, NULL);
22190Sstevel@tonic-gate 	sbp = &idn.sigbintr;
22200Sstevel@tonic-gate 	sbp->sb_busy = IDNSIGB_INACTIVE;
22210Sstevel@tonic-gate 	idn.sigb_threadp = thread_create(NULL, 0,
22220Sstevel@tonic-gate 	    idn_sigbhandler_thread, &sbp, sizeof (sbp), &p0,
22230Sstevel@tonic-gate 	    TS_RUN, minclsyspri);
22240Sstevel@tonic-gate 	sbp->sb_inum = add_softintr((uint_t)idn_sigbpil,
22252973Sgovinda 	    idn_sigbhandler_wakeup, 0, SOFTINT_ST);
22260Sstevel@tonic-gate }
22270Sstevel@tonic-gate 
22280Sstevel@tonic-gate static void
idn_sigbhandler_kill()22290Sstevel@tonic-gate idn_sigbhandler_kill()
22300Sstevel@tonic-gate {
22310Sstevel@tonic-gate 	if (idn.sigb_threadp) {
22320Sstevel@tonic-gate 		struct sigbintr	*sbp;
22330Sstevel@tonic-gate 
22340Sstevel@tonic-gate 		sbp = &idn.sigbintr;
22350Sstevel@tonic-gate 		if (sbp->sb_inum != 0)
22362973Sgovinda 			(void) rem_softintr(sbp->sb_inum);
22370Sstevel@tonic-gate 		sbp->sb_inum = 0;
22380Sstevel@tonic-gate 		sbp->sb_busy = IDNSIGB_DIE;
22390Sstevel@tonic-gate 		cv_signal(&sbp->sb_cv);
22400Sstevel@tonic-gate 		while (idn.sigb_threadp != NULL)
22410Sstevel@tonic-gate 			cv_wait(&sbp->sb_cv, &idn.sigbintr.sb_mutex);
22420Sstevel@tonic-gate 		sbp->sb_busy = IDNSIGB_INACTIVE;
22430Sstevel@tonic-gate 		cv_destroy(&sbp->sb_cv);
22440Sstevel@tonic-gate 	}
22450Sstevel@tonic-gate }
22460Sstevel@tonic-gate 
22470Sstevel@tonic-gate /*ARGSUSED0*/
22480Sstevel@tonic-gate static uint_t
idn_sigbhandler_wakeup(caddr_t arg1,caddr_t arg2)22490Sstevel@tonic-gate idn_sigbhandler_wakeup(caddr_t arg1, caddr_t arg2)
22500Sstevel@tonic-gate {
22510Sstevel@tonic-gate 	mutex_enter(&idn.sigbintr.sb_mutex);
22520Sstevel@tonic-gate 	if (idn.sigbintr.sb_busy == IDNSIGB_STARTED) {
22530Sstevel@tonic-gate 		idn.sigbintr.sb_busy = IDNSIGB_ACTIVE;
22540Sstevel@tonic-gate 		cv_signal(&idn.sigbintr.sb_cv);
22550Sstevel@tonic-gate 	}
22560Sstevel@tonic-gate 	mutex_exit(&idn.sigbintr.sb_mutex);
22570Sstevel@tonic-gate 
22580Sstevel@tonic-gate 	return (DDI_INTR_CLAIMED);
22590Sstevel@tonic-gate }
22600Sstevel@tonic-gate 
22610Sstevel@tonic-gate static void
idn_sigbhandler(processorid_t cpuid,cpu_sgnblk_t * sgnblkp)22620Sstevel@tonic-gate idn_sigbhandler(processorid_t cpuid, cpu_sgnblk_t *sgnblkp)
22630Sstevel@tonic-gate {
22640Sstevel@tonic-gate 	struct sigbintr	*sbp = &idn.sigbintr;
22650Sstevel@tonic-gate 	sigbmbox_t	*mbp;
22660Sstevel@tonic-gate 	idnsb_data_t	*sdp;
22670Sstevel@tonic-gate 	idnsb_error_t	*sep;
22680Sstevel@tonic-gate 	uint32_t	cmd;
22690Sstevel@tonic-gate 	int		sigb_lock = 0;
22700Sstevel@tonic-gate 
22710Sstevel@tonic-gate 	ASSERT(sgnblkp);
22720Sstevel@tonic-gate 
22730Sstevel@tonic-gate 	mbp = &sgnblkp->sigb_host_mbox;
22740Sstevel@tonic-gate 	sdp = (idnsb_data_t *)mbp->data;
22750Sstevel@tonic-gate 	sep = &sdp->ssb_error;
22760Sstevel@tonic-gate 	cmd = mbp->cmd;
22770Sstevel@tonic-gate 
22780Sstevel@tonic-gate 	if ((mbp->flag != CBS_TO_HOST) || !VALID_IDNSIGBCMD(cmd)) {
22790Sstevel@tonic-gate 		/*
22800Sstevel@tonic-gate 		 * Not a valid IDN command.  Just bail out.
22810Sstevel@tonic-gate 		 */
22820Sstevel@tonic-gate 		return;
22830Sstevel@tonic-gate 	}
22840Sstevel@tonic-gate 
22850Sstevel@tonic-gate 	mbp->flag = SIGB_MBOX_BUSY;
22860Sstevel@tonic-gate 	SET_IDNKERR_ERRNO(sep, 0);
22870Sstevel@tonic-gate 
22880Sstevel@tonic-gate 	if (cmd & SSI_ACK) {
22890Sstevel@tonic-gate 		/*
22900Sstevel@tonic-gate 		 * Hmmm...weird, the ACK bit is set.
22910Sstevel@tonic-gate 		 */
22920Sstevel@tonic-gate 		SET_IDNKERR_ERRNO(sep, EPROTO);
22930Sstevel@tonic-gate 		SET_IDNKERR_IDNERR(sep, IDNKERR_INVALID_CMD);
22940Sstevel@tonic-gate 		SET_IDNKERR_PARAM0(sep, cmd);
22950Sstevel@tonic-gate 		goto sigb_done;
22960Sstevel@tonic-gate 	}
22970Sstevel@tonic-gate 
22980Sstevel@tonic-gate 	if (!mutex_tryenter(&idn.sigbintr.sb_mutex)) {
22990Sstevel@tonic-gate 		/*
23000Sstevel@tonic-gate 		 * Couldn't get the lock.  Driver is either
23010Sstevel@tonic-gate 		 * not quite all the way up or is shutting down
23020Sstevel@tonic-gate 		 * for some reason.  Caller should spin again.
23030Sstevel@tonic-gate 		 */
23040Sstevel@tonic-gate 		cmd |= SSI_ACK;
23050Sstevel@tonic-gate 		SET_IDNKERR_ERRNO(sep, EBUSY);
23060Sstevel@tonic-gate 		SET_IDNKERR_IDNERR(sep, IDNKERR_SIGBINTR_LOCKED);
23070Sstevel@tonic-gate 		goto sigb_done;
23080Sstevel@tonic-gate 	}
23090Sstevel@tonic-gate 	sigb_lock = 1;
23100Sstevel@tonic-gate 
23110Sstevel@tonic-gate 	if ((idn.sigb_threadp == NULL) ||
23127656SSherry.Moore@Sun.COM 	    (sbp->sb_busy == IDNSIGB_NOTREADY)) {
23130Sstevel@tonic-gate 		cmd |= SSI_ACK;
23140Sstevel@tonic-gate 		SET_IDNKERR_ERRNO(sep, EAGAIN);
23150Sstevel@tonic-gate 		SET_IDNKERR_IDNERR(sep, IDNKERR_SIGBINTR_NOTRDY);
23160Sstevel@tonic-gate 		goto sigb_done;
23170Sstevel@tonic-gate 	}
23180Sstevel@tonic-gate 
23190Sstevel@tonic-gate 	if (sbp->sb_busy != IDNSIGB_INACTIVE) {
23200Sstevel@tonic-gate 		cmd |= SSI_ACK;
23210Sstevel@tonic-gate 		SET_IDNKERR_ERRNO(sep, EBUSY);
23220Sstevel@tonic-gate 		SET_IDNKERR_IDNERR(sep, IDNKERR_SIGBINTR_BUSY);
23230Sstevel@tonic-gate 		goto sigb_done;
23240Sstevel@tonic-gate 	}
23250Sstevel@tonic-gate 
23260Sstevel@tonic-gate 	sbp->sb_cpuid = (uchar_t)cpuid & 0xff;
23270Sstevel@tonic-gate 	membar_stst_ldst();
23280Sstevel@tonic-gate 	sbp->sb_busy = IDNSIGB_STARTED;
23290Sstevel@tonic-gate 	/*
23300Sstevel@tonic-gate 	 * The sb_busy bit is set and the mailbox flag
23310Sstevel@tonic-gate 	 * indicates BUSY also, so we effectively have things locked.
23320Sstevel@tonic-gate 	 * So, we can drop the critical sb_mutex which we want to
23330Sstevel@tonic-gate 	 * do since it pushes us to PIL 14 while we hold it and we
23340Sstevel@tonic-gate 	 * don't want to run at PIL 14 across IDN code.
23350Sstevel@tonic-gate 	 *
23360Sstevel@tonic-gate 	 * Send interrupt to cause idn_sigbhandler_thread to wakeup.
23370Sstevel@tonic-gate 	 * We cannot do wakeup (cv_signal) directly from here since
23380Sstevel@tonic-gate 	 * we're executing from a high-level (14) interrupt.
23390Sstevel@tonic-gate 	 */
23400Sstevel@tonic-gate 	setsoftint(sbp->sb_inum);
23410Sstevel@tonic-gate 
23420Sstevel@tonic-gate sigb_done:
23430Sstevel@tonic-gate 
23440Sstevel@tonic-gate 	if (GET_IDNKERR_ERRNO(sep) != 0) {
23450Sstevel@tonic-gate 		mbp->len = sizeof (idnsb_data_t);
23460Sstevel@tonic-gate 		mbp->cmd = cmd;
23470Sstevel@tonic-gate 		membar_stst_ldst();
23480Sstevel@tonic-gate 		mbp->flag = HOST_TO_CBS;
23490Sstevel@tonic-gate 	}
23500Sstevel@tonic-gate 
23510Sstevel@tonic-gate 	if (sigb_lock)
23520Sstevel@tonic-gate 		mutex_exit(&idn.sigbintr.sb_mutex);
23530Sstevel@tonic-gate }
23540Sstevel@tonic-gate 
23550Sstevel@tonic-gate static int
idn_info(idnsb_info_t * sfp)23560Sstevel@tonic-gate idn_info(idnsb_info_t *sfp)
23570Sstevel@tonic-gate {
23580Sstevel@tonic-gate 	int		count, d;
23590Sstevel@tonic-gate 	idn_domain_t	*dp;
23600Sstevel@tonic-gate 	idnsb_info_t	sinfo;
23610Sstevel@tonic-gate 	int		local_id, master_id;
23620Sstevel@tonic-gate 	procname_t	proc = "idn_info";
23630Sstevel@tonic-gate 
23640Sstevel@tonic-gate 	bzero(&sinfo, sizeof (sinfo));
23650Sstevel@tonic-gate 	sinfo.master_index = (uchar_t)-1;
23660Sstevel@tonic-gate 	sinfo.master_cpuid = (uchar_t)-1;
23670Sstevel@tonic-gate 	sinfo.local_index  = (uchar_t)-1;
23680Sstevel@tonic-gate 	sinfo.local_cpuid  = (uchar_t)-1;
23690Sstevel@tonic-gate 
23700Sstevel@tonic-gate 	IDN_GLOCK_SHARED();
23710Sstevel@tonic-gate 
23720Sstevel@tonic-gate 	sinfo.idn_state = (uchar_t)idn.state;
23730Sstevel@tonic-gate 
23740Sstevel@tonic-gate 	switch (idn.state) {
23750Sstevel@tonic-gate 	case IDNGS_OFFLINE:
23760Sstevel@tonic-gate 		sinfo.idn_active = SSISTATE_INACTIVE;
23770Sstevel@tonic-gate 		PR_PROTO("%s: idn_state (%s) = INACTIVE\n",
23787656SSherry.Moore@Sun.COM 		    proc, idngs_str[idn.state]);
23790Sstevel@tonic-gate 		break;
23800Sstevel@tonic-gate 
23810Sstevel@tonic-gate 	case IDNGS_IGNORE:
23820Sstevel@tonic-gate 		PR_PROTO("%s: IGNORING IDN_INFO call...\n", proc);
23830Sstevel@tonic-gate 		IDN_GUNLOCK();
23840Sstevel@tonic-gate 		return (EIO);
23850Sstevel@tonic-gate 
23860Sstevel@tonic-gate 	default:
23870Sstevel@tonic-gate 		sinfo.idn_active = SSISTATE_ACTIVE;
23880Sstevel@tonic-gate 		PR_PROTO("%s: idn_state (%s) = ACTIVE\n",
23897656SSherry.Moore@Sun.COM 		    proc, idngs_str[idn.state]);
23900Sstevel@tonic-gate 		break;
23910Sstevel@tonic-gate 	}
23920Sstevel@tonic-gate 	master_id = IDN_GET_MASTERID();
23930Sstevel@tonic-gate 	local_id = idn.localid;
23940Sstevel@tonic-gate 
23950Sstevel@tonic-gate 	/*
23960Sstevel@tonic-gate 	 * Need to drop idn.grwlock before acquiring domain locks.
23970Sstevel@tonic-gate 	 */
23980Sstevel@tonic-gate 	IDN_GUNLOCK();
23990Sstevel@tonic-gate 
24000Sstevel@tonic-gate 	IDN_SYNC_LOCK();
24010Sstevel@tonic-gate 
24020Sstevel@tonic-gate 	sinfo.awol_domset = (ushort_t)idn.domset.ds_awol;
24030Sstevel@tonic-gate 	sinfo.conn_domset = (ushort_t)(idn.domset.ds_connected &
24047656SSherry.Moore@Sun.COM 	    ~idn.domset.ds_trans_on);
24050Sstevel@tonic-gate 	DOMAINSET_ADD(sinfo.conn_domset, idn.localid);
24060Sstevel@tonic-gate 
24070Sstevel@tonic-gate 	count = 0;
24080Sstevel@tonic-gate 	for (d = 0; d < MAX_DOMAINS; d++) {
24090Sstevel@tonic-gate 		dp = &idn_domain[d];
24100Sstevel@tonic-gate 
24110Sstevel@tonic-gate 		if (dp->dcpu == IDN_NIL_DCPU)
24120Sstevel@tonic-gate 			continue;
24130Sstevel@tonic-gate 
24140Sstevel@tonic-gate 		IDN_DLOCK_SHARED(d);
24150Sstevel@tonic-gate 		if ((dp->dcpu == IDN_NIL_DCPU) ||
24167656SSherry.Moore@Sun.COM 		    (dp->dstate == IDNDS_CLOSED)) {
24170Sstevel@tonic-gate 			IDN_DUNLOCK(d);
24180Sstevel@tonic-gate 			continue;
24190Sstevel@tonic-gate 		}
24200Sstevel@tonic-gate 
24210Sstevel@tonic-gate 		count++;
24220Sstevel@tonic-gate 		if (d == local_id) {
24230Sstevel@tonic-gate 			sinfo.local_index = (uchar_t)d;
24240Sstevel@tonic-gate 			sinfo.local_cpuid = (uchar_t)dp->dcpu;
24250Sstevel@tonic-gate 			PR_PROTO("%s: domid %d is LOCAL (cpuid = %d)\n",
24267656SSherry.Moore@Sun.COM 			    proc, d, dp->dcpu);
24270Sstevel@tonic-gate 		}
24280Sstevel@tonic-gate 		if (d == master_id) {
24290Sstevel@tonic-gate 			sinfo.master_index = (uchar_t)d;
24300Sstevel@tonic-gate 			sinfo.master_cpuid = (uchar_t)dp->dcpu;
24310Sstevel@tonic-gate 			PR_PROTO("%s: domid %d is MASTER (cpuid = %d)\n",
24327656SSherry.Moore@Sun.COM 			    proc, d, dp->dcpu);
24330Sstevel@tonic-gate 		}
24340Sstevel@tonic-gate 
24350Sstevel@tonic-gate 		sinfo.domain_boardset[d] = (ushort_t)dp->dhw.dh_boardset;
24360Sstevel@tonic-gate 
24370Sstevel@tonic-gate 		IDN_DUNLOCK(d);
24380Sstevel@tonic-gate 	}
24390Sstevel@tonic-gate 
24400Sstevel@tonic-gate 	IDN_SYNC_UNLOCK();
24410Sstevel@tonic-gate 
24420Sstevel@tonic-gate 	bcopy(&sinfo, sfp, sizeof (*sfp));
24430Sstevel@tonic-gate 
24440Sstevel@tonic-gate 	PR_PROTO("%s: Found %d domains within IDNnet\n", proc, count);
24450Sstevel@tonic-gate 
24460Sstevel@tonic-gate 	return (0);
24470Sstevel@tonic-gate }
24480Sstevel@tonic-gate 
24490Sstevel@tonic-gate /*
24500Sstevel@tonic-gate  * ----------------------------------------------
24510Sstevel@tonic-gate  * ndd param support routines.
24520Sstevel@tonic-gate  * - Borrowed from tcp.
24530Sstevel@tonic-gate  * ----------------------------------------------
24540Sstevel@tonic-gate  */
24550Sstevel@tonic-gate static void
idn_param_cleanup()24560Sstevel@tonic-gate idn_param_cleanup()
24570Sstevel@tonic-gate {
24580Sstevel@tonic-gate 	IDN_GLOCK_EXCL();
24590Sstevel@tonic-gate 	if (!idn.strup && idn_ndlist)
24600Sstevel@tonic-gate 		nd_free(&idn_ndlist);
24610Sstevel@tonic-gate 	IDN_GUNLOCK();
24620Sstevel@tonic-gate }
24630Sstevel@tonic-gate 
24640Sstevel@tonic-gate /*ARGSUSED*/
24650Sstevel@tonic-gate static int
idn_param_get(queue_t * q,mblk_t * mp,caddr_t cp,cred_t * cr)24660Sstevel@tonic-gate idn_param_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *cr)
24670Sstevel@tonic-gate {
24680Sstevel@tonic-gate 	idnparam_t	*idnpa = (idnparam_t *)cp;
24690Sstevel@tonic-gate 
24700Sstevel@tonic-gate 	/*
24710Sstevel@tonic-gate 	 * lock grabbed before calling nd_getset.
24720Sstevel@tonic-gate 	 */
24730Sstevel@tonic-gate 	ASSERT(IDN_GLOCK_IS_HELD());
24740Sstevel@tonic-gate 
24750Sstevel@tonic-gate 	(void) mi_mpprintf(mp, "%ld", idnpa->sp_val);
24760Sstevel@tonic-gate 
24770Sstevel@tonic-gate 	return (0);
24780Sstevel@tonic-gate }
24790Sstevel@tonic-gate 
24800Sstevel@tonic-gate /*ARGSUSED*/
24810Sstevel@tonic-gate static int
idn_param_set(queue_t * q,mblk_t * mp,char * value,caddr_t cp,cred_t * cr)24820Sstevel@tonic-gate idn_param_set(queue_t *q, mblk_t *mp, char *value, caddr_t cp, cred_t *cr)
24830Sstevel@tonic-gate {
24840Sstevel@tonic-gate 	char		*end;
24850Sstevel@tonic-gate 	ulong_t		new_value;
24860Sstevel@tonic-gate 	idnparam_t	*idnpa = (idnparam_t *)cp;
24870Sstevel@tonic-gate 
24880Sstevel@tonic-gate 	/*
24890Sstevel@tonic-gate 	 * lock grabbed before calling nd_getset.
24900Sstevel@tonic-gate 	 */
24910Sstevel@tonic-gate 	ASSERT(IDN_GLOCK_IS_EXCL());
24920Sstevel@tonic-gate 
24930Sstevel@tonic-gate 	new_value = (ulong_t)mi_strtol(value, &end, 10);
24940Sstevel@tonic-gate 
24950Sstevel@tonic-gate 	if ((end == value) ||
24967656SSherry.Moore@Sun.COM 	    (new_value < idnpa->sp_min) ||
24977656SSherry.Moore@Sun.COM 	    (new_value > idnpa->sp_max))
24980Sstevel@tonic-gate 		return (EINVAL);
24990Sstevel@tonic-gate 
25000Sstevel@tonic-gate 	if (idn.enabled == 0) {
25010Sstevel@tonic-gate #ifdef DEBUG
25020Sstevel@tonic-gate 		cmn_err(CE_NOTE,
25037656SSherry.Moore@Sun.COM 		    "IDN: 102: driver disabled "
25047656SSherry.Moore@Sun.COM 		    "- check OBP environment "
25057656SSherry.Moore@Sun.COM 		    "(idn-smr-size)");
25060Sstevel@tonic-gate #else /* DEBUG */
25070Sstevel@tonic-gate 		cmn_err(CE_NOTE,
25087656SSherry.Moore@Sun.COM 		    "!IDN: 102: driver disabled "
25097656SSherry.Moore@Sun.COM 		    "- check OBP environment "
25107656SSherry.Moore@Sun.COM 		    "(idn-smr-size)");
25110Sstevel@tonic-gate #endif /* DEBUG */
25120Sstevel@tonic-gate 		return (EACCES);
25130Sstevel@tonic-gate 	}
25140Sstevel@tonic-gate 
25150Sstevel@tonic-gate 	idnpa->sp_val = new_value;
25160Sstevel@tonic-gate 
25170Sstevel@tonic-gate 	return (0);
25180Sstevel@tonic-gate }
25190Sstevel@tonic-gate 
25200Sstevel@tonic-gate static int
idn_param_register(register idnparam_t * idnpa,int count)25210Sstevel@tonic-gate idn_param_register(register idnparam_t *idnpa, int count)
25220Sstevel@tonic-gate {
25230Sstevel@tonic-gate 	ASSERT(IDN_GLOCK_IS_EXCL());
25240Sstevel@tonic-gate 
25250Sstevel@tonic-gate 	for (; count > 0; count--, idnpa++) {
25260Sstevel@tonic-gate 		if (idnpa->sp_name && idnpa->sp_name[0]) {
25270Sstevel@tonic-gate 			register int	i;
25280Sstevel@tonic-gate 			ndsetf_t	set_func;
25290Sstevel@tonic-gate 			char		*p;
25300Sstevel@tonic-gate 			/*
25310Sstevel@tonic-gate 			 * Don't advertise in non-DEBUG parameters.
25320Sstevel@tonic-gate 			 */
25330Sstevel@tonic-gate 			for (i = 0; idn_param_debug_only[i]; i++) {
25340Sstevel@tonic-gate 				p = idn_param_debug_only[i];
25350Sstevel@tonic-gate 				if (strcmp(idnpa->sp_name, p) == 0)
25360Sstevel@tonic-gate 					break;
25370Sstevel@tonic-gate 			}
25380Sstevel@tonic-gate 			if (idn_param_debug_only[i])
25390Sstevel@tonic-gate 				continue;
25400Sstevel@tonic-gate 
25410Sstevel@tonic-gate 			/*
25420Sstevel@tonic-gate 			 * Do not register a "set" function for
25430Sstevel@tonic-gate 			 * read-only parameters.
25440Sstevel@tonic-gate 			 */
25450Sstevel@tonic-gate 			for (i = 0; idn_param_read_only[i]; i++) {
25460Sstevel@tonic-gate 				p = idn_param_read_only[i];
25470Sstevel@tonic-gate 				if (strcmp(idnpa->sp_name, p) == 0)
25480Sstevel@tonic-gate 					break;
25490Sstevel@tonic-gate 			}
25500Sstevel@tonic-gate 			if (idn_param_read_only[i])
25510Sstevel@tonic-gate 				set_func = NULL;
25520Sstevel@tonic-gate 			else
25530Sstevel@tonic-gate 				set_func = idn_param_set;
25540Sstevel@tonic-gate 
25550Sstevel@tonic-gate 			if (!nd_load(&idn_ndlist, idnpa->sp_name,
25567656SSherry.Moore@Sun.COM 			    idn_param_get, set_func,
25577656SSherry.Moore@Sun.COM 			    (caddr_t)idnpa)) {
25580Sstevel@tonic-gate 				nd_free(&idn_ndlist);
25590Sstevel@tonic-gate 				return (-1);
25600Sstevel@tonic-gate 			}
25610Sstevel@tonic-gate 		}
25620Sstevel@tonic-gate 	}
25630Sstevel@tonic-gate 	if (!nd_load(&idn_ndlist, "idn_slabpool", idn_slabpool_report,
25647656SSherry.Moore@Sun.COM 	    NULL, NULL)) {
25650Sstevel@tonic-gate 		nd_free(&idn_ndlist);
25660Sstevel@tonic-gate 		return (-1);
25670Sstevel@tonic-gate 	}
25680Sstevel@tonic-gate 	if (!nd_load(&idn_ndlist, "idn_buffers", idn_buffer_report,
25697656SSherry.Moore@Sun.COM 	    NULL, NULL)) {
25700Sstevel@tonic-gate 		nd_free(&idn_ndlist);
25710Sstevel@tonic-gate 		return (-1);
25720Sstevel@tonic-gate 	}
25730Sstevel@tonic-gate 	if (!nd_load(&idn_ndlist, "idn_mboxtbl", idn_mboxtbl_report,
25747656SSherry.Moore@Sun.COM 	    NULL, MBXTBL_PART_REPORT)) {
25750Sstevel@tonic-gate 		nd_free(&idn_ndlist);
25760Sstevel@tonic-gate 		return (-1);
25770Sstevel@tonic-gate 	}
25780Sstevel@tonic-gate 	if (!nd_load(&idn_ndlist, "idn_mboxtbl_all", idn_mboxtbl_report,
25797656SSherry.Moore@Sun.COM 	    NULL, MBXTBL_FULL_REPORT)) {
25800Sstevel@tonic-gate 		nd_free(&idn_ndlist);
25810Sstevel@tonic-gate 		return (-1);
25820Sstevel@tonic-gate 	}
25830Sstevel@tonic-gate 	if (!nd_load(&idn_ndlist, "idn_mainmbox", idn_mainmbox_report,
25847656SSherry.Moore@Sun.COM 	    NULL, NULL)) {
25850Sstevel@tonic-gate 		nd_free(&idn_ndlist);
25860Sstevel@tonic-gate 		return (-1);
25870Sstevel@tonic-gate 	}
25880Sstevel@tonic-gate 	if (!nd_load(&idn_ndlist, "idn_global", idn_global_report,
25897656SSherry.Moore@Sun.COM 	    NULL, NULL)) {
25900Sstevel@tonic-gate 		nd_free(&idn_ndlist);
25910Sstevel@tonic-gate 		return (-1);
25920Sstevel@tonic-gate 	}
25930Sstevel@tonic-gate 	if (!nd_load(&idn_ndlist, "idn_domain", idn_domain_report,
25947656SSherry.Moore@Sun.COM 	    NULL, (caddr_t)0)) {
25950Sstevel@tonic-gate 		nd_free(&idn_ndlist);
25960Sstevel@tonic-gate 		return (-1);
25970Sstevel@tonic-gate 	}
25980Sstevel@tonic-gate 	if (!nd_load(&idn_ndlist, "idn_domain_all", idn_domain_report,
25997656SSherry.Moore@Sun.COM 	    NULL, (caddr_t)1)) {
26000Sstevel@tonic-gate 		nd_free(&idn_ndlist);
26010Sstevel@tonic-gate 		return (-1);
26020Sstevel@tonic-gate 	}
26030Sstevel@tonic-gate 	if (!nd_load(&idn_ndlist, "idn_bind_net", idn_get_net_binding,
26047656SSherry.Moore@Sun.COM 	    idn_set_net_binding, NULL)) {
26050Sstevel@tonic-gate 		nd_free(&idn_ndlist);
26060Sstevel@tonic-gate 		return (-1);
26070Sstevel@tonic-gate 	}
26080Sstevel@tonic-gate 
26090Sstevel@tonic-gate 	return (0);
26100Sstevel@tonic-gate }
26110Sstevel@tonic-gate 
26120Sstevel@tonic-gate /*ARGSUSED*/
26130Sstevel@tonic-gate static int
idn_set_net_binding(queue_t * q,mblk_t * mp,char * value,caddr_t cp,cred_t * cr)26140Sstevel@tonic-gate idn_set_net_binding(queue_t *q, mblk_t *mp, char *value, caddr_t cp, cred_t *cr)
26150Sstevel@tonic-gate {
26160Sstevel@tonic-gate 	char		*end, *cpup;
26170Sstevel@tonic-gate 	long		net;
26180Sstevel@tonic-gate 	processorid_t	cpuid;
26190Sstevel@tonic-gate 
26200Sstevel@tonic-gate 	/*
26210Sstevel@tonic-gate 	 * lock grabbed before calling nd_getset.
26220Sstevel@tonic-gate 	 */
26230Sstevel@tonic-gate 	ASSERT(IDN_GLOCK_IS_EXCL());
26240Sstevel@tonic-gate 
26250Sstevel@tonic-gate 	if ((cpup = strchr(value, '=')) == NULL)
26260Sstevel@tonic-gate 		return (EINVAL);
26270Sstevel@tonic-gate 
26280Sstevel@tonic-gate 	*cpup++ = '\0';
26290Sstevel@tonic-gate 
26300Sstevel@tonic-gate 	net = mi_strtol(value, &end, 10);
26310Sstevel@tonic-gate 	if ((end == value) || (net < 0) || (net >= IDN_MAX_NETS) ||
26327656SSherry.Moore@Sun.COM 	    !CHAN_IN_SET(idn.chanset, net))
26330Sstevel@tonic-gate 		return (EINVAL);
26340Sstevel@tonic-gate 
26350Sstevel@tonic-gate 	cpuid = (processorid_t)mi_strtol(cpup, &end, 10);
26360Sstevel@tonic-gate 	if ((end == cpup) || ((cpuid != -1) &&
26377656SSherry.Moore@Sun.COM 	    (!VALID_CPUID(cpuid) ||
26387656SSherry.Moore@Sun.COM 	    !CPU_IN_SET(cpu_ready_set, cpuid))))
26390Sstevel@tonic-gate 		return (EINVAL);
26400Sstevel@tonic-gate 
26410Sstevel@tonic-gate 	idn_chanserver_bind(net, cpuid);
26420Sstevel@tonic-gate 
26430Sstevel@tonic-gate 	return (0);
26440Sstevel@tonic-gate }
26450Sstevel@tonic-gate 
26460Sstevel@tonic-gate /*ARGSUSED*/
26470Sstevel@tonic-gate static int
idn_get_net_binding(queue_t * q,mblk_t * mp,caddr_t cp,cred_t * cr)26480Sstevel@tonic-gate idn_get_net_binding(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *cr)
26490Sstevel@tonic-gate {
26500Sstevel@tonic-gate 	int	c;
26510Sstevel@tonic-gate 
26520Sstevel@tonic-gate 	/*
26530Sstevel@tonic-gate 	 * lock grabbed before calling nd_getset.
26540Sstevel@tonic-gate 	 */
26550Sstevel@tonic-gate 	ASSERT(IDN_GLOCK_IS_HELD());
26560Sstevel@tonic-gate 
26570Sstevel@tonic-gate 	(void) mi_mpprintf(mp,
26587656SSherry.Moore@Sun.COM 	    "IDN network interfaces/channels active = %d",
26597656SSherry.Moore@Sun.COM 	    idn.nchannels);
26600Sstevel@tonic-gate 
26610Sstevel@tonic-gate 	if (idn.nchannels == 0)
26620Sstevel@tonic-gate 		return (0);
26630Sstevel@tonic-gate 
2664*11311SSurya.Prakki@Sun.COM 	(void) mi_mpprintf(mp, "Net    Cpu");
26650Sstevel@tonic-gate 
26660Sstevel@tonic-gate 	for (c = 0; c < IDN_MAX_NETS; c++) {
26670Sstevel@tonic-gate 		int		bc;
26680Sstevel@tonic-gate 		idn_chansvr_t	*csp;
26690Sstevel@tonic-gate 
26700Sstevel@tonic-gate 		if (!CHAN_IN_SET(idn.chanset, c))
26710Sstevel@tonic-gate 			continue;
26720Sstevel@tonic-gate 
26730Sstevel@tonic-gate 		csp = &idn.chan_servers[c];
26740Sstevel@tonic-gate 
26750Sstevel@tonic-gate 		if ((bc = csp->ch_bound_cpuid) == -1)
26760Sstevel@tonic-gate 			bc = csp->ch_bound_cpuid_pending;
26770Sstevel@tonic-gate 
26780Sstevel@tonic-gate 		if (c < 10)
2679*11311SSurya.Prakki@Sun.COM 			(void) mi_mpprintf(mp, " %d      %d", c, bc);
26800Sstevel@tonic-gate 		else
2681*11311SSurya.Prakki@Sun.COM 			(void) mi_mpprintf(mp, " %d     %d", c, bc);
26820Sstevel@tonic-gate 	}
26830Sstevel@tonic-gate 
26840Sstevel@tonic-gate 	return (0);
26850Sstevel@tonic-gate }
26860Sstevel@tonic-gate 
26870Sstevel@tonic-gate static int
idnioc_link(idnop_t * idnop)26880Sstevel@tonic-gate idnioc_link(idnop_t *idnop)
26890Sstevel@tonic-gate {
26900Sstevel@tonic-gate 	int		rv;
26910Sstevel@tonic-gate 	int		pri;
26920Sstevel@tonic-gate 	idnsb_error_t	err;
26930Sstevel@tonic-gate 	procname_t	proc = "idnioc_link";
26940Sstevel@tonic-gate 
26950Sstevel@tonic-gate 	if (idnop->link.master < 0)
26960Sstevel@tonic-gate 		pri = IDNVOTE_MINPRI;
26970Sstevel@tonic-gate 	else if (idnop->link.master > 0)
26980Sstevel@tonic-gate 		pri = IDNVOTE_MAXPRI;
26990Sstevel@tonic-gate 	else
27000Sstevel@tonic-gate 		pri = IDNVOTE_DEFPRI;
27010Sstevel@tonic-gate 
27020Sstevel@tonic-gate 	PR_DRV("%s: domid = %d, cpuid = %d, pri = %d\n",
27037656SSherry.Moore@Sun.COM 	    proc, idnop->link.domid, idnop->link.cpuid, pri);
27040Sstevel@tonic-gate 
27050Sstevel@tonic-gate 	rv = idn_link(idnop->link.domid, idnop->link.cpuid,
27067656SSherry.Moore@Sun.COM 	    pri, idnop->link.wait, &err);
27070Sstevel@tonic-gate 
27080Sstevel@tonic-gate 	return (rv);
27090Sstevel@tonic-gate }
27100Sstevel@tonic-gate 
27110Sstevel@tonic-gate static int
idnioc_unlink(idnop_t * idnop)27120Sstevel@tonic-gate idnioc_unlink(idnop_t *idnop)
27130Sstevel@tonic-gate {
27140Sstevel@tonic-gate 	int		d, cpuid, domid, rv;
27150Sstevel@tonic-gate 	boardset_t	idnset;
27160Sstevel@tonic-gate 	idn_fin_t	fintype;
27170Sstevel@tonic-gate 	idn_domain_t	*dp, *xdp;
27180Sstevel@tonic-gate 	idnsb_error_t	err;
27190Sstevel@tonic-gate 	procname_t	proc = "idnioc_unlink";
27200Sstevel@tonic-gate 
27210Sstevel@tonic-gate 	PR_DRV("%s: domid = %d, cpuid = %d, force = %d\n",
27227656SSherry.Moore@Sun.COM 	    proc, idnop->unlink.domid, idnop->unlink.cpuid,
27237656SSherry.Moore@Sun.COM 	    idnop->unlink.force);
27240Sstevel@tonic-gate 
27250Sstevel@tonic-gate 	idnset = BOARDSET_ALL;
27260Sstevel@tonic-gate 	domid = idnop->unlink.domid;
27270Sstevel@tonic-gate 	cpuid = idnop->unlink.cpuid;
27280Sstevel@tonic-gate 	dp = NULL;
27290Sstevel@tonic-gate 
27300Sstevel@tonic-gate 	if (domid == IDN_NIL_DOMID)
27310Sstevel@tonic-gate 		domid = idn.localid;
27320Sstevel@tonic-gate 
27330Sstevel@tonic-gate 	if (VALID_DOMAINID(domid)) {
27340Sstevel@tonic-gate 		dp = &idn_domain[domid];
27350Sstevel@tonic-gate 		if (VALID_CPUID(cpuid) && (dp->dcpu != IDN_NIL_DCPU) &&
27367656SSherry.Moore@Sun.COM 		    !CPU_IN_SET(dp->dcpuset, cpuid)) {
27370Sstevel@tonic-gate 			dp = NULL;
27380Sstevel@tonic-gate 			PR_PROTO("%s: ERROR: invalid cpuid "
27397656SSherry.Moore@Sun.COM 			    "(%d) for domain (%d) [cset = 0x%x.x%x]\n",
27407656SSherry.Moore@Sun.COM 			    proc, cpuid, domid,
27417656SSherry.Moore@Sun.COM 			    UPPER32_CPUMASK(dp->dcpuset),
27427656SSherry.Moore@Sun.COM 			    LOWER32_CPUMASK(dp->dcpuset));
27430Sstevel@tonic-gate 		}
27440Sstevel@tonic-gate 	} else if (VALID_CPUID(cpuid)) {
27450Sstevel@tonic-gate 		for (d = 0; d < MAX_DOMAINS; d++) {
27460Sstevel@tonic-gate 			xdp = &idn_domain[d];
27470Sstevel@tonic-gate 
27480Sstevel@tonic-gate 			if (xdp->dcpu == IDN_NIL_DCPU)
27490Sstevel@tonic-gate 				continue;
27500Sstevel@tonic-gate 
27510Sstevel@tonic-gate 			if (CPU_IN_SET(xdp->dcpuset, cpuid))
27520Sstevel@tonic-gate 				break;
27530Sstevel@tonic-gate 		}
27540Sstevel@tonic-gate 		dp = (d == MAX_DOMAINS) ? NULL : xdp;
27550Sstevel@tonic-gate 	}
27560Sstevel@tonic-gate 
27570Sstevel@tonic-gate 	if ((dp == NULL) || (dp->dcpu == IDN_NIL_DCPU))
27580Sstevel@tonic-gate 		return (0);
27590Sstevel@tonic-gate 
27600Sstevel@tonic-gate 	domid = dp->domid;
27610Sstevel@tonic-gate 
27620Sstevel@tonic-gate 	switch (idnop->unlink.force) {
27630Sstevel@tonic-gate 	case SSIFORCE_OFF:
27640Sstevel@tonic-gate 		fintype = IDNFIN_NORMAL;
27650Sstevel@tonic-gate 		break;
27660Sstevel@tonic-gate 
27670Sstevel@tonic-gate 	case SSIFORCE_SOFT:
27680Sstevel@tonic-gate 		fintype = IDNFIN_FORCE_SOFT;
27690Sstevel@tonic-gate 		break;
27700Sstevel@tonic-gate 
27710Sstevel@tonic-gate 	case SSIFORCE_HARD:
27720Sstevel@tonic-gate 		fintype = IDNFIN_FORCE_HARD;
27730Sstevel@tonic-gate 		break;
27740Sstevel@tonic-gate 	default:
27750Sstevel@tonic-gate 		PR_PROTO("%s: invalid force parameter \"%d\"",
27767656SSherry.Moore@Sun.COM 		    proc, idnop->unlink.force);
27770Sstevel@tonic-gate 		return (EINVAL);
27780Sstevel@tonic-gate 	}
27790Sstevel@tonic-gate 
27800Sstevel@tonic-gate 	rv = idn_unlink(domid, idnset, fintype, IDNFIN_OPT_UNLINK,
27817656SSherry.Moore@Sun.COM 	    idnop->unlink.wait, &err);
27820Sstevel@tonic-gate 
27830Sstevel@tonic-gate 	return (rv);
27840Sstevel@tonic-gate }
27850Sstevel@tonic-gate 
27860Sstevel@tonic-gate static int
idn_send_ping(idnop_t * idnop)27870Sstevel@tonic-gate idn_send_ping(idnop_t *idnop)
27880Sstevel@tonic-gate {
27890Sstevel@tonic-gate 	int		domid = idnop->ping.domid;
27900Sstevel@tonic-gate 	int		cpuid = idnop->ping.cpuid;
27910Sstevel@tonic-gate 	int		ocpuid;
27920Sstevel@tonic-gate 	idn_domain_t	*dp;
27930Sstevel@tonic-gate 	idn_msgtype_t	mt;
27940Sstevel@tonic-gate 	procname_t	proc = "idn_send_ping";
27950Sstevel@tonic-gate 
27960Sstevel@tonic-gate 	if ((domid == IDN_NIL_DOMID) && (cpuid == IDN_NIL_DCPU)) {
27970Sstevel@tonic-gate 		cmn_err(CE_WARN,
27987656SSherry.Moore@Sun.COM 		    "IDN: %s: no valid domain ID or CPU ID given",
27997656SSherry.Moore@Sun.COM 		    proc);
28000Sstevel@tonic-gate 		return (EINVAL);
28010Sstevel@tonic-gate 	}
28020Sstevel@tonic-gate 	if (domid == IDN_NIL_DOMID)
28030Sstevel@tonic-gate 		domid = MAX_DOMAINS - 1;
28040Sstevel@tonic-gate 
28050Sstevel@tonic-gate 	dp = &idn_domain[domid];
28060Sstevel@tonic-gate 	IDN_DLOCK_EXCL(domid);
28070Sstevel@tonic-gate 	if ((dp->dcpu == IDN_NIL_DCPU) && (cpuid == IDN_NIL_DCPU)) {
28080Sstevel@tonic-gate 		cmn_err(CE_WARN,
28097656SSherry.Moore@Sun.COM 		    "IDN: %s: no valid target CPU specified",
28107656SSherry.Moore@Sun.COM 		    proc);
28110Sstevel@tonic-gate 		IDN_DUNLOCK(domid);
28120Sstevel@tonic-gate 		return (EINVAL);
28130Sstevel@tonic-gate 	}
28140Sstevel@tonic-gate 	if (cpuid == IDN_NIL_DCPU)
28150Sstevel@tonic-gate 		cpuid = dp->dcpu;
28160Sstevel@tonic-gate 
28170Sstevel@tonic-gate 	ocpuid = dp->dcpu;
28180Sstevel@tonic-gate 	dp->dcpu = cpuid;
28190Sstevel@tonic-gate 
28200Sstevel@tonic-gate 	/*
28210Sstevel@tonic-gate 	 * XXX - Need a special PING IDN command.
28220Sstevel@tonic-gate 	 */
28230Sstevel@tonic-gate 	mt.mt_mtype = IDNP_DATA | IDNP_ACK;
28240Sstevel@tonic-gate 	mt.mt_atype = 0;
28250Sstevel@tonic-gate 
28260Sstevel@tonic-gate 	(void) IDNXDC(domid, &mt, 0x100, 0x200, 0x300, 0x400);
28270Sstevel@tonic-gate 
28280Sstevel@tonic-gate 	dp->dcpu = ocpuid;
28290Sstevel@tonic-gate 	IDN_DUNLOCK(domid);
28300Sstevel@tonic-gate 
28310Sstevel@tonic-gate 	return (0);
28320Sstevel@tonic-gate }
28330Sstevel@tonic-gate 
28340Sstevel@tonic-gate /*
28350Sstevel@tonic-gate  * ----------------------------------------------
28360Sstevel@tonic-gate  */
28370Sstevel@tonic-gate static void
idn_dopers_init()28380Sstevel@tonic-gate idn_dopers_init()
28390Sstevel@tonic-gate {
28400Sstevel@tonic-gate 	int		i;
28410Sstevel@tonic-gate 	dop_waitlist_t	*dwl;
28420Sstevel@tonic-gate 
28430Sstevel@tonic-gate 	if (idn.dopers)
28440Sstevel@tonic-gate 		return;
28450Sstevel@tonic-gate 
28460Sstevel@tonic-gate 	idn.dopers = GETSTRUCT(struct dopers, 1);
28470Sstevel@tonic-gate 
28480Sstevel@tonic-gate 	bzero(idn.dopers, sizeof (struct dopers));
28490Sstevel@tonic-gate 
28500Sstevel@tonic-gate 	dwl = &idn.dopers->_dop_wcache[0];
28510Sstevel@tonic-gate 	for (i = 0; i < (IDNOP_CACHE_SIZE-1); i++)
28520Sstevel@tonic-gate 		dwl[i].dw_next = &dwl[i+1];
28530Sstevel@tonic-gate 	dwl[i].dw_next = NULL;
28540Sstevel@tonic-gate 
28550Sstevel@tonic-gate 	idn.dopers->dop_freelist = &idn.dopers->_dop_wcache[0];
28560Sstevel@tonic-gate 	idn.dopers->dop_waitcount = 0;
28570Sstevel@tonic-gate 	idn.dopers->dop_domset = 0;
28580Sstevel@tonic-gate 	idn.dopers->dop_waitlist = NULL;
28590Sstevel@tonic-gate 
28600Sstevel@tonic-gate 	cv_init(&idn.dopers->dop_cv, NULL, CV_DEFAULT, NULL);
28610Sstevel@tonic-gate 	mutex_init(&idn.dopers->dop_mutex, NULL, MUTEX_DEFAULT, NULL);
28620Sstevel@tonic-gate }
28630Sstevel@tonic-gate 
28640Sstevel@tonic-gate static void
idn_dopers_deinit()28650Sstevel@tonic-gate idn_dopers_deinit()
28660Sstevel@tonic-gate {
28670Sstevel@tonic-gate 	dop_waitlist_t	*dwl, *next_dwl;
28680Sstevel@tonic-gate 
28690Sstevel@tonic-gate 
28700Sstevel@tonic-gate 	if (idn.dopers == NULL)
28710Sstevel@tonic-gate 		return;
28720Sstevel@tonic-gate 
28730Sstevel@tonic-gate 	for (dwl = idn.dopers->dop_waitlist; dwl; dwl = next_dwl) {
28740Sstevel@tonic-gate 		next_dwl = dwl->dw_next;
28750Sstevel@tonic-gate 		if (!IDNOP_IN_CACHE(dwl))
28760Sstevel@tonic-gate 			FREESTRUCT(dwl, dop_waitlist_t, 1);
28770Sstevel@tonic-gate 	}
28780Sstevel@tonic-gate 
28790Sstevel@tonic-gate 	cv_destroy(&idn.dopers->dop_cv);
28800Sstevel@tonic-gate 	mutex_destroy(&idn.dopers->dop_mutex);
28810Sstevel@tonic-gate 
28820Sstevel@tonic-gate 	FREESTRUCT(idn.dopers, struct dopers, 1);
28830Sstevel@tonic-gate 	idn.dopers = NULL;
28840Sstevel@tonic-gate }
28850Sstevel@tonic-gate 
28860Sstevel@tonic-gate /*
28870Sstevel@tonic-gate  * Reset the dop_errset field in preparation for an
28880Sstevel@tonic-gate  * IDN operation attempt.  This is only called from
28890Sstevel@tonic-gate  * idn_link() and idn_unlink().
28900Sstevel@tonic-gate  */
28910Sstevel@tonic-gate void *
idn_init_op(idn_opflag_t opflag,domainset_t domset,idnsb_error_t * sep)28920Sstevel@tonic-gate idn_init_op(idn_opflag_t opflag, domainset_t domset, idnsb_error_t *sep)
28930Sstevel@tonic-gate {
28940Sstevel@tonic-gate 	dop_waitlist_t	*dwl;
28950Sstevel@tonic-gate 	/*
28960Sstevel@tonic-gate 	 * Clear any outstanding error ops in preparation
28970Sstevel@tonic-gate 	 * for an IDN (link/unlink) operation.
28980Sstevel@tonic-gate 	 */
28990Sstevel@tonic-gate 	mutex_enter(&idn.dopers->dop_mutex);
29000Sstevel@tonic-gate 	if ((dwl = idn.dopers->dop_freelist) == NULL) {
29010Sstevel@tonic-gate 		dwl = GETSTRUCT(dop_waitlist_t, 1);
29020Sstevel@tonic-gate 	} else {
29030Sstevel@tonic-gate 		idn.dopers->dop_freelist = dwl->dw_next;
29040Sstevel@tonic-gate 		bzero(dwl, sizeof (*dwl));
29050Sstevel@tonic-gate 	}
29060Sstevel@tonic-gate 	dwl->dw_op = opflag;
29070Sstevel@tonic-gate 	dwl->dw_reqset = domset;
29080Sstevel@tonic-gate 	dwl->dw_idnerr = sep;
29090Sstevel@tonic-gate 	dwl->dw_next = idn.dopers->dop_waitlist;
29100Sstevel@tonic-gate 
29110Sstevel@tonic-gate 	idn.dopers->dop_waitlist = dwl;
29120Sstevel@tonic-gate 	idn.dopers->dop_waitcount++;
29130Sstevel@tonic-gate 	idn.dopers->dop_domset |= domset;
29140Sstevel@tonic-gate 	mutex_exit(&idn.dopers->dop_mutex);
29150Sstevel@tonic-gate 
29160Sstevel@tonic-gate 	return (dwl);
29170Sstevel@tonic-gate }
29180Sstevel@tonic-gate 
29190Sstevel@tonic-gate /*
29200Sstevel@tonic-gate  * Anybody waiting on a opflag operation for any one
29210Sstevel@tonic-gate  * of the domains in domset, needs to be updated to
29220Sstevel@tonic-gate  * additionally wait for new domains in domset.
29230Sstevel@tonic-gate  * This is used, for example, when needing to connect
29240Sstevel@tonic-gate  * to more domains than known at the time of the
29250Sstevel@tonic-gate  * original request.
29260Sstevel@tonic-gate  */
29270Sstevel@tonic-gate void
idn_add_op(idn_opflag_t opflag,domainset_t domset)29280Sstevel@tonic-gate idn_add_op(idn_opflag_t opflag, domainset_t domset)
29290Sstevel@tonic-gate {
29300Sstevel@tonic-gate 	dop_waitlist_t	*dwl;
29310Sstevel@tonic-gate 
29320Sstevel@tonic-gate 	mutex_enter(&idn.dopers->dop_mutex);
29330Sstevel@tonic-gate 	if ((idn.dopers->dop_waitcount == 0) ||
29347656SSherry.Moore@Sun.COM 	    ((idn.dopers->dop_domset & domset) == 0)) {
29350Sstevel@tonic-gate 		mutex_exit(&idn.dopers->dop_mutex);
29360Sstevel@tonic-gate 		return;
29370Sstevel@tonic-gate 	}
29380Sstevel@tonic-gate 	for (dwl = idn.dopers->dop_waitlist; dwl; dwl = dwl->dw_next)
29390Sstevel@tonic-gate 		if ((dwl->dw_op == opflag) && (dwl->dw_reqset & domset))
29400Sstevel@tonic-gate 			dwl->dw_reqset |= domset;
29410Sstevel@tonic-gate 	mutex_exit(&idn.dopers->dop_mutex);
29420Sstevel@tonic-gate }
29430Sstevel@tonic-gate 
29440Sstevel@tonic-gate /*
29450Sstevel@tonic-gate  * Mechanism to wakeup any potential users which may be waiting
29460Sstevel@tonic-gate  * for a link/unlink operation to complete.  If an error occurred
29470Sstevel@tonic-gate  * don't update dop_errset unless there was no previous error.
29480Sstevel@tonic-gate  */
29490Sstevel@tonic-gate void
idn_update_op(idn_opflag_t opflag,domainset_t domset,idnsb_error_t * sep)29500Sstevel@tonic-gate idn_update_op(idn_opflag_t opflag, domainset_t domset, idnsb_error_t *sep)
29510Sstevel@tonic-gate {
29520Sstevel@tonic-gate 	int		do_wakeup = 0;
29530Sstevel@tonic-gate 	dop_waitlist_t	*dw;
29540Sstevel@tonic-gate 	procname_t	proc = "idn_update_op";
29550Sstevel@tonic-gate 
29560Sstevel@tonic-gate 	mutex_enter(&idn.dopers->dop_mutex);
29570Sstevel@tonic-gate 	/*
29580Sstevel@tonic-gate 	 * If there are no waiters, or nobody is waiting for
29590Sstevel@tonic-gate 	 * the particular domainset in question, then
29600Sstevel@tonic-gate 	 * just bail.
29610Sstevel@tonic-gate 	 */
29620Sstevel@tonic-gate 	if ((idn.dopers->dop_waitcount == 0) ||
29637656SSherry.Moore@Sun.COM 	    ((idn.dopers->dop_domset & domset) == 0)) {
29640Sstevel@tonic-gate 		mutex_exit(&idn.dopers->dop_mutex);
29650Sstevel@tonic-gate 		PR_PROTO("%s: NO waiters exist (domset=0x%x)\n",
29667656SSherry.Moore@Sun.COM 		    proc, domset);
29670Sstevel@tonic-gate 		return;
29680Sstevel@tonic-gate 	}
29690Sstevel@tonic-gate 
29700Sstevel@tonic-gate 	for (dw = idn.dopers->dop_waitlist; dw; dw = dw->dw_next) {
29710Sstevel@tonic-gate 		int		d;
29720Sstevel@tonic-gate 		domainset_t	dset, rset;
29730Sstevel@tonic-gate 
29740Sstevel@tonic-gate 		if ((dset = dw->dw_reqset & domset) == 0)
29750Sstevel@tonic-gate 			continue;
29760Sstevel@tonic-gate 
29770Sstevel@tonic-gate 		if (opflag == IDNOP_ERROR) {
29780Sstevel@tonic-gate 			dw->dw_errset |= dset;
29790Sstevel@tonic-gate 			if (sep) {
29800Sstevel@tonic-gate 				for (d = 0; d < MAX_DOMAINS; d++) {
29810Sstevel@tonic-gate 					if (!DOMAIN_IN_SET(dset, d))
29820Sstevel@tonic-gate 						continue;
29830Sstevel@tonic-gate 
29840Sstevel@tonic-gate 					dw->dw_errors[d] =
29857656SSherry.Moore@Sun.COM 					    (short)GET_IDNKERR_ERRNO(sep);
29860Sstevel@tonic-gate 				}
29870Sstevel@tonic-gate 				bcopy(sep, dw->dw_idnerr, sizeof (*sep));
29880Sstevel@tonic-gate 			}
29890Sstevel@tonic-gate 		} else if (opflag == dw->dw_op) {
29900Sstevel@tonic-gate 			dw->dw_domset |= dset;
29910Sstevel@tonic-gate 		}
29920Sstevel@tonic-gate 
29930Sstevel@tonic-gate 		/*
29940Sstevel@tonic-gate 		 * Check if all the domains are spoken for that
29950Sstevel@tonic-gate 		 * a particular waiter may have been waiting for.
29960Sstevel@tonic-gate 		 * If there's at least one, we'll need to broadcast.
29970Sstevel@tonic-gate 		 */
29980Sstevel@tonic-gate 		rset = (dw->dw_errset | dw->dw_domset) & dw->dw_reqset;
29990Sstevel@tonic-gate 		if (rset == dw->dw_reqset)
30000Sstevel@tonic-gate 			do_wakeup++;
30010Sstevel@tonic-gate 	}
30020Sstevel@tonic-gate 
30030Sstevel@tonic-gate 	PR_PROTO("%s: found %d waiters ready for wakeup\n", proc, do_wakeup);
30040Sstevel@tonic-gate 
30050Sstevel@tonic-gate 	if (do_wakeup > 0)
30060Sstevel@tonic-gate 		cv_broadcast(&idn.dopers->dop_cv);
30070Sstevel@tonic-gate 
30080Sstevel@tonic-gate 	mutex_exit(&idn.dopers->dop_mutex);
30090Sstevel@tonic-gate }
30100Sstevel@tonic-gate 
30110Sstevel@tonic-gate void
idn_deinit_op(void * cookie)30120Sstevel@tonic-gate idn_deinit_op(void *cookie)
30130Sstevel@tonic-gate {
30140Sstevel@tonic-gate 	domainset_t	domset;
30150Sstevel@tonic-gate 	dop_waitlist_t	*hw, *tw;
30160Sstevel@tonic-gate 	dop_waitlist_t	*dwl = (dop_waitlist_t *)cookie;
30170Sstevel@tonic-gate 
30180Sstevel@tonic-gate 	mutex_enter(&idn.dopers->dop_mutex);
30190Sstevel@tonic-gate 
30200Sstevel@tonic-gate 	ASSERT(idn.dopers->dop_waitlist);
30210Sstevel@tonic-gate 
30220Sstevel@tonic-gate 	if (dwl == idn.dopers->dop_waitlist) {
30230Sstevel@tonic-gate 		idn.dopers->dop_waitlist = dwl->dw_next;
30240Sstevel@tonic-gate 		if (IDNOP_IN_CACHE(dwl)) {
30250Sstevel@tonic-gate 			dwl->dw_next = idn.dopers->dop_freelist;
30260Sstevel@tonic-gate 			idn.dopers->dop_freelist = dwl;
30270Sstevel@tonic-gate 		} else {
30280Sstevel@tonic-gate 			FREESTRUCT(dwl, dop_waitlist_t, 1);
30290Sstevel@tonic-gate 		}
30300Sstevel@tonic-gate 	} else {
30310Sstevel@tonic-gate 		for (tw = idn.dopers->dop_waitlist, hw = tw->dw_next;
30327656SSherry.Moore@Sun.COM 		    hw;
30337656SSherry.Moore@Sun.COM 		    tw = hw, hw = hw->dw_next) {
30340Sstevel@tonic-gate 			if (dwl == hw)
30350Sstevel@tonic-gate 				break;
30360Sstevel@tonic-gate 		}
30370Sstevel@tonic-gate 		ASSERT(hw);
30380Sstevel@tonic-gate 
30390Sstevel@tonic-gate 		tw->dw_next = hw->dw_next;
30400Sstevel@tonic-gate 	}
30410Sstevel@tonic-gate 
30420Sstevel@tonic-gate 	/*
30430Sstevel@tonic-gate 	 * Recompute domainset for which waiters might be waiting.
30440Sstevel@tonic-gate 	 * It's possible there may be other waiters waiting for
30450Sstevel@tonic-gate 	 * the same domainset that the current waiter that's leaving
30460Sstevel@tonic-gate 	 * may have been waiting for, so we can't simply delete
30470Sstevel@tonic-gate 	 * the leaving waiter's domainset from dop_domset.
30480Sstevel@tonic-gate 	 */
30490Sstevel@tonic-gate 	for (hw = idn.dopers->dop_waitlist, domset = 0; hw; hw = hw->dw_next)
30500Sstevel@tonic-gate 		domset |= hw->dw_reqset;
30510Sstevel@tonic-gate 
30520Sstevel@tonic-gate 	idn.dopers->dop_waitcount--;
30530Sstevel@tonic-gate 	idn.dopers->dop_domset = domset;
30540Sstevel@tonic-gate 
30550Sstevel@tonic-gate 	mutex_exit(&idn.dopers->dop_mutex);
30560Sstevel@tonic-gate }
30570Sstevel@tonic-gate 
30580Sstevel@tonic-gate /*
30590Sstevel@tonic-gate  * Wait until the specified operation succeeds or fails with
30600Sstevel@tonic-gate  * respect to the given domains.  Note the function terminates
30610Sstevel@tonic-gate  * if at least one error occurs.
30620Sstevel@tonic-gate  * This process is necessary since link/unlink operations occur
30630Sstevel@tonic-gate  * asynchronously and we need some way of waiting to find out
30640Sstevel@tonic-gate  * if it indeed completed.
30650Sstevel@tonic-gate  * Timeout value is received indirectly from the SSP and
30660Sstevel@tonic-gate  * represents seconds.
30670Sstevel@tonic-gate  */
30680Sstevel@tonic-gate int
idn_wait_op(void * cookie,domainset_t * domsetp,int wait_timeout)30690Sstevel@tonic-gate idn_wait_op(void *cookie, domainset_t *domsetp, int wait_timeout)
30700Sstevel@tonic-gate {
30710Sstevel@tonic-gate 	int	d, rv, err = 0;
30720Sstevel@tonic-gate 	dop_waitlist_t	*dwl;
30730Sstevel@tonic-gate 
30740Sstevel@tonic-gate 
30750Sstevel@tonic-gate 	dwl = (dop_waitlist_t *)cookie;
30760Sstevel@tonic-gate 
30770Sstevel@tonic-gate 	ASSERT(wait_timeout > 0);
30780Sstevel@tonic-gate 	ASSERT((dwl->dw_op == IDNOP_CONNECTED) ||
30797656SSherry.Moore@Sun.COM 	    (dwl->dw_op == IDNOP_DISCONNECTED));
30800Sstevel@tonic-gate 
30810Sstevel@tonic-gate 	mutex_enter(&idn.dopers->dop_mutex);
30820Sstevel@tonic-gate 
30830Sstevel@tonic-gate 	while (((dwl->dw_domset | dwl->dw_errset) != dwl->dw_reqset) && !err) {
308411066Srafael.vanoni@sun.com 		rv = cv_reltimedwait_sig(&idn.dopers->dop_cv,
308511066Srafael.vanoni@sun.com 		    &idn.dopers->dop_mutex, (wait_timeout * hz), TR_CLOCK_TICK);
30860Sstevel@tonic-gate 
30870Sstevel@tonic-gate 		if ((dwl->dw_domset | dwl->dw_errset) == dwl->dw_reqset)
30880Sstevel@tonic-gate 			break;
30890Sstevel@tonic-gate 
30900Sstevel@tonic-gate 		switch (rv) {
30910Sstevel@tonic-gate 		case -1:
30920Sstevel@tonic-gate 			/*
30930Sstevel@tonic-gate 			 * timed out
30940Sstevel@tonic-gate 			 */
30950Sstevel@tonic-gate 			cmn_err(CE_WARN,
30967656SSherry.Moore@Sun.COM 			    "!IDN: 129: %s operation timed out",
30977656SSherry.Moore@Sun.COM 			    (dwl->dw_op == IDNOP_CONNECTED) ? "LINK" :
30987656SSherry.Moore@Sun.COM 			    (dwl->dw_op == IDNOP_DISCONNECTED) ? "UNLINK" :
30997656SSherry.Moore@Sun.COM 			    "UNKNOWN");
31000Sstevel@tonic-gate 			/*FALLTHROUGH*/
31010Sstevel@tonic-gate 		case 0:
31020Sstevel@tonic-gate 			/*
31030Sstevel@tonic-gate 			 * signal, e.g. kill(2)
31040Sstevel@tonic-gate 			 */
31050Sstevel@tonic-gate 			err = 1;
31060Sstevel@tonic-gate 			break;
31070Sstevel@tonic-gate 
31080Sstevel@tonic-gate 		default:
31090Sstevel@tonic-gate 			break;
31100Sstevel@tonic-gate 		}
31110Sstevel@tonic-gate 	}
31120Sstevel@tonic-gate 
31130Sstevel@tonic-gate 	if (dwl->dw_domset == dwl->dw_reqset) {
31140Sstevel@tonic-gate 		rv = 0;
31150Sstevel@tonic-gate 	} else {
31160Sstevel@tonic-gate 		/*
31170Sstevel@tonic-gate 		 * Op failed for some domains or we were awakened.
31180Sstevel@tonic-gate 		 */
31190Sstevel@tonic-gate 		for (d = rv = 0; (d < MAX_DOMAINS) && !rv; d++)
31200Sstevel@tonic-gate 			rv = dwl->dw_errors[d];
31210Sstevel@tonic-gate 	}
31220Sstevel@tonic-gate 	*domsetp = dwl->dw_domset;
31230Sstevel@tonic-gate 
31240Sstevel@tonic-gate 	mutex_exit(&idn.dopers->dop_mutex);
31250Sstevel@tonic-gate 
31260Sstevel@tonic-gate 	idn_deinit_op(cookie);
31270Sstevel@tonic-gate 
31280Sstevel@tonic-gate 	return (rv);
31290Sstevel@tonic-gate }
31300Sstevel@tonic-gate 
31310Sstevel@tonic-gate /*
31320Sstevel@tonic-gate  * --------------------------------------------------
31330Sstevel@tonic-gate  * Return any valid (& ready) cpuid for the given board based on
31340Sstevel@tonic-gate  * the given cpuset.
31350Sstevel@tonic-gate  * --------------------------------------------------
31360Sstevel@tonic-gate  */
31370Sstevel@tonic-gate int
board_to_ready_cpu(int board,cpuset_t cpuset)31380Sstevel@tonic-gate board_to_ready_cpu(int board, cpuset_t cpuset)
31390Sstevel@tonic-gate {
31400Sstevel@tonic-gate 	int	base_cpuid;
31410Sstevel@tonic-gate 	int	ncpu_board = MAX_CPU_PER_BRD;
31420Sstevel@tonic-gate 
31430Sstevel@tonic-gate 	board *= ncpu_board;
31440Sstevel@tonic-gate 	for (base_cpuid = board;
31457656SSherry.Moore@Sun.COM 	    base_cpuid < (board + ncpu_board);
31467656SSherry.Moore@Sun.COM 	    base_cpuid++)
31470Sstevel@tonic-gate 		if (CPU_IN_SET(cpuset, base_cpuid))
31480Sstevel@tonic-gate 			return (base_cpuid);
31490Sstevel@tonic-gate 
31500Sstevel@tonic-gate 	return (-1);
31510Sstevel@tonic-gate }
31520Sstevel@tonic-gate 
31530Sstevel@tonic-gate void
idn_domain_resetentry(idn_domain_t * dp)31540Sstevel@tonic-gate idn_domain_resetentry(idn_domain_t *dp)
31550Sstevel@tonic-gate {
31560Sstevel@tonic-gate 	register int		i;
31570Sstevel@tonic-gate 	procname_t	proc = "idn_domain_resetentry";
31580Sstevel@tonic-gate 
31590Sstevel@tonic-gate 	ASSERT(dp);
31600Sstevel@tonic-gate 	ASSERT(dp->dstate == IDNDS_CLOSED);
31610Sstevel@tonic-gate 	ASSERT(IDN_DLOCK_IS_EXCL(dp->domid));
31620Sstevel@tonic-gate 	ASSERT(IDN_GLOCK_IS_EXCL());
31630Sstevel@tonic-gate 
31640Sstevel@tonic-gate 	ASSERT(dp->domid == (dp - &idn_domain[0]));
31650Sstevel@tonic-gate 
31660Sstevel@tonic-gate 	IDN_FSTATE_TRANSITION(dp, IDNFIN_OFF);
31670Sstevel@tonic-gate 	dp->dname[0]	= '\0';
31680Sstevel@tonic-gate 	dp->dnetid	= (ushort_t)-1;
31690Sstevel@tonic-gate 	dp->dmtu	= 0;
31700Sstevel@tonic-gate 	dp->dbufsize	= 0;
31710Sstevel@tonic-gate 	dp->dslabsize	= 0;
31720Sstevel@tonic-gate 	dp->dnwrsize	= 0;
31730Sstevel@tonic-gate 	dp->dncpus	= 0;
31740Sstevel@tonic-gate 	dp->dcpuindex   = 0;
31750Sstevel@tonic-gate 	CPUSET_ZERO(dp->dcpuset);
31760Sstevel@tonic-gate 	dp->dcpu	= dp->dcpu_last = dp->dcpu_save = IDN_NIL_DCPU;
31770Sstevel@tonic-gate 	dp->dvote.ticket = 0;
31780Sstevel@tonic-gate 	dp->dslab	= NULL;
31790Sstevel@tonic-gate 	dp->dslab_state = DSLAB_STATE_UNKNOWN;
31800Sstevel@tonic-gate 	dp->dnslabs	= 0;
31810Sstevel@tonic-gate 	dp->dio		= 0;
31820Sstevel@tonic-gate 	dp->dioerr	= 0;
31830Sstevel@tonic-gate 	lock_clear(&dp->diowanted);
31840Sstevel@tonic-gate 	bzero(&dp->dhw, sizeof (dp->dhw));
31850Sstevel@tonic-gate 	dp->dxp		= NULL;
31860Sstevel@tonic-gate 	IDN_XSTATE_TRANSITION(dp, IDNXS_NIL);
31870Sstevel@tonic-gate 	dp->dsync.s_cmd = IDNSYNC_NIL;
31880Sstevel@tonic-gate 	dp->dfin_sync   = IDNFIN_SYNC_OFF;
31890Sstevel@tonic-gate 	IDN_RESET_COOKIES(dp->domid);
31900Sstevel@tonic-gate 	dp->dcookie_err = 0;
31910Sstevel@tonic-gate 	bzero(&dp->dawol, sizeof (dp->dawol));
31920Sstevel@tonic-gate 	dp->dtmp = -1;
31930Sstevel@tonic-gate 
31940Sstevel@tonic-gate 	if (dp->dtimerq.tq_queue != NULL) {
31950Sstevel@tonic-gate 		PR_PROTO("%s: WARNING: MSG timerq not empty (count = %d)\n",
31967656SSherry.Moore@Sun.COM 		    proc, dp->dtimerq.tq_count);
31970Sstevel@tonic-gate 		IDN_MSGTIMER_STOP(dp->domid, 0, 0);
31980Sstevel@tonic-gate 	}
31990Sstevel@tonic-gate 
32000Sstevel@tonic-gate 	for (i = 0; i < NCPU; i++)
32010Sstevel@tonic-gate 		dp->dcpumap[i] = (uchar_t)-1;
32020Sstevel@tonic-gate }
32030Sstevel@tonic-gate 
32040Sstevel@tonic-gate int
idn_open_domain(int domid,int cpuid,uint_t ticket)32050Sstevel@tonic-gate idn_open_domain(int domid, int cpuid, uint_t ticket)
32060Sstevel@tonic-gate {
32070Sstevel@tonic-gate 	int		c, new_cpuid;
32080Sstevel@tonic-gate 	idn_domain_t	*dp, *ldp;
32090Sstevel@tonic-gate 	procname_t	proc = "idn_open_domain";
32100Sstevel@tonic-gate 
32110Sstevel@tonic-gate 	ASSERT(IDN_SYNC_IS_LOCKED());
32120Sstevel@tonic-gate 	ASSERT(IDN_DLOCK_IS_EXCL(domid));
32130Sstevel@tonic-gate 
32140Sstevel@tonic-gate 	if (!VALID_DOMAINID(domid)) {
32150Sstevel@tonic-gate 		PR_PROTO("%s: INVALID domainid (%d) "
32167656SSherry.Moore@Sun.COM 		    "[cpuid = %d, ticket = 0x%x]\n",
32177656SSherry.Moore@Sun.COM 		    proc, domid, cpuid, ticket);
32180Sstevel@tonic-gate 		return (-1);
32190Sstevel@tonic-gate 	}
32200Sstevel@tonic-gate 
32210Sstevel@tonic-gate 	dp = &idn_domain[domid];
32220Sstevel@tonic-gate 	ldp = &idn_domain[idn.localid];
32230Sstevel@tonic-gate 
32240Sstevel@tonic-gate 	if (dp->dcpu >= 0) {
32250Sstevel@tonic-gate 		PR_PROTO("%s:%d: domain already OPEN (state = %s)\n",
32267656SSherry.Moore@Sun.COM 		    proc, domid, idnds_str[dp->dstate]);
32270Sstevel@tonic-gate 		return (1);
32280Sstevel@tonic-gate 	}
32290Sstevel@tonic-gate 
32300Sstevel@tonic-gate 	if (DOMAIN_IN_SET(idn.domset.ds_relink, domid)) {
32310Sstevel@tonic-gate 		if (dp->dcpu_save == IDN_NIL_DCPU)
32320Sstevel@tonic-gate 			new_cpuid = cpuid;
32330Sstevel@tonic-gate 		else
32340Sstevel@tonic-gate 			new_cpuid = dp->dcpu_save;
32350Sstevel@tonic-gate 	} else {
32360Sstevel@tonic-gate 		new_cpuid = cpuid;
32370Sstevel@tonic-gate 	}
32380Sstevel@tonic-gate 
32390Sstevel@tonic-gate 	if (new_cpuid == IDN_NIL_DCPU) {
32400Sstevel@tonic-gate 		PR_PROTO("%s:%d: WARNING: invalid cpuid (%d) specified\n",
32417656SSherry.Moore@Sun.COM 		    proc, domid, new_cpuid);
32420Sstevel@tonic-gate 		return (-1);
32430Sstevel@tonic-gate 	}
32440Sstevel@tonic-gate 
32450Sstevel@tonic-gate 	IDN_GLOCK_EXCL();
32460Sstevel@tonic-gate 
32470Sstevel@tonic-gate 	idn_domain_resetentry(dp);
32480Sstevel@tonic-gate 
32490Sstevel@tonic-gate 	PR_STATE("%s:%d: requested cpuid %d, assigning cpuid %d\n",
32507656SSherry.Moore@Sun.COM 	    proc, domid, cpuid, new_cpuid);
32510Sstevel@tonic-gate 
32520Sstevel@tonic-gate 	idn_assign_cookie(domid);
32530Sstevel@tonic-gate 
32540Sstevel@tonic-gate 	dp->dcpu = dp->dcpu_save = new_cpuid;
32550Sstevel@tonic-gate 	dp->dvote.ticket = ticket;
32560Sstevel@tonic-gate 	CPUSET_ADD(dp->dcpuset, new_cpuid);
32570Sstevel@tonic-gate 	dp->dncpus = 1;
32580Sstevel@tonic-gate 	for (c = 0; c < NCPU; c++)
32590Sstevel@tonic-gate 		dp->dcpumap[c] = (uchar_t)new_cpuid;
32600Sstevel@tonic-gate 	dp->dhw.dh_nboards = 1;
32610Sstevel@tonic-gate 	dp->dhw.dh_boardset = BOARDSET(CPUID_TO_BOARDID(new_cpuid));
32620Sstevel@tonic-gate 
32630Sstevel@tonic-gate 	if (domid != idn.localid)
32640Sstevel@tonic-gate 		IDN_DLOCK_EXCL(idn.localid);
32650Sstevel@tonic-gate 
32660Sstevel@tonic-gate 	if (idn.ndomains == 1) {
32670Sstevel@tonic-gate 		struct hwconfig	local_hw;
32680Sstevel@tonic-gate 
32690Sstevel@tonic-gate 		/*
32700Sstevel@tonic-gate 		 * We're attempting to connect to our first domain.
32710Sstevel@tonic-gate 		 * Recheck our local hardware configuration before
32720Sstevel@tonic-gate 		 * we go any further in case it changed due to a DR,
32730Sstevel@tonic-gate 		 * and update any structs dependent on this.
32740Sstevel@tonic-gate 		 * ASSUMPTION:
32750Sstevel@tonic-gate 		 *	IDN is unlinked before performing any DRs.
32760Sstevel@tonic-gate 		 */
32770Sstevel@tonic-gate 		PR_PROTO("%s: RECHECKING local HW config.\n", proc);
32780Sstevel@tonic-gate 		if (get_hw_config(&local_hw)) {
32790Sstevel@tonic-gate 			dp->dcpu = IDN_NIL_DCPU;
32800Sstevel@tonic-gate 			cmn_err(CE_WARN,
32817656SSherry.Moore@Sun.COM 			    "IDN: 118: hardware config not appropriate");
32820Sstevel@tonic-gate 			if (domid != idn.localid)
32830Sstevel@tonic-gate 				IDN_DUNLOCK(idn.localid);
32840Sstevel@tonic-gate 			IDN_GUNLOCK();
32850Sstevel@tonic-gate 			return (-1);
32860Sstevel@tonic-gate 		}
32870Sstevel@tonic-gate 		(void) update_local_hw_config(ldp, &local_hw);
32880Sstevel@tonic-gate 	}
32890Sstevel@tonic-gate 
32900Sstevel@tonic-gate 	idn.ndomains++;
32910Sstevel@tonic-gate 
32920Sstevel@tonic-gate 	if (domid != idn.localid)
32930Sstevel@tonic-gate 		IDN_DUNLOCK(idn.localid);
32940Sstevel@tonic-gate 	IDN_GUNLOCK();
32950Sstevel@tonic-gate 
32960Sstevel@tonic-gate 	IDN_MBOX_LOCK(domid);
32970Sstevel@tonic-gate 	dp->dmbox.m_tbl = NULL;
32980Sstevel@tonic-gate 
32990Sstevel@tonic-gate 	if (domid != idn.localid) {
33000Sstevel@tonic-gate 		dp->dmbox.m_send = idn_mainmbox_init(domid,
33017656SSherry.Moore@Sun.COM 		    IDNMMBOX_TYPE_SEND);
33020Sstevel@tonic-gate 		dp->dmbox.m_recv = idn_mainmbox_init(domid,
33037656SSherry.Moore@Sun.COM 		    IDNMMBOX_TYPE_RECV);
33040Sstevel@tonic-gate 	} else {
33050Sstevel@tonic-gate 		/*
33060Sstevel@tonic-gate 		 * The local domain does not need send/recv
33070Sstevel@tonic-gate 		 * mailboxes in its idn_domain[] entry.
33080Sstevel@tonic-gate 		 */
33090Sstevel@tonic-gate 		dp->dmbox.m_send = NULL;
33100Sstevel@tonic-gate 		dp->dmbox.m_recv = NULL;
33110Sstevel@tonic-gate 	}
33120Sstevel@tonic-gate 	IDN_MBOX_UNLOCK(domid);
33130Sstevel@tonic-gate 
33140Sstevel@tonic-gate 	PR_PROTO("%s:%d: new domain (cpu = %d, vote = 0x%x)\n",
33157656SSherry.Moore@Sun.COM 	    proc, domid, dp->dcpu, dp->dvote.ticket);
33160Sstevel@tonic-gate 
33170Sstevel@tonic-gate 	return (0);
33180Sstevel@tonic-gate }
33190Sstevel@tonic-gate 
33200Sstevel@tonic-gate /*
33210Sstevel@tonic-gate  * The local domain never "closes" itself unless the driver
33220Sstevel@tonic-gate  * is doing a idndetach.  It will be reopened during idnattach
33230Sstevel@tonic-gate  * when idn_domains_init is called.
33240Sstevel@tonic-gate  */
33250Sstevel@tonic-gate void
idn_close_domain(int domid)33260Sstevel@tonic-gate idn_close_domain(int domid)
33270Sstevel@tonic-gate {
33280Sstevel@tonic-gate 	uint_t		token;
33290Sstevel@tonic-gate 	idn_domain_t	*dp;
33300Sstevel@tonic-gate 	procname_t	proc = "idn_close_domain";
33310Sstevel@tonic-gate 
33320Sstevel@tonic-gate 	ASSERT(IDN_SYNC_IS_LOCKED());
33330Sstevel@tonic-gate 	ASSERT(IDN_DLOCK_IS_EXCL(domid));
33340Sstevel@tonic-gate 
33350Sstevel@tonic-gate 	dp = &idn_domain[domid];
33360Sstevel@tonic-gate 
33370Sstevel@tonic-gate 	ASSERT(dp->dstate == IDNDS_CLOSED);
33380Sstevel@tonic-gate 
33390Sstevel@tonic-gate 	if (dp->dcpu == IDN_NIL_DCPU) {
33400Sstevel@tonic-gate 		PR_PROTO("%s:%d: DOMAIN ALREADY CLOSED!\n",
33417656SSherry.Moore@Sun.COM 		    proc, domid);
33420Sstevel@tonic-gate 		return;
33430Sstevel@tonic-gate 	}
33440Sstevel@tonic-gate 
33450Sstevel@tonic-gate 	token = IDN_RETRY_TOKEN(domid, IDN_RETRY_TYPEALL);
33460Sstevel@tonic-gate 
33470Sstevel@tonic-gate 	(void) idn_retry_terminate(token);
33480Sstevel@tonic-gate 
33490Sstevel@tonic-gate 	DOMAINSET_DEL(idn.domset.ds_trans_on, domid);
33500Sstevel@tonic-gate 	DOMAINSET_DEL(idn.domset.ds_ready_on, domid);
33510Sstevel@tonic-gate 	DOMAINSET_DEL(idn.domset.ds_connected, domid);
33520Sstevel@tonic-gate 	DOMAINSET_DEL(idn.domset.ds_trans_off, domid);
33530Sstevel@tonic-gate 	DOMAINSET_DEL(idn.domset.ds_ready_off, domid);
33540Sstevel@tonic-gate 	DOMAINSET_DEL(idn.domset.ds_hwlinked, domid);
33550Sstevel@tonic-gate 	DOMAINSET_DEL(idn.domset.ds_flush, domid);
33560Sstevel@tonic-gate 
33570Sstevel@tonic-gate 	idn_sync_exit(domid, IDNSYNC_CONNECT);
33580Sstevel@tonic-gate 	idn_sync_exit(domid, IDNSYNC_DISCONNECT);
33590Sstevel@tonic-gate 
33600Sstevel@tonic-gate 	IDN_GLOCK_EXCL();
33610Sstevel@tonic-gate 
33620Sstevel@tonic-gate 	if (DOMAIN_IN_SET(idn.domset.ds_awol, domid))
33630Sstevel@tonic-gate 		idn_clear_awol(domid);
33640Sstevel@tonic-gate 
33650Sstevel@tonic-gate 	idn.ndomains--;
33660Sstevel@tonic-gate 
33670Sstevel@tonic-gate 	IDN_GUNLOCK();
33680Sstevel@tonic-gate 
33690Sstevel@tonic-gate 	IDN_MBOX_LOCK(domid);
33700Sstevel@tonic-gate 	dp->dmbox.m_tbl = NULL;
33710Sstevel@tonic-gate 
33720Sstevel@tonic-gate 	if (dp->dmbox.m_send)  {
33730Sstevel@tonic-gate 		idn_mainmbox_deinit(domid, dp->dmbox.m_send);
33740Sstevel@tonic-gate 		dp->dmbox.m_send = NULL;
33750Sstevel@tonic-gate 	}
33760Sstevel@tonic-gate 
33770Sstevel@tonic-gate 	if (dp->dmbox.m_recv) {
33780Sstevel@tonic-gate 		idn_mainmbox_deinit(domid, dp->dmbox.m_recv);
33790Sstevel@tonic-gate 		dp->dmbox.m_recv = NULL;
33800Sstevel@tonic-gate 	}
33810Sstevel@tonic-gate 
33820Sstevel@tonic-gate 	IDN_MBOX_UNLOCK(domid);
33830Sstevel@tonic-gate 
33840Sstevel@tonic-gate 	cmn_err(CE_NOTE,
33857656SSherry.Moore@Sun.COM 	    "!IDN: 142: link (domain %d, CPU %d) disconnected",
33867656SSherry.Moore@Sun.COM 	    dp->domid, dp->dcpu);
33870Sstevel@tonic-gate 
33880Sstevel@tonic-gate 	dp->dcpu = IDN_NIL_DCPU;	/* ultimate demise */
33890Sstevel@tonic-gate 
33900Sstevel@tonic-gate 	IDN_RESET_COOKIES(domid);
33910Sstevel@tonic-gate 
33920Sstevel@tonic-gate 	ASSERT(dp->dio <= 0);
33930Sstevel@tonic-gate 	ASSERT(dp->dioerr == 0);
33940Sstevel@tonic-gate 	ASSERT(dp->dslab == NULL);
33950Sstevel@tonic-gate 	ASSERT(dp->dnslabs == 0);
33960Sstevel@tonic-gate 
33970Sstevel@tonic-gate 	IDN_GKSTAT_GLOBAL_EVENT(gk_unlinks, gk_unlink_last);
33980Sstevel@tonic-gate }
33990Sstevel@tonic-gate 
34000Sstevel@tonic-gate 
34010Sstevel@tonic-gate /*
34020Sstevel@tonic-gate  * -----------------------------------------------------------------------
34030Sstevel@tonic-gate  */
34040Sstevel@tonic-gate static void
idn_domains_init(struct hwconfig * local_hw)34050Sstevel@tonic-gate idn_domains_init(struct hwconfig *local_hw)
34060Sstevel@tonic-gate {
34070Sstevel@tonic-gate 	register int		i, d;
34080Sstevel@tonic-gate 	idn_domain_t		*ldp;
34090Sstevel@tonic-gate 	uchar_t			*cpumap;
34100Sstevel@tonic-gate 
34110Sstevel@tonic-gate 	ASSERT(local_hw != NULL);
34120Sstevel@tonic-gate 
34130Sstevel@tonic-gate 	cpumap = GETSTRUCT(uchar_t, NCPU * MAX_DOMAINS);
34140Sstevel@tonic-gate 
34150Sstevel@tonic-gate 	for (d = 0; d < MAX_DOMAINS; d++) {
34160Sstevel@tonic-gate 		register idn_domain_t	*dp;
34170Sstevel@tonic-gate 
34180Sstevel@tonic-gate 		dp = &idn_domain[d];
34190Sstevel@tonic-gate 
34200Sstevel@tonic-gate 		dp->domid = d;
34210Sstevel@tonic-gate 
34220Sstevel@tonic-gate 		rw_init(&dp->drwlock, NULL, RW_DEFAULT, NULL);
34230Sstevel@tonic-gate 
34240Sstevel@tonic-gate 		IDN_TIMERQ_INIT(&dp->dtimerq);
34250Sstevel@tonic-gate 
34260Sstevel@tonic-gate 		dp->dstate = IDNDS_CLOSED;
34270Sstevel@tonic-gate 
34280Sstevel@tonic-gate 		mutex_init(&dp->dmbox.m_mutex, NULL, MUTEX_DEFAULT, NULL);
34290Sstevel@tonic-gate 
34300Sstevel@tonic-gate 		dp->dcpumap = cpumap;
34310Sstevel@tonic-gate 
34320Sstevel@tonic-gate 		rw_init(&dp->dslab_rwlock, NULL, RW_DEFAULT, NULL);
34330Sstevel@tonic-gate 
34340Sstevel@tonic-gate 		IDN_DLOCK_EXCL(d);
34350Sstevel@tonic-gate 		IDN_GLOCK_EXCL();
34360Sstevel@tonic-gate 
34370Sstevel@tonic-gate 		idn_domain_resetentry(dp);
34380Sstevel@tonic-gate 
34390Sstevel@tonic-gate 		IDN_GUNLOCK();
34400Sstevel@tonic-gate 
34410Sstevel@tonic-gate 		IDNSB_DOMAIN_UPDATE(dp);
34420Sstevel@tonic-gate 
34430Sstevel@tonic-gate 		IDN_DUNLOCK(d);
34440Sstevel@tonic-gate 
34450Sstevel@tonic-gate 		cpumap += NCPU;
34460Sstevel@tonic-gate 	}
34470Sstevel@tonic-gate 
34480Sstevel@tonic-gate 	IDN_SYNC_LOCK();
34490Sstevel@tonic-gate 
34500Sstevel@tonic-gate 	/*
34510Sstevel@tonic-gate 	 * Update local domain information.
34520Sstevel@tonic-gate 	 */
34530Sstevel@tonic-gate 	ASSERT(idn.smr.locpfn);
34540Sstevel@tonic-gate 	ASSERT(local_hw->dh_nboards && local_hw->dh_boardset);
34550Sstevel@tonic-gate 
34560Sstevel@tonic-gate 	idn.ndomains = 0;	/* note that open_domain will get us to 1 */
34570Sstevel@tonic-gate 
34580Sstevel@tonic-gate 	IDN_DLOCK_EXCL(idn.localid);
34590Sstevel@tonic-gate 	d = idn_open_domain(idn.localid, (int)CPU->cpu_id, 0);
34600Sstevel@tonic-gate 	ASSERT(d == 0);
34610Sstevel@tonic-gate 	IDN_GLOCK_EXCL();
34620Sstevel@tonic-gate 	IDN_SET_MASTERID(IDN_NIL_DOMID);
34630Sstevel@tonic-gate 	IDN_SET_NEW_MASTERID(IDN_NIL_DOMID);
34640Sstevel@tonic-gate 
34650Sstevel@tonic-gate 	ldp = &idn_domain[idn.localid];
34660Sstevel@tonic-gate 
3467*11311SSurya.Prakki@Sun.COM 	(void) strncpy(ldp->dname, utsname.nodename, MAXDNAME - 1);
34680Sstevel@tonic-gate 	ldp->dname[MAXDNAME-1] = '\0';
34690Sstevel@tonic-gate 	bcopy(local_hw, &ldp->dhw, sizeof (ldp->dhw));
34700Sstevel@tonic-gate 	ASSERT(idn.ndomains == 1);
34710Sstevel@tonic-gate 	ASSERT((ldp->dhw.dh_nboards > 0) &&
34727656SSherry.Moore@Sun.COM 	    (ldp->dhw.dh_nboards <= MAX_BOARDS));
34730Sstevel@tonic-gate 	ldp->dnetid	= IDN_DOMID2NETID(ldp->domid);
34740Sstevel@tonic-gate 	ldp->dmtu	= IDN_MTU;
34750Sstevel@tonic-gate 	ldp->dbufsize	= IDN_SMR_BUFSIZE;
34760Sstevel@tonic-gate 	ldp->dslabsize	= (short)IDN_SLAB_BUFCOUNT;
34770Sstevel@tonic-gate 	ldp->dnwrsize	= (short)IDN_NWR_SIZE;
34780Sstevel@tonic-gate 	ldp->dcpuset	= cpu_ready_set;
34790Sstevel@tonic-gate 	ldp->dncpus	= (short)ncpus;
34800Sstevel@tonic-gate 	ldp->dvote.ticket	= IDNVOTE_INITIAL_TICKET;
34810Sstevel@tonic-gate 	ldp->dvote.v.master	= 0;
34820Sstevel@tonic-gate 	ldp->dvote.v.nmembrds	= ldp->dhw.dh_nmcadr - 1;
34830Sstevel@tonic-gate 	ldp->dvote.v.ncpus	= (int)ldp->dncpus - 1;
34840Sstevel@tonic-gate 	ldp->dvote.v.board	= CPUID_TO_BOARDID(ldp->dcpu);
34850Sstevel@tonic-gate 	i = -1;
34860Sstevel@tonic-gate 	for (d = 0; d < NCPU; d++) {
34870Sstevel@tonic-gate 		BUMP_INDEX(ldp->dcpuset, i);
34880Sstevel@tonic-gate 		ldp->dcpumap[d] = (uchar_t)i;
34890Sstevel@tonic-gate 	}
34900Sstevel@tonic-gate 
34910Sstevel@tonic-gate 	CPUSET_ZERO(idn.dc_cpuset);
34920Sstevel@tonic-gate 	CPUSET_OR(idn.dc_cpuset, ldp->dcpuset);
34930Sstevel@tonic-gate 	idn.dc_boardset = ldp->dhw.dh_boardset;
34940Sstevel@tonic-gate 
34950Sstevel@tonic-gate 	/*
34960Sstevel@tonic-gate 	 * Setting the state for ourselves is only relevant
34970Sstevel@tonic-gate 	 * for loopback performance testing.  Anyway, it
34980Sstevel@tonic-gate 	 * makes sense that we always have an established
34990Sstevel@tonic-gate 	 * connection with ourself regardless of IDN :-o
35000Sstevel@tonic-gate 	 */
35010Sstevel@tonic-gate 	IDN_DSTATE_TRANSITION(ldp, IDNDS_CONNECTED);
35020Sstevel@tonic-gate 
35030Sstevel@tonic-gate 	IDN_GUNLOCK();
35040Sstevel@tonic-gate 	IDN_DUNLOCK(idn.localid);
35050Sstevel@tonic-gate 	IDN_SYNC_UNLOCK();
35060Sstevel@tonic-gate }
35070Sstevel@tonic-gate 
35080Sstevel@tonic-gate static void
idn_domains_deinit()35090Sstevel@tonic-gate idn_domains_deinit()
35100Sstevel@tonic-gate {
35110Sstevel@tonic-gate 	register int	d;
35120Sstevel@tonic-gate 
35130Sstevel@tonic-gate 	IDN_SYNC_LOCK();
35140Sstevel@tonic-gate 	IDN_DLOCK_EXCL(idn.localid);
35150Sstevel@tonic-gate 	IDN_DSTATE_TRANSITION(&idn_domain[idn.localid], IDNDS_CLOSED);
35160Sstevel@tonic-gate 	idn_close_domain(idn.localid);
35170Sstevel@tonic-gate 	IDN_DUNLOCK(idn.localid);
35180Sstevel@tonic-gate 	IDN_SYNC_UNLOCK();
35190Sstevel@tonic-gate 	idn.localid = IDN_NIL_DOMID;
35200Sstevel@tonic-gate 
35210Sstevel@tonic-gate 	FREESTRUCT(idn_domain[0].dcpumap, uchar_t, NCPU * MAX_DOMAINS);
35220Sstevel@tonic-gate 
35230Sstevel@tonic-gate 	for (d = 0; d < MAX_DOMAINS; d++) {
35240Sstevel@tonic-gate 		idn_domain_t	*dp;
35250Sstevel@tonic-gate 
35260Sstevel@tonic-gate 		dp = &idn_domain[d];
35270Sstevel@tonic-gate 
35280Sstevel@tonic-gate 		rw_destroy(&dp->dslab_rwlock);
35290Sstevel@tonic-gate 		mutex_destroy(&dp->dmbox.m_mutex);
35300Sstevel@tonic-gate 		rw_destroy(&dp->drwlock);
35310Sstevel@tonic-gate 		IDN_TIMERQ_DEINIT(&dp->dtimerq);
35320Sstevel@tonic-gate 		dp->dcpumap = NULL;
35330Sstevel@tonic-gate 	}
35340Sstevel@tonic-gate }
35350Sstevel@tonic-gate 
35360Sstevel@tonic-gate /*
35370Sstevel@tonic-gate  * -----------------------------------------------------------------------
35380Sstevel@tonic-gate  */
35390Sstevel@tonic-gate static void
idn_retrytask_init()35400Sstevel@tonic-gate idn_retrytask_init()
35410Sstevel@tonic-gate {
35420Sstevel@tonic-gate 	ASSERT(idn.retryqueue.rq_cache == NULL);
35430Sstevel@tonic-gate 
35440Sstevel@tonic-gate 	mutex_init(&idn.retryqueue.rq_mutex, NULL, MUTEX_DEFAULT, NULL);
35450Sstevel@tonic-gate 	idn.retryqueue.rq_cache = kmem_cache_create("idn_retryjob_cache",
35467656SSherry.Moore@Sun.COM 	    sizeof (idn_retry_job_t),
35477656SSherry.Moore@Sun.COM 	    0, NULL, NULL, NULL,
35487656SSherry.Moore@Sun.COM 	    NULL, NULL, 0);
35490Sstevel@tonic-gate }
35500Sstevel@tonic-gate 
35510Sstevel@tonic-gate static void
idn_retrytask_deinit()35520Sstevel@tonic-gate idn_retrytask_deinit()
35530Sstevel@tonic-gate {
35540Sstevel@tonic-gate 	if (idn.retryqueue.rq_cache == NULL)
35550Sstevel@tonic-gate 		return;
35560Sstevel@tonic-gate 
35570Sstevel@tonic-gate 	kmem_cache_destroy(idn.retryqueue.rq_cache);
35580Sstevel@tonic-gate 	mutex_destroy(&idn.retryqueue.rq_mutex);
35590Sstevel@tonic-gate 
35600Sstevel@tonic-gate 	bzero(&idn.retryqueue, sizeof (idn.retryqueue));
35610Sstevel@tonic-gate }
35620Sstevel@tonic-gate 
35630Sstevel@tonic-gate /*
35640Sstevel@tonic-gate  * -----------------------------------------------------------------------
35650Sstevel@tonic-gate  */
35660Sstevel@tonic-gate static void
idn_timercache_init()35670Sstevel@tonic-gate idn_timercache_init()
35680Sstevel@tonic-gate {
35690Sstevel@tonic-gate 	ASSERT(idn.timer_cache == NULL);
35700Sstevel@tonic-gate 
35710Sstevel@tonic-gate 	idn.timer_cache = kmem_cache_create("idn_timer_cache",
35727656SSherry.Moore@Sun.COM 	    sizeof (idn_timer_t),
35737656SSherry.Moore@Sun.COM 	    0, NULL, NULL, NULL,
35747656SSherry.Moore@Sun.COM 	    NULL, NULL, 0);
35750Sstevel@tonic-gate }
35760Sstevel@tonic-gate 
35770Sstevel@tonic-gate static void
idn_timercache_deinit()35780Sstevel@tonic-gate idn_timercache_deinit()
35790Sstevel@tonic-gate {
35800Sstevel@tonic-gate 	if (idn.timer_cache == NULL)
35810Sstevel@tonic-gate 		return;
35820Sstevel@tonic-gate 
35830Sstevel@tonic-gate 	kmem_cache_destroy(idn.timer_cache);
35840Sstevel@tonic-gate 	idn.timer_cache = NULL;
35850Sstevel@tonic-gate }
35860Sstevel@tonic-gate 
35870Sstevel@tonic-gate idn_timer_t *
idn_timer_alloc()35880Sstevel@tonic-gate idn_timer_alloc()
35890Sstevel@tonic-gate {
35900Sstevel@tonic-gate 	idn_timer_t	*tp;
35910Sstevel@tonic-gate 
35920Sstevel@tonic-gate 	tp = kmem_cache_alloc(idn.timer_cache, KM_SLEEP);
35930Sstevel@tonic-gate 	bzero(tp, sizeof (*tp));
35940Sstevel@tonic-gate 	tp->t_forw = tp->t_back = tp;
35950Sstevel@tonic-gate 
35960Sstevel@tonic-gate 	return (tp);
35970Sstevel@tonic-gate }
35980Sstevel@tonic-gate 
35990Sstevel@tonic-gate void
idn_timer_free(idn_timer_t * tp)36000Sstevel@tonic-gate idn_timer_free(idn_timer_t *tp)
36010Sstevel@tonic-gate {
36020Sstevel@tonic-gate 	if (tp == NULL)
36030Sstevel@tonic-gate 		return;
36040Sstevel@tonic-gate 	kmem_cache_free(idn.timer_cache, tp);
36050Sstevel@tonic-gate }
36060Sstevel@tonic-gate 
36070Sstevel@tonic-gate void
idn_timerq_init(idn_timerq_t * tq)36080Sstevel@tonic-gate idn_timerq_init(idn_timerq_t *tq)
36090Sstevel@tonic-gate {
36100Sstevel@tonic-gate 	mutex_init(&tq->tq_mutex, NULL, MUTEX_DEFAULT, NULL);
36110Sstevel@tonic-gate 	tq->tq_count = 0;
36120Sstevel@tonic-gate 	tq->tq_queue = NULL;
36130Sstevel@tonic-gate }
36140Sstevel@tonic-gate 
36150Sstevel@tonic-gate void
idn_timerq_deinit(idn_timerq_t * tq)36160Sstevel@tonic-gate idn_timerq_deinit(idn_timerq_t *tq)
36170Sstevel@tonic-gate {
36180Sstevel@tonic-gate 	ASSERT(tq->tq_queue == NULL);
36190Sstevel@tonic-gate 	mutex_destroy(&tq->tq_mutex);
36200Sstevel@tonic-gate }
36210Sstevel@tonic-gate 
36220Sstevel@tonic-gate /*
36230Sstevel@tonic-gate  * Dequeue all the timers of the given subtype from the
36240Sstevel@tonic-gate  * given timerQ.  If subtype is 0, then dequeue all the
36250Sstevel@tonic-gate  * timers.
36260Sstevel@tonic-gate  */
36270Sstevel@tonic-gate idn_timer_t *
idn_timer_get(idn_timerq_t * tq,int type,ushort_t tcookie)36280Sstevel@tonic-gate idn_timer_get(idn_timerq_t *tq, int type, ushort_t tcookie)
36290Sstevel@tonic-gate {
36300Sstevel@tonic-gate 	register idn_timer_t	*tp, *tphead;
36310Sstevel@tonic-gate 
36320Sstevel@tonic-gate 	ASSERT(IDN_TIMERQ_IS_LOCKED(tq));
36330Sstevel@tonic-gate 
36340Sstevel@tonic-gate 	if ((tp = tq->tq_queue) == NULL)
36350Sstevel@tonic-gate 		return (NULL);
36360Sstevel@tonic-gate 
36370Sstevel@tonic-gate 	if (!type) {
36380Sstevel@tonic-gate 		tq->tq_queue = NULL;
36390Sstevel@tonic-gate 		tq->tq_count = 0;
36400Sstevel@tonic-gate 		tphead = tp;
36410Sstevel@tonic-gate 	} else {
36420Sstevel@tonic-gate 		int		count;
36430Sstevel@tonic-gate 		idn_timer_t	*tpnext;
36440Sstevel@tonic-gate 
36450Sstevel@tonic-gate 		tphead = NULL;
36460Sstevel@tonic-gate 		count = tq->tq_count;
36470Sstevel@tonic-gate 		do {
36480Sstevel@tonic-gate 			tpnext = tp->t_forw;
36490Sstevel@tonic-gate 			if ((tp->t_type == type) &&
36507656SSherry.Moore@Sun.COM 			    (!tcookie || (tp->t_cookie == tcookie))) {
36510Sstevel@tonic-gate 				tp->t_forw->t_back = tp->t_back;
36520Sstevel@tonic-gate 				tp->t_back->t_forw = tp->t_forw;
36530Sstevel@tonic-gate 				if (tphead == NULL) {
36540Sstevel@tonic-gate 					tp->t_forw = tp->t_back = tp;
36550Sstevel@tonic-gate 				} else {
36560Sstevel@tonic-gate 					tp->t_forw = tphead;
36570Sstevel@tonic-gate 					tp->t_back = tphead->t_back;
36580Sstevel@tonic-gate 					tp->t_back->t_forw = tp;
36590Sstevel@tonic-gate 					tphead->t_back = tp;
36600Sstevel@tonic-gate 				}
36610Sstevel@tonic-gate 				tphead = tp;
36620Sstevel@tonic-gate 				if (--(tq->tq_count) == 0)
36630Sstevel@tonic-gate 					tq->tq_queue = NULL;
36640Sstevel@tonic-gate 				else if (tq->tq_queue == tp)
36650Sstevel@tonic-gate 					tq->tq_queue = tpnext;
36660Sstevel@tonic-gate 			}
36670Sstevel@tonic-gate 			tp = tpnext;
36680Sstevel@tonic-gate 		} while (--count > 0);
36690Sstevel@tonic-gate 	}
36700Sstevel@tonic-gate 
36710Sstevel@tonic-gate 	if (tphead) {
36720Sstevel@tonic-gate 		tphead->t_back->t_forw = NULL;
36730Sstevel@tonic-gate 
36740Sstevel@tonic-gate 		for (tp = tphead; tp; tp = tp->t_forw)
36750Sstevel@tonic-gate 			tp->t_onq = 0;
36760Sstevel@tonic-gate 	}
36770Sstevel@tonic-gate 
36780Sstevel@tonic-gate 	return (tphead);
36790Sstevel@tonic-gate }
36800Sstevel@tonic-gate 
36810Sstevel@tonic-gate ushort_t
idn_timer_start(idn_timerq_t * tq,idn_timer_t * tp,clock_t tval)36820Sstevel@tonic-gate idn_timer_start(idn_timerq_t *tq, idn_timer_t *tp, clock_t tval)
36830Sstevel@tonic-gate {
36840Sstevel@tonic-gate 	idn_timer_t	*otp;
36850Sstevel@tonic-gate 	ushort_t	tcookie;
36860Sstevel@tonic-gate 	procname_t	proc = "idn_timer_start";
36870Sstevel@tonic-gate 	STRING(str);
36880Sstevel@tonic-gate 
36890Sstevel@tonic-gate 	ASSERT(tq && tp && (tval > 0));
36900Sstevel@tonic-gate 	ASSERT((tp->t_forw == tp) && (tp->t_back == tp));
36910Sstevel@tonic-gate 	ASSERT(tp->t_type != 0);
36920Sstevel@tonic-gate 
36930Sstevel@tonic-gate 	IDN_TIMERQ_LOCK(tq);
36940Sstevel@tonic-gate 	/*
36950Sstevel@tonic-gate 	 * Assign a unique non-zero 8-bit cookie to this timer
36960Sstevel@tonic-gate 	 * if the caller hasn't already preassigned one.
36970Sstevel@tonic-gate 	 */
36980Sstevel@tonic-gate 	while ((tcookie = tp->t_cookie) == 0) {
36990Sstevel@tonic-gate 		tp->t_cookie = (tp->t_type & 0xf) |
37007656SSherry.Moore@Sun.COM 		    ((++tq->tq_cookie & 0xf) << 4);
37010Sstevel@tonic-gate 		/*
37020Sstevel@tonic-gate 		 * Calculated cookie must never conflict
37030Sstevel@tonic-gate 		 * with the public timer cookie.
37040Sstevel@tonic-gate 		 */
37050Sstevel@tonic-gate 		ASSERT(tp->t_cookie != IDN_TIMER_PUBLIC_COOKIE);
37060Sstevel@tonic-gate 	}
37070Sstevel@tonic-gate 
37080Sstevel@tonic-gate 	/*
37090Sstevel@tonic-gate 	 * First have to remove old timers of the
37100Sstevel@tonic-gate 	 * same type and cookie, and get rid of them.
37110Sstevel@tonic-gate 	 */
37120Sstevel@tonic-gate 	otp = idn_timer_get(tq, tp->t_type, tcookie);
37130Sstevel@tonic-gate 
37140Sstevel@tonic-gate 	tq->tq_count++;
37150Sstevel@tonic-gate 
37160Sstevel@tonic-gate 	if (tq->tq_queue == NULL) {
37170Sstevel@tonic-gate 		tq->tq_queue = tp;
37180Sstevel@tonic-gate 		ASSERT((tp->t_forw == tp) && (tp->t_back == tp));
37190Sstevel@tonic-gate 	} else {
37200Sstevel@tonic-gate 		/*
37210Sstevel@tonic-gate 		 * Put me at the end of the list.
37220Sstevel@tonic-gate 		 */
37230Sstevel@tonic-gate 		tp->t_forw = tq->tq_queue;
37240Sstevel@tonic-gate 		tp->t_back = tq->tq_queue->t_back;
37250Sstevel@tonic-gate 		tp->t_back->t_forw = tp;
37260Sstevel@tonic-gate 		tp->t_forw->t_back = tp;
37270Sstevel@tonic-gate 	}
37280Sstevel@tonic-gate 
37290Sstevel@tonic-gate 	tp->t_onq = 1;
37300Sstevel@tonic-gate 	tp->t_q = tq;
37310Sstevel@tonic-gate 	tp->t_id = timeout(idn_timer_expired, (caddr_t)tp, tval);
37320Sstevel@tonic-gate 
37330Sstevel@tonic-gate 
37340Sstevel@tonic-gate 	INUM2STR(tp->t_type, str);
37350Sstevel@tonic-gate 	PR_TIMER("%s: started %s timer (domain = %d, cookie = 0x%x)\n",
37367656SSherry.Moore@Sun.COM 	    proc, str, tp->t_domid, tcookie);
37370Sstevel@tonic-gate 
37380Sstevel@tonic-gate 	IDN_TIMERQ_UNLOCK(tq);
37390Sstevel@tonic-gate 
37400Sstevel@tonic-gate 	if (otp)
37410Sstevel@tonic-gate 		(void) idn_timer_stopall(otp);
37420Sstevel@tonic-gate 
37430Sstevel@tonic-gate 	return (tcookie);
37440Sstevel@tonic-gate }
37450Sstevel@tonic-gate 
37460Sstevel@tonic-gate /*
37470Sstevel@tonic-gate  * Stop all timers of the given subtype.
37480Sstevel@tonic-gate  * If subtype is 0, then stop all timers
37490Sstevel@tonic-gate  * in this timerQ.
37500Sstevel@tonic-gate  */
37510Sstevel@tonic-gate void
idn_timer_stop(idn_timerq_t * tq,int type,ushort_t tcookie)37520Sstevel@tonic-gate idn_timer_stop(idn_timerq_t *tq, int type, ushort_t tcookie)
37530Sstevel@tonic-gate {
37540Sstevel@tonic-gate 	idn_timer_t	*tphead;
37550Sstevel@tonic-gate 	procname_t	proc = "idn_timer_stop";
37560Sstevel@tonic-gate 	STRING(str);
37570Sstevel@tonic-gate 
37580Sstevel@tonic-gate 	ASSERT(tq);
37590Sstevel@tonic-gate 
37600Sstevel@tonic-gate 	INUM2STR(type, str);
37610Sstevel@tonic-gate 
37620Sstevel@tonic-gate 	IDN_TIMERQ_LOCK(tq);
37630Sstevel@tonic-gate 
37640Sstevel@tonic-gate 	if (tq->tq_count == 0) {
37650Sstevel@tonic-gate 		PR_TIMER("%s: found no %s timers (count=0)\n", proc, str);
37660Sstevel@tonic-gate 		IDN_TIMERQ_UNLOCK(tq);
37670Sstevel@tonic-gate 		return;
37680Sstevel@tonic-gate 	}
37690Sstevel@tonic-gate 	tphead = idn_timer_get(tq, type, tcookie);
37700Sstevel@tonic-gate #ifdef DEBUG
37710Sstevel@tonic-gate 	if (tphead == NULL)
37720Sstevel@tonic-gate 		PR_TIMER("%s: found no %s (cookie = 0x%x) "
37737656SSherry.Moore@Sun.COM 		    "timers (count=%d)!!\n",
37747656SSherry.Moore@Sun.COM 		    proc, str, tcookie, tq->tq_count);
37750Sstevel@tonic-gate #endif /* DEBUG */
37760Sstevel@tonic-gate 	IDN_TIMERQ_UNLOCK(tq);
37770Sstevel@tonic-gate 
37780Sstevel@tonic-gate 	if (tphead)
37790Sstevel@tonic-gate 		(void) idn_timer_stopall(tphead);
37800Sstevel@tonic-gate }
37810Sstevel@tonic-gate 
37820Sstevel@tonic-gate int
idn_timer_stopall(idn_timer_t * tp)37830Sstevel@tonic-gate idn_timer_stopall(idn_timer_t *tp)
37840Sstevel@tonic-gate {
37850Sstevel@tonic-gate 	int		count = 0;
37860Sstevel@tonic-gate 	int		nonactive;
37870Sstevel@tonic-gate 	uint_t		type;
37880Sstevel@tonic-gate 	idn_timer_t	*ntp;
37890Sstevel@tonic-gate 	procname_t	proc = "idn_timer_stopall";
37900Sstevel@tonic-gate 	STRING(str);
37910Sstevel@tonic-gate 
37920Sstevel@tonic-gate 	nonactive = 0;
37930Sstevel@tonic-gate 
37940Sstevel@tonic-gate 	if (tp) {
37950Sstevel@tonic-gate 		/*
37960Sstevel@tonic-gate 		 * Circle should have been broken.
37970Sstevel@tonic-gate 		 */
37980Sstevel@tonic-gate 		ASSERT(tp->t_back->t_forw == NULL);
37990Sstevel@tonic-gate 		type = tp->t_type;
38000Sstevel@tonic-gate 		INUM2STR(type, str);
38010Sstevel@tonic-gate 	}
38020Sstevel@tonic-gate 
38030Sstevel@tonic-gate 	for (; tp; tp = ntp) {
38040Sstevel@tonic-gate 		ntp = tp->t_forw;
38050Sstevel@tonic-gate 		count++;
38060Sstevel@tonic-gate 		ASSERT(tp->t_id != (timeout_id_t)0);
38070Sstevel@tonic-gate 		if (untimeout(tp->t_id) < 0) {
38080Sstevel@tonic-gate 			nonactive++;
38090Sstevel@tonic-gate 			PR_TIMER("%s: bad %s untimeout (domain=%d)\n",
38107656SSherry.Moore@Sun.COM 			    proc, str, tp->t_domid);
38110Sstevel@tonic-gate 		} else {
38120Sstevel@tonic-gate 			PR_TIMER("%s: good %s untimeout (domain=%d)\n",
38137656SSherry.Moore@Sun.COM 			    proc, str, tp->t_domid);
38140Sstevel@tonic-gate 		}
38150Sstevel@tonic-gate 		/*
38160Sstevel@tonic-gate 		 * There are two possible outcomes from
38170Sstevel@tonic-gate 		 * the untimeout().  Each ultimately result
38180Sstevel@tonic-gate 		 * in us having to free the timeout structure.
38190Sstevel@tonic-gate 		 *
38200Sstevel@tonic-gate 		 * 1. We successfully aborted a timeout call.
38210Sstevel@tonic-gate 		 *
38220Sstevel@tonic-gate 		 * 2. We failed to find the given timer.  He
38230Sstevel@tonic-gate 		 *    probably just fired off.
38240Sstevel@tonic-gate 		 */
38250Sstevel@tonic-gate 		idn_timer_free(tp);
38260Sstevel@tonic-gate 	}
38270Sstevel@tonic-gate 	PR_TIMER("%s: stopped %d of %d %s timers\n",
38287656SSherry.Moore@Sun.COM 	    proc, count - nonactive, count, str);
38290Sstevel@tonic-gate 
38300Sstevel@tonic-gate 	return (count);
38310Sstevel@tonic-gate }
38320Sstevel@tonic-gate 
38330Sstevel@tonic-gate void
idn_timer_dequeue(idn_timerq_t * tq,idn_timer_t * tp)38340Sstevel@tonic-gate idn_timer_dequeue(idn_timerq_t *tq, idn_timer_t *tp)
38350Sstevel@tonic-gate {
38360Sstevel@tonic-gate 	ASSERT(tq && tp);
38370Sstevel@tonic-gate 	ASSERT(IDN_TIMERQ_IS_LOCKED(tq));
38380Sstevel@tonic-gate 
38390Sstevel@tonic-gate 	ASSERT(tp->t_q == tq);
38400Sstevel@tonic-gate 
38410Sstevel@tonic-gate 	if (tp->t_onq == 0) {
38420Sstevel@tonic-gate 		/*
38430Sstevel@tonic-gate 		 * We've already been dequeued.
38440Sstevel@tonic-gate 		 */
38450Sstevel@tonic-gate 		ASSERT(tp == tp->t_forw);
38460Sstevel@tonic-gate 		ASSERT(tp == tp->t_back);
38470Sstevel@tonic-gate 	} else {
38480Sstevel@tonic-gate 		/*
38490Sstevel@tonic-gate 		 * We're still in the queue, get out.
38500Sstevel@tonic-gate 		 */
38510Sstevel@tonic-gate 		if (tq->tq_queue == tp)
38520Sstevel@tonic-gate 			tq->tq_queue = tp->t_forw;
38530Sstevel@tonic-gate 		tp->t_forw->t_back = tp->t_back;
38540Sstevel@tonic-gate 		tp->t_back->t_forw = tp->t_forw;
38550Sstevel@tonic-gate 		tp->t_onq = 0;
38560Sstevel@tonic-gate 		if (--(tq->tq_count) == 0) {
38570Sstevel@tonic-gate 			ASSERT(tq->tq_queue == tp);
38580Sstevel@tonic-gate 			tq->tq_queue = NULL;
38590Sstevel@tonic-gate 		}
38600Sstevel@tonic-gate 		tp->t_forw = tp->t_back = tp;
38610Sstevel@tonic-gate 	}
38620Sstevel@tonic-gate }
38630Sstevel@tonic-gate 
38640Sstevel@tonic-gate /*
38650Sstevel@tonic-gate  * -----------------------------------------------------------------------
38660Sstevel@tonic-gate  */
38670Sstevel@tonic-gate /*ARGSUSED*/
38680Sstevel@tonic-gate static int
idn_slabpool_report(queue_t * wq,mblk_t * mp,caddr_t cp,cred_t * cr)38690Sstevel@tonic-gate idn_slabpool_report(queue_t *wq, mblk_t *mp, caddr_t cp, cred_t *cr)
38700Sstevel@tonic-gate {
38710Sstevel@tonic-gate 	register int	p, nfree;
38720Sstevel@tonic-gate 	char		dsetstr[128];
38730Sstevel@tonic-gate 
38740Sstevel@tonic-gate 	ASSERT(IDN_GLOCK_IS_HELD());
38750Sstevel@tonic-gate 
38760Sstevel@tonic-gate 	if (idn.slabpool == NULL) {
38770Sstevel@tonic-gate 		(void) mi_mpprintf(mp,
38787656SSherry.Moore@Sun.COM 		    "IDN slabpool not initialized (masterid = %d)",
38797656SSherry.Moore@Sun.COM 		    IDN_GET_MASTERID());
38800Sstevel@tonic-gate 		return (0);
38810Sstevel@tonic-gate 	}
38820Sstevel@tonic-gate 
38830Sstevel@tonic-gate 	for (p = nfree = 0; p < idn.slabpool->npools; p++)
38840Sstevel@tonic-gate 		nfree += idn.slabpool->pool[p].nfree;
38850Sstevel@tonic-gate 
38860Sstevel@tonic-gate 	(void) mi_mpprintf(mp,
38877656SSherry.Moore@Sun.COM 	    "IDN slabpool (ntotal_slabs = %d, nalloc = %d, "
38887656SSherry.Moore@Sun.COM 	    "npools = %d)",
38897656SSherry.Moore@Sun.COM 	    idn.slabpool->ntotslabs,
38907656SSherry.Moore@Sun.COM 	    idn.slabpool->ntotslabs - nfree,
38917656SSherry.Moore@Sun.COM 	    idn.slabpool->npools);
38920Sstevel@tonic-gate 
38930Sstevel@tonic-gate 	(void) mi_mpprintf(mp, "pool  nslabs  nfree domains");
38940Sstevel@tonic-gate 
38950Sstevel@tonic-gate 	for (p = 0; p < idn.slabpool->npools; p++) {
38960Sstevel@tonic-gate 		register int	d, s;
38970Sstevel@tonic-gate 		uint_t		domset;
38980Sstevel@tonic-gate 
38990Sstevel@tonic-gate 		domset = 0;
39000Sstevel@tonic-gate 		for (s = 0; s < idn.slabpool->pool[p].nslabs; s++) {
39010Sstevel@tonic-gate 			short	dd;
39020Sstevel@tonic-gate 
39030Sstevel@tonic-gate 			dd = idn.slabpool->pool[p].sarray[s].sl_domid;
39040Sstevel@tonic-gate 			if (dd != (short)IDN_NIL_DOMID)
39050Sstevel@tonic-gate 				DOMAINSET_ADD(domset, dd);
39060Sstevel@tonic-gate 		}
39070Sstevel@tonic-gate 		dsetstr[0] = '\0';
39080Sstevel@tonic-gate 		if (domset) {
39090Sstevel@tonic-gate 			for (d = 0; d < MAX_DOMAINS; d++) {
39100Sstevel@tonic-gate 				if (!DOMAIN_IN_SET(domset, d))
39110Sstevel@tonic-gate 					continue;
39120Sstevel@tonic-gate 
39130Sstevel@tonic-gate 				if (dsetstr[0] == '\0')
39140Sstevel@tonic-gate 					(void) sprintf(dsetstr, "%d", d);
39150Sstevel@tonic-gate 				else
39160Sstevel@tonic-gate 					(void) sprintf(dsetstr, "%s %d",
39177656SSherry.Moore@Sun.COM 					    dsetstr, d);
39180Sstevel@tonic-gate 			}
39190Sstevel@tonic-gate 		}
39200Sstevel@tonic-gate 
39210Sstevel@tonic-gate 		if (p < 10)
39220Sstevel@tonic-gate 			(void) mi_mpprintf(mp, "  %d     %d       %d    %s",
39237656SSherry.Moore@Sun.COM 			    p, idn.slabpool->pool[p].nslabs,
39247656SSherry.Moore@Sun.COM 			    idn.slabpool->pool[p].nfree,
39257656SSherry.Moore@Sun.COM 			    dsetstr);
39260Sstevel@tonic-gate 		else
39270Sstevel@tonic-gate 			(void) mi_mpprintf(mp, " %d     %d       %d    %s",
39287656SSherry.Moore@Sun.COM 			    p, idn.slabpool->pool[p].nslabs,
39297656SSherry.Moore@Sun.COM 			    idn.slabpool->pool[p].nfree,
39307656SSherry.Moore@Sun.COM 			    dsetstr);
39310Sstevel@tonic-gate 	}
39320Sstevel@tonic-gate 	return (0);
39330Sstevel@tonic-gate }
39340Sstevel@tonic-gate 
39350Sstevel@tonic-gate /*ARGSUSED*/
39360Sstevel@tonic-gate static int
idn_buffer_report(queue_t * wq,mblk_t * mp,caddr_t cp,cred_t * cr)39370Sstevel@tonic-gate idn_buffer_report(queue_t *wq, mblk_t *mp, caddr_t cp, cred_t *cr)
39380Sstevel@tonic-gate {
39390Sstevel@tonic-gate 	smr_slab_t	*sp;
39400Sstevel@tonic-gate 	register int	d, cnt;
39410Sstevel@tonic-gate 	int		bufcount[MAX_DOMAINS];
39420Sstevel@tonic-gate 	int		spl;
39430Sstevel@tonic-gate 
39440Sstevel@tonic-gate 	ASSERT(IDN_GLOCK_IS_HELD());
39450Sstevel@tonic-gate 
39460Sstevel@tonic-gate 	if (idn.localid == IDN_NIL_DOMID) {
39470Sstevel@tonic-gate 		(void) mi_mpprintf(mp, "IDN not initialized (localid = %d)",
39487656SSherry.Moore@Sun.COM 		    idn.localid);
39490Sstevel@tonic-gate 		return (0);
39500Sstevel@tonic-gate 	}
39510Sstevel@tonic-gate 
39520Sstevel@tonic-gate 	(void) mi_mpprintf(mp, "Local domain has %d slabs allocated.",
39537656SSherry.Moore@Sun.COM 	    idn_domain[idn.localid].dnslabs);
39540Sstevel@tonic-gate 
39550Sstevel@tonic-gate 	DSLAB_LOCK_SHARED(idn.localid);
39560Sstevel@tonic-gate 	if ((sp = idn_domain[idn.localid].dslab) == NULL) {
39570Sstevel@tonic-gate 		DSLAB_UNLOCK(idn.localid);
39580Sstevel@tonic-gate 		return (0);
39590Sstevel@tonic-gate 	}
39600Sstevel@tonic-gate 
39610Sstevel@tonic-gate 	bzero(bufcount, sizeof (bufcount));
39620Sstevel@tonic-gate 	cnt = 0;
39630Sstevel@tonic-gate 
39640Sstevel@tonic-gate 	spl = splhi();
39650Sstevel@tonic-gate 	for (; sp; sp = sp->sl_next) {
39660Sstevel@tonic-gate 		smr_slabbuf_t	*bp;
39670Sstevel@tonic-gate 
39680Sstevel@tonic-gate 		while (!lock_try(&sp->sl_lock))
39690Sstevel@tonic-gate 			;
39700Sstevel@tonic-gate 		for (bp = sp->sl_inuse; bp; bp = bp->sb_next) {
39710Sstevel@tonic-gate 			bufcount[bp->sb_domid]++;
39720Sstevel@tonic-gate 			cnt++;
39730Sstevel@tonic-gate 		}
39740Sstevel@tonic-gate 		lock_clear(&sp->sl_lock);
39750Sstevel@tonic-gate 	}
39760Sstevel@tonic-gate 	splx(spl);
39770Sstevel@tonic-gate 
39780Sstevel@tonic-gate 	DSLAB_UNLOCK(idn.localid);
39790Sstevel@tonic-gate 
39800Sstevel@tonic-gate 	(void) mi_mpprintf(mp, "Local domain has %d buffers outstanding.", cnt);
39810Sstevel@tonic-gate 	if (cnt == 0)
39820Sstevel@tonic-gate 		return (0);
39830Sstevel@tonic-gate 
39840Sstevel@tonic-gate 	(void) mi_mpprintf(mp, "Domain  nbufs");
39850Sstevel@tonic-gate 	for (d = 0; d < MAX_DOMAINS; d++)
39860Sstevel@tonic-gate 		if (bufcount[d]) {
39870Sstevel@tonic-gate 			if (d < 10)
39880Sstevel@tonic-gate 				(void) mi_mpprintf(mp, "   %d      %d",
39897656SSherry.Moore@Sun.COM 				    d, bufcount[d]);
39900Sstevel@tonic-gate 			else
39910Sstevel@tonic-gate 				(void) mi_mpprintf(mp, "  %d      %d",
39927656SSherry.Moore@Sun.COM 				    d, bufcount[d]);
39930Sstevel@tonic-gate 		}
39940Sstevel@tonic-gate 
39950Sstevel@tonic-gate 	return (0);
39960Sstevel@tonic-gate }
39970Sstevel@tonic-gate 
39980Sstevel@tonic-gate static const char *
_get_spaces(int w,int s,int W)39990Sstevel@tonic-gate _get_spaces(int w, int s, int W)
40000Sstevel@tonic-gate {
40010Sstevel@tonic-gate 	static const char *const _spaces[] = {
40020Sstevel@tonic-gate 		"",			/* 0 */
40030Sstevel@tonic-gate 		" ",			/* 1 */
40040Sstevel@tonic-gate 		"  ", 			/* 2 */
40050Sstevel@tonic-gate 		"   ", 			/* 3 */
40060Sstevel@tonic-gate 		"    ", 		/* 4 */
40070Sstevel@tonic-gate 		"     ", 		/* 5 */
40080Sstevel@tonic-gate 		"      ", 		/* 6 */
40090Sstevel@tonic-gate 		"       ", 		/* 7 */
40100Sstevel@tonic-gate 		"        ", 		/* 8 */
40110Sstevel@tonic-gate 		"         ", 		/* 9 */
40120Sstevel@tonic-gate 		"          ", 		/* 10 */
40130Sstevel@tonic-gate 		"           ", 		/* 11 */
40140Sstevel@tonic-gate 		"            ", 	/* 12 */
40150Sstevel@tonic-gate 		"             ", 	/* 13 */
40160Sstevel@tonic-gate 		"              ", 	/* 14 */
40170Sstevel@tonic-gate 		"               ", 	/* 15 */
40180Sstevel@tonic-gate 		"                ", 	/* 16 */
40190Sstevel@tonic-gate 		"                 ", 	/* 17 */
40200Sstevel@tonic-gate 		"                  ", 	/* 18 */
40210Sstevel@tonic-gate 		"                   ", 	/* 19 */
40220Sstevel@tonic-gate 	};
40230Sstevel@tonic-gate 	return (_spaces[w+s-W]);
40240Sstevel@tonic-gate }
40250Sstevel@tonic-gate 
40260Sstevel@tonic-gate #define	_SSS(X, W, w, s) \
40270Sstevel@tonic-gate 	(((w) >= (W)) && (X)) ? _get_spaces((w), (s), (W))
40280Sstevel@tonic-gate 
40290Sstevel@tonic-gate static const char *
_hexspace(uint64_t v,int sz,int width,int padding)40300Sstevel@tonic-gate _hexspace(uint64_t v, int sz, int width, int padding)
40310Sstevel@tonic-gate {
40320Sstevel@tonic-gate 	int	maxnbl = 16;
40330Sstevel@tonic-gate 	int	diff;
40340Sstevel@tonic-gate 	uchar_t	*np;
40350Sstevel@tonic-gate 
40360Sstevel@tonic-gate 	diff = sizeof (uint64_t) - sz;
40370Sstevel@tonic-gate 	np = (uchar_t *)&v + diff;
40380Sstevel@tonic-gate 	maxnbl -= diff << 1;
40390Sstevel@tonic-gate 	while (sz-- > 0) {
40400Sstevel@tonic-gate 		if ((*np & 0xf0) && (width >= maxnbl))
40410Sstevel@tonic-gate 			return (_get_spaces(width, padding, maxnbl));
40420Sstevel@tonic-gate 		maxnbl--;
40430Sstevel@tonic-gate 		if ((*np & 0x0f) && (width >= maxnbl))
40440Sstevel@tonic-gate 			return (_get_spaces(width, padding, maxnbl));
40450Sstevel@tonic-gate 		maxnbl--;
40460Sstevel@tonic-gate 		np++;
40470Sstevel@tonic-gate 	}
40480Sstevel@tonic-gate 	return (_get_spaces(width, padding, 1));
40490Sstevel@tonic-gate }
40500Sstevel@tonic-gate 
40510Sstevel@tonic-gate #define	HEXSPACE(v, t, w, s)	_hexspace((uint64_t)(v), sizeof (t), (w), (s))
40520Sstevel@tonic-gate 
40530Sstevel@tonic-gate #define	DECSPACE(n, w, s) \
4054931Smathue 	(_SSS((uint_t)(n) >= 10000000, 8, (w), (s)) : \
4055931Smathue 	_SSS((uint_t)(n) >= 1000000, 7, (w), (s)) : \
4056931Smathue 	_SSS((uint_t)(n) >= 100000, 6, (w), (s)) : \
4057931Smathue 	_SSS((uint_t)(n) >= 10000, 5, (w), (s)) : \
4058931Smathue 	_SSS((uint_t)(n) >= 1000, 4, (w), (s)) : \
4059931Smathue 	_SSS((uint_t)(n) >= 100, 3, (w), (s)) : \
4060931Smathue 	_SSS((uint_t)(n) >= 10, 2, (w), (s)) : \
4061931Smathue 	_get_spaces((w), (s), 1))
4062931Smathue 
4063931Smathue #define	DECSPACE16(n, w, s) \
4064931Smathue 	(_SSS((n) >= 10000, 5, (w), (s)) : \
40650Sstevel@tonic-gate 	_SSS((n) >= 1000, 4, (w), (s)) : \
40660Sstevel@tonic-gate 	_SSS((n) >= 100, 3, (w), (s)) : \
40670Sstevel@tonic-gate 	_SSS((n) >= 10, 2, (w), (s)) : \
40680Sstevel@tonic-gate 	_get_spaces((w), (s), 1))
40690Sstevel@tonic-gate 
40700Sstevel@tonic-gate #define	MBXINFO(mtp) \
4071*11311SSurya.Prakki@Sun.COM 	(void *)&mtp->mt_header, \
40720Sstevel@tonic-gate 		HEXSPACE(&mtp->mt_header, &mtp->mt_header, 16, 2), \
40730Sstevel@tonic-gate 	mtp->mt_header.mh_svr_ready_ptr, \
40740Sstevel@tonic-gate 		HEXSPACE(mtp->mt_header.mh_svr_ready_ptr, \
40750Sstevel@tonic-gate 			mtp->mt_header.mh_svr_ready_ptr, 8, 1), \
40760Sstevel@tonic-gate 	mtp->mt_header.mh_svr_active_ptr, \
40770Sstevel@tonic-gate 		HEXSPACE(mtp->mt_header.mh_svr_active_ptr, \
40780Sstevel@tonic-gate 			mtp->mt_header.mh_svr_active_ptr, 8, 2), \
40790Sstevel@tonic-gate 	*(ushort_t *)(IDN_OFFSET2ADDR(mtp->mt_header.mh_svr_ready_ptr)), \
4080931Smathue 	DECSPACE16(*(ushort_t *) \
40810Sstevel@tonic-gate 			(IDN_OFFSET2ADDR(mtp->mt_header.mh_svr_ready_ptr)), \
40820Sstevel@tonic-gate 			1, 1), \
40830Sstevel@tonic-gate 	*(ushort_t *)(IDN_OFFSET2ADDR(mtp->mt_header.mh_svr_active_ptr)), \
4084931Smathue 	DECSPACE16(*(ushort_t *) \
40850Sstevel@tonic-gate 			(IDN_OFFSET2ADDR(mtp->mt_header.mh_svr_active_ptr)), \
40860Sstevel@tonic-gate 			1, 5), \
40870Sstevel@tonic-gate 	mtp->mt_header.mh_cookie, \
40880Sstevel@tonic-gate 		HEXSPACE(mtp->mt_header.mh_cookie, \
40890Sstevel@tonic-gate 			mtp->mt_header.mh_cookie, 8, 2), \
4090*11311SSurya.Prakki@Sun.COM 	(void *)&mtp->mt_queue[0], \
40910Sstevel@tonic-gate 		HEXSPACE(&mtp->mt_queue[0], &mtp->mt_queue[0], 16, 2)
40920Sstevel@tonic-gate 
40930Sstevel@tonic-gate /*ARGSUSED*/
40940Sstevel@tonic-gate static int
idn_mboxtbl_report(queue_t * wq,mblk_t * mp,caddr_t cp,cred_t * cr)40950Sstevel@tonic-gate idn_mboxtbl_report(queue_t *wq, mblk_t *mp, caddr_t cp, cred_t *cr)
40960Sstevel@tonic-gate {
40970Sstevel@tonic-gate 	register int		c, n, domid, subdomid;
40980Sstevel@tonic-gate 	register idn_mboxtbl_t	*mtp;
40990Sstevel@tonic-gate 	register idn_mboxmsg_t	*msp;
41000Sstevel@tonic-gate 	idn_mboxtbl_t		*map, *mtbasep;
41010Sstevel@tonic-gate 
41020Sstevel@tonic-gate 
41030Sstevel@tonic-gate 	ASSERT((cp == MBXTBL_PART_REPORT) || (cp == MBXTBL_FULL_REPORT));
41040Sstevel@tonic-gate 
41050Sstevel@tonic-gate 	if (IDN_GLOCK_TRY_SHARED() == 0) {
41060Sstevel@tonic-gate 		(void) mi_mpprintf(mp, "Local domain busy, try again.");
41070Sstevel@tonic-gate 		return (0);
41080Sstevel@tonic-gate 	}
41090Sstevel@tonic-gate 
41100Sstevel@tonic-gate 	if ((map = idn.mboxarea) == NULL) {
41110Sstevel@tonic-gate 		(void) mi_mpprintf(mp,
41127656SSherry.Moore@Sun.COM 		    "WARNING: Local domain is not master, "
41137656SSherry.Moore@Sun.COM 		    "ASSUMING idn.smr.vaddr.");
41140Sstevel@tonic-gate 		map = (idn_mboxtbl_t *)idn.smr.vaddr;
41150Sstevel@tonic-gate 	}
41160Sstevel@tonic-gate 
41170Sstevel@tonic-gate 	if (map) {
41180Sstevel@tonic-gate 		(void) mi_mpprintf(mp, "Mailbox Area starts @ 0x%p",
4119*11311SSurya.Prakki@Sun.COM 		    (void *)map);
41200Sstevel@tonic-gate 	} else {
41210Sstevel@tonic-gate 		(void) mi_mpprintf(mp, "Mailbox Area not found.");
41220Sstevel@tonic-gate 		goto repdone;
41230Sstevel@tonic-gate 	}
41240Sstevel@tonic-gate 
41250Sstevel@tonic-gate 	if (!idn.nchannels) {
41260Sstevel@tonic-gate 		(void) mi_mpprintf(mp, "No OPEN channels found");
41270Sstevel@tonic-gate 		goto repdone;
41280Sstevel@tonic-gate 	}
41290Sstevel@tonic-gate 
41300Sstevel@tonic-gate 	for (c = 0; c < IDN_MAX_NETS; c++) {
41310Sstevel@tonic-gate 
41320Sstevel@tonic-gate 		IDN_CHAN_LOCK_GLOBAL(&idn.chan_servers[c]);
41330Sstevel@tonic-gate 		if (!IDN_CHANNEL_IS_ATTACHED(&idn.chan_servers[c])) {
41340Sstevel@tonic-gate 			IDN_CHAN_UNLOCK_GLOBAL(&idn.chan_servers[c]);
41350Sstevel@tonic-gate 			continue;
41360Sstevel@tonic-gate 		}
41370Sstevel@tonic-gate 
41380Sstevel@tonic-gate 		(void) mi_mpprintf(mp,
41397656SSherry.Moore@Sun.COM 		    "Channel %d ---------------------------"
41407656SSherry.Moore@Sun.COM 		    "--------------------------"
41417656SSherry.Moore@Sun.COM 		    "-----------------------------", c);
41420Sstevel@tonic-gate 		(void) mi_mpprintf(mp,
41437656SSherry.Moore@Sun.COM 		    "  Domain   Header	    "
41447656SSherry.Moore@Sun.COM 		    "Ready/Active Ptrs    "
41457656SSherry.Moore@Sun.COM 		    "rdy/actv  cookie    Queue	     "
41467656SSherry.Moore@Sun.COM 		    "busy");
41470Sstevel@tonic-gate 
41480Sstevel@tonic-gate 		for (domid = 0; domid < MAX_DOMAINS; domid++) {
41490Sstevel@tonic-gate 			register int	busy_count;
41500Sstevel@tonic-gate 
41510Sstevel@tonic-gate 			if ((cp == MBXTBL_PART_REPORT) &&
41527656SSherry.Moore@Sun.COM 			    (idn_domain[domid].dcpu == IDN_NIL_DCPU))
41530Sstevel@tonic-gate 				continue;
41540Sstevel@tonic-gate 
41550Sstevel@tonic-gate 			mtbasep = IDN_MBOXAREA_BASE(map, domid);
41560Sstevel@tonic-gate 
41570Sstevel@tonic-gate 			for (subdomid = 0; subdomid < MAX_DOMAINS;
41587656SSherry.Moore@Sun.COM 			    subdomid++) {
41590Sstevel@tonic-gate 				mtp = IDN_MBOXTBL_PTR(mtbasep, subdomid);
41600Sstevel@tonic-gate 				mtp = IDN_MBOXTBL_PTR_CHAN(mtp, c);
41610Sstevel@tonic-gate 
41620Sstevel@tonic-gate 				if (subdomid == domid) {
41630Sstevel@tonic-gate 					if (subdomid == 0)
41640Sstevel@tonic-gate 						(void) mi_mpprintf(mp,
41657656SSherry.Moore@Sun.COM 						    "   %x.%x-%d%s%s",
41667656SSherry.Moore@Sun.COM 						    domid, subdomid, c,
41670Sstevel@tonic-gate 							/*CONSTCOND*/
41687656SSherry.Moore@Sun.COM 						    DECSPACE(c, 2, 2),
41697656SSherry.Moore@Sun.COM 						    "-- unused --");
41700Sstevel@tonic-gate 					else
41710Sstevel@tonic-gate 						(void) mi_mpprintf(mp,
41727656SSherry.Moore@Sun.COM 						    "    .%x-%d%s%s",
41737656SSherry.Moore@Sun.COM 						    subdomid, c,
41740Sstevel@tonic-gate 							/*CONSTCOND*/
41757656SSherry.Moore@Sun.COM 						    DECSPACE(c, 2, 2),
41767656SSherry.Moore@Sun.COM 						    "-- unused --");
41770Sstevel@tonic-gate 					continue;
41780Sstevel@tonic-gate 				}
41790Sstevel@tonic-gate 				busy_count = 0;
41800Sstevel@tonic-gate 				msp = &mtp->mt_queue[0];
41810Sstevel@tonic-gate 				for (n = 0; n < IDN_MMBOX_NUMENTRIES; n++) {
41820Sstevel@tonic-gate 					if (msp[n].ms_owner)
41830Sstevel@tonic-gate 						busy_count++;
41840Sstevel@tonic-gate 				}
41850Sstevel@tonic-gate 				if (subdomid == 0) {
41860Sstevel@tonic-gate 					(void) mi_mpprintf(mp,
41877656SSherry.Moore@Sun.COM 					    "   %x.%x-%d%s%p%s%x%s/ %x%s"
41887656SSherry.Moore@Sun.COM 					    "%d%s/ %d%s%x%s%p%s%d%s",
41897656SSherry.Moore@Sun.COM 					    domid, subdomid, c,
41900Sstevel@tonic-gate 						/*CONSTCOND*/
41917656SSherry.Moore@Sun.COM 					    DECSPACE(c, 2, 2),
41927656SSherry.Moore@Sun.COM 					    MBXINFO(mtp), busy_count,
41937656SSherry.Moore@Sun.COM 					    busy_count ? " <<<<<":"");
41940Sstevel@tonic-gate 				} else {
41950Sstevel@tonic-gate 					(void) mi_mpprintf(mp,
41967656SSherry.Moore@Sun.COM 					    "    .%x-%d%s%p%s%x%s/ %x%s"
41977656SSherry.Moore@Sun.COM 					    "%d%s/ %d%s%x%s%p%s%d%s",
41987656SSherry.Moore@Sun.COM 					    subdomid, c,
41990Sstevel@tonic-gate 						/*CONSTCOND*/
42007656SSherry.Moore@Sun.COM 					    DECSPACE(c, 2, 2),
42017656SSherry.Moore@Sun.COM 					    MBXINFO(mtp), busy_count,
42027656SSherry.Moore@Sun.COM 					    busy_count ? " <<<<<":"");
42030Sstevel@tonic-gate 				}
42040Sstevel@tonic-gate 			}
42050Sstevel@tonic-gate 		}
42060Sstevel@tonic-gate 		IDN_CHAN_UNLOCK_GLOBAL(&idn.chan_servers[c]);
42070Sstevel@tonic-gate 	}
42080Sstevel@tonic-gate 
42090Sstevel@tonic-gate repdone:
42100Sstevel@tonic-gate 	IDN_GUNLOCK();
42110Sstevel@tonic-gate 
42120Sstevel@tonic-gate 	return (0);
42130Sstevel@tonic-gate }
42140Sstevel@tonic-gate 
42150Sstevel@tonic-gate /*ARGSUSED*/
42160Sstevel@tonic-gate static void
idn_mainmbox_domain_report(queue_t * wq,mblk_t * mp,int domid,idn_mainmbox_t * mmp,char * mbxtype)42170Sstevel@tonic-gate idn_mainmbox_domain_report(queue_t *wq, mblk_t *mp, int domid,
42180Sstevel@tonic-gate 					idn_mainmbox_t *mmp, char *mbxtype)
42190Sstevel@tonic-gate {
42200Sstevel@tonic-gate 	register int	c;
42210Sstevel@tonic-gate 
42220Sstevel@tonic-gate 	if (mmp == NULL) {
42230Sstevel@tonic-gate 		(void) mi_mpprintf(mp, " %x.%s  -- none --", domid, mbxtype);
42240Sstevel@tonic-gate 		return;
42250Sstevel@tonic-gate 	}
42260Sstevel@tonic-gate 
42270Sstevel@tonic-gate 	for (c = 0; c < IDN_MAX_NETS; mmp++, c++) {
42280Sstevel@tonic-gate 		int	mm_count;
42290Sstevel@tonic-gate 
42300Sstevel@tonic-gate 		IDN_CHAN_LOCK_GLOBAL(&idn.chan_servers[c]);
42310Sstevel@tonic-gate 		if (IDN_CHANNEL_IS_DETACHED(&idn.chan_servers[c])) {
42320Sstevel@tonic-gate 			(void) mi_mpprintf(mp, " %x.%s  %u  -- not open --",
42337656SSherry.Moore@Sun.COM 			    domid, mbxtype, (int)mmp->mm_channel);
42340Sstevel@tonic-gate 			IDN_CHAN_UNLOCK_GLOBAL(&idn.chan_servers[c]);
42350Sstevel@tonic-gate 			continue;
42360Sstevel@tonic-gate 		}
42370Sstevel@tonic-gate 
42380Sstevel@tonic-gate 		mm_count = ((mmp->mm_count < 0) ? 0 : mmp->mm_count) / 1000;
42390Sstevel@tonic-gate 
42400Sstevel@tonic-gate 		(void) mi_mpprintf(mp, " %x.%s  %d%s%d%s%d%s%p%s%p%s%p%s%d/%d",
42417656SSherry.Moore@Sun.COM 		    domid, mbxtype,
42427656SSherry.Moore@Sun.COM 		    (int)mmp->mm_channel,
42430Sstevel@tonic-gate 					/*CONSTCOND*/
42447656SSherry.Moore@Sun.COM 		    DECSPACE((int)mmp->mm_channel, 5, 2),
42457656SSherry.Moore@Sun.COM 		    mm_count, DECSPACE(mm_count, 8, 2),
42467656SSherry.Moore@Sun.COM 		    mmp->mm_dropped,
42477656SSherry.Moore@Sun.COM 		    DECSPACE(mmp->mm_dropped, 8, 2),
4248*11311SSurya.Prakki@Sun.COM 		    (void *)mmp->mm_smr_mboxp,
42497656SSherry.Moore@Sun.COM 		    HEXSPACE(mmp->mm_smr_mboxp,
42507656SSherry.Moore@Sun.COM 		    mmp->mm_smr_mboxp, 16, 2),
4251*11311SSurya.Prakki@Sun.COM 		    (void *)mmp->mm_smr_readyp,
42527656SSherry.Moore@Sun.COM 		    HEXSPACE(mmp->mm_smr_readyp,
42537656SSherry.Moore@Sun.COM 		    mmp->mm_smr_readyp, 16, 2),
4254*11311SSurya.Prakki@Sun.COM 		    (void *)mmp->mm_smr_activep,
42557656SSherry.Moore@Sun.COM 		    HEXSPACE(mmp->mm_smr_activep,
42567656SSherry.Moore@Sun.COM 		    mmp->mm_smr_activep, 16, 2),
42577656SSherry.Moore@Sun.COM 		    mmp->mm_qiget, mmp->mm_qiput);
42580Sstevel@tonic-gate 		IDN_CHAN_UNLOCK_GLOBAL(&idn.chan_servers[c]);
42590Sstevel@tonic-gate 	}
42600Sstevel@tonic-gate }
42610Sstevel@tonic-gate 
42620Sstevel@tonic-gate /*ARGSUSED2*/
42630Sstevel@tonic-gate static int
idn_mainmbox_report(queue_t * wq,mblk_t * mp,caddr_t cp,cred_t * cr)42640Sstevel@tonic-gate idn_mainmbox_report(queue_t *wq, mblk_t *mp, caddr_t cp, cred_t *cr)
42650Sstevel@tonic-gate {
42660Sstevel@tonic-gate 	int	domid;
42670Sstevel@tonic-gate 	int	header = 0;
42680Sstevel@tonic-gate 
42690Sstevel@tonic-gate 	/*
42700Sstevel@tonic-gate 	 * Domain 0 never has a send/recv mainmbox so
42710Sstevel@tonic-gate 	 * don't bother printing him.
42720Sstevel@tonic-gate 	 */
42730Sstevel@tonic-gate 	for (domid = 1; domid < MAX_DOMAINS; domid++) {
42740Sstevel@tonic-gate 		idn_domain_t	*dp;
42750Sstevel@tonic-gate 
42760Sstevel@tonic-gate 		dp = &idn_domain[domid];
42770Sstevel@tonic-gate 
42780Sstevel@tonic-gate 		if (dp->dcpu == IDN_NIL_DCPU)
42790Sstevel@tonic-gate 			continue;
42800Sstevel@tonic-gate 		IDN_DLOCK_SHARED(domid);
42810Sstevel@tonic-gate 		if (dp->dcpu == IDN_NIL_DCPU) {
42820Sstevel@tonic-gate 			IDN_DUNLOCK(domid);
42830Sstevel@tonic-gate 			continue;
42840Sstevel@tonic-gate 		}
42850Sstevel@tonic-gate 		if (!header) {
42860Sstevel@tonic-gate 			(void) mi_mpprintf(mp,
42877656SSherry.Moore@Sun.COM 			    "Domain  Chan   PktCntK   "
42887656SSherry.Moore@Sun.COM 			    "PktDrop   SMRMbox	   "
42897656SSherry.Moore@Sun.COM 			    "ReadyPtr	  "
42907656SSherry.Moore@Sun.COM 			    "ActvPtr	  Miget/Miput");
42910Sstevel@tonic-gate 			header = 1;
42920Sstevel@tonic-gate 		}
42930Sstevel@tonic-gate 
42940Sstevel@tonic-gate 		mutex_enter(&dp->dmbox.m_mutex);
42950Sstevel@tonic-gate 		idn_mainmbox_domain_report(wq, mp, domid,
42967656SSherry.Moore@Sun.COM 		    idn_domain[domid].dmbox.m_send,
42977656SSherry.Moore@Sun.COM 		    "snd");
42980Sstevel@tonic-gate 		idn_mainmbox_domain_report(wq, mp, domid,
42997656SSherry.Moore@Sun.COM 		    idn_domain[domid].dmbox.m_recv,
43007656SSherry.Moore@Sun.COM 		    "rcv");
43010Sstevel@tonic-gate 		mutex_exit(&dp->dmbox.m_mutex);
43020Sstevel@tonic-gate 
43030Sstevel@tonic-gate 		IDN_DUNLOCK(domid);
43040Sstevel@tonic-gate 
43050Sstevel@tonic-gate 		(void) mi_mpprintf(mp,
43067656SSherry.Moore@Sun.COM 		    "  ---------------------------------------"
43077656SSherry.Moore@Sun.COM 		    "------------------------"
43087656SSherry.Moore@Sun.COM 		    "----------------------------");
43090Sstevel@tonic-gate 	}
43100Sstevel@tonic-gate 
43110Sstevel@tonic-gate 	if (!header)
43120Sstevel@tonic-gate 		(void) mi_mpprintf(mp, "No ACTIVE domain connections exist");
43130Sstevel@tonic-gate 
43140Sstevel@tonic-gate 	return (0);
43150Sstevel@tonic-gate }
43160Sstevel@tonic-gate 
43170Sstevel@tonic-gate /*ARGSUSED*/
43180Sstevel@tonic-gate static int
idn_global_report(queue_t * wq,mblk_t * mp,caddr_t cp,cred_t * cr)43190Sstevel@tonic-gate idn_global_report(queue_t *wq, mblk_t *mp, caddr_t cp, cred_t *cr)
43200Sstevel@tonic-gate {
43210Sstevel@tonic-gate 	int		i, nactive, masterid, nretry;
43220Sstevel@tonic-gate 	uint_t		locpfn_upper, locpfn_lower,
43237656SSherry.Moore@Sun.COM 	    rempfn_upper, rempfn_lower;
43240Sstevel@tonic-gate 	uint_t		marea_upper, marea_lower,
43257656SSherry.Moore@Sun.COM 	    iarea_upper, iarea_lower;
43260Sstevel@tonic-gate 	char		alt_dbuffer[64];
43270Sstevel@tonic-gate 	idn_retry_job_t	*rp;
43280Sstevel@tonic-gate 	domainset_t	retryset;
43290Sstevel@tonic-gate 	domainset_t	connected;
43300Sstevel@tonic-gate 	idn_synczone_t	*zp;
43310Sstevel@tonic-gate 	idn_syncop_t	*sp;
43320Sstevel@tonic-gate 	idn_domain_t	*dp;
43330Sstevel@tonic-gate 	char		*dbp, *dbuffer;
43340Sstevel@tonic-gate 
43350Sstevel@tonic-gate 	if (IDN_SYNC_TRYLOCK() == 0) {
43360Sstevel@tonic-gate 		(void) mi_mpprintf(mp, "Sync lock busy, try again.");
43370Sstevel@tonic-gate 		return (0);
43380Sstevel@tonic-gate 	}
43390Sstevel@tonic-gate 
43400Sstevel@tonic-gate 	if (IDN_GLOCK_TRY_SHARED() == 0) {
43410Sstevel@tonic-gate 		(void) mi_mpprintf(mp, "Local domain busy, try again.");
43420Sstevel@tonic-gate 		IDN_SYNC_UNLOCK();
43430Sstevel@tonic-gate 		return (0);
43440Sstevel@tonic-gate 	}
43450Sstevel@tonic-gate 	if ((dbp = dbuffer = ALLOC_DISPSTRING()) == NULL)
43460Sstevel@tonic-gate 		dbp = alt_dbuffer;
43470Sstevel@tonic-gate 
43480Sstevel@tonic-gate 	(void) mi_mpprintf(mp, "IDN\n    Global State = %s (%d)",
43497656SSherry.Moore@Sun.COM 	    idngs_str[idn.state], idn.state);
43500Sstevel@tonic-gate 
43510Sstevel@tonic-gate 	(void) mi_mpprintf(mp, "SMR");
43520Sstevel@tonic-gate 	(void) mi_mpprintf(mp, "    vaddr                ");
4353*11311SSurya.Prakki@Sun.COM 	(void) mi_mpprintf(mp, "    0x%p", (void *)idn.smr.vaddr);
43540Sstevel@tonic-gate 
43550Sstevel@tonic-gate 	(void) mi_mpprintf(mp, "    paddr-local     paddr-remote");
43560Sstevel@tonic-gate 	masterid = IDN_GET_MASTERID();
43570Sstevel@tonic-gate 	locpfn_upper = (uint_t)(idn.smr.locpfn >> (32 - PAGESHIFT));
43580Sstevel@tonic-gate 	locpfn_lower = (uint_t)(idn.smr.locpfn << PAGESHIFT);
43590Sstevel@tonic-gate 	if (idn.smr.rempfn == PFN_INVALID) {
43600Sstevel@tonic-gate 		rempfn_upper = rempfn_lower = 0;
43610Sstevel@tonic-gate 	} else {
43620Sstevel@tonic-gate 		rempfn_upper = (uint_t)(idn.smr.rempfn >> (32 - PAGESHIFT));
43630Sstevel@tonic-gate 		rempfn_lower = (uint_t)(idn.smr.rempfn << PAGESHIFT);
43640Sstevel@tonic-gate 	}
43650Sstevel@tonic-gate 	(void) mi_mpprintf(mp, "    0x%x.%x%s0x%x.%x",
43667656SSherry.Moore@Sun.COM 	    locpfn_upper, locpfn_lower,
43677656SSherry.Moore@Sun.COM 	    HEXSPACE(locpfn_lower, locpfn_lower, 8,
43687656SSherry.Moore@Sun.COM 	    (locpfn_upper < 0x10) ? 4 : 3),
43697656SSherry.Moore@Sun.COM 	    rempfn_upper, rempfn_lower);
43700Sstevel@tonic-gate 
43710Sstevel@tonic-gate 	(void) mi_mpprintf(mp, "    SMR length  = %d MBytes", IDN_SMR_SIZE);
43720Sstevel@tonic-gate 	(void) mi_mpprintf(mp, "    SMR bufsize = %d Bytes", IDN_SMR_BUFSIZE);
43730Sstevel@tonic-gate 	(void) mi_mpprintf(mp, "    NWR length  = %d MBytes", IDN_NWR_SIZE);
43740Sstevel@tonic-gate 	marea_upper = (uint_t)((uint64_t)IDN_MBOXAREA_SIZE >> 32);
43750Sstevel@tonic-gate 	marea_lower = (uint_t)((uint64_t)IDN_MBOXAREA_SIZE & 0xffffffff);
43760Sstevel@tonic-gate 	iarea_upper = (uint_t)((uint64_t)(MB2B(IDN_NWR_SIZE) -
43777656SSherry.Moore@Sun.COM 	    (size_t)IDN_MBOXAREA_SIZE) >> 32);
43780Sstevel@tonic-gate 	iarea_lower = (uint_t)((MB2B(IDN_NWR_SIZE) -
43797656SSherry.Moore@Sun.COM 	    (size_t)IDN_MBOXAREA_SIZE) & 0xffffffff);
43800Sstevel@tonic-gate 	(void) mi_mpprintf(mp,
43817656SSherry.Moore@Sun.COM 	    "    [ mbox area = 0x%x.%x Bytes, "
43827656SSherry.Moore@Sun.COM 	    "iobuf area = 0x%x.%x Bytes ]",
43837656SSherry.Moore@Sun.COM 	    marea_upper, marea_lower, iarea_upper, iarea_lower);
43840Sstevel@tonic-gate 
43850Sstevel@tonic-gate 	(void) mi_mpprintf(mp,
43867656SSherry.Moore@Sun.COM 	    "\nIDNnet (local domain [id:%d] [name:%s] is %s)",
43877656SSherry.Moore@Sun.COM 	    idn.localid,
43887656SSherry.Moore@Sun.COM 	    idn_domain[idn.localid].dname,
43897656SSherry.Moore@Sun.COM 	    (masterid == IDN_NIL_DOMID) ? "IDLE" :
43907656SSherry.Moore@Sun.COM 	    (idn.localid == masterid) ? "MASTER" :
43917656SSherry.Moore@Sun.COM 	    "SLAVE");
43920Sstevel@tonic-gate 	nactive = 0;
43930Sstevel@tonic-gate 	for (i = 0; i < IDN_MAX_NETS; i++) {
43940Sstevel@tonic-gate 		IDN_CHAN_LOCK_GLOBAL(&idn.chan_servers[i]);
43950Sstevel@tonic-gate 		if (IDN_CHANNEL_IS_ACTIVE(&idn.chan_servers[i]))
43960Sstevel@tonic-gate 			nactive++;
43970Sstevel@tonic-gate 		IDN_CHAN_UNLOCK_GLOBAL(&idn.chan_servers[i]);
43980Sstevel@tonic-gate 	}
43990Sstevel@tonic-gate 	(void) mi_mpprintf(mp, "    I/O Networks: (Open = %d, "
44007656SSherry.Moore@Sun.COM 	    "Active = %d, Max = %d)",
44017656SSherry.Moore@Sun.COM 	    idn.nchannels, nactive, IDN_MAX_NETS);
44020Sstevel@tonic-gate 	(void) mi_mpprintf(mp, "    Number of Domains  = %d", idn.ndomains);
44030Sstevel@tonic-gate 	(void) mi_mpprintf(mp, "    Number of AWOLs    = %d", idn.nawols);
44040Sstevel@tonic-gate 	/*
44050Sstevel@tonic-gate 	 * During connect domains can possibly be in ds_connected
44060Sstevel@tonic-gate 	 * while still in ds_trans_on.  Only once they leave ds_trans_on
44070Sstevel@tonic-gate 	 * are they really connected.
44080Sstevel@tonic-gate 	 */
44090Sstevel@tonic-gate 	connected = idn.domset.ds_connected & ~idn.domset.ds_trans_on;
44100Sstevel@tonic-gate 	DOMAINSET_ADD(connected, idn.localid);
44110Sstevel@tonic-gate 	boardset2str(connected, dbp);
44120Sstevel@tonic-gate 	(void) mi_mpprintf(mp, "    Connected Domains      = %s", dbp);
44130Sstevel@tonic-gate 	domainset2str(idn.domset.ds_trans_on, dbp);
44140Sstevel@tonic-gate 	(void) mi_mpprintf(mp, "    Pending Domain Links   = %s",
44157656SSherry.Moore@Sun.COM 	    idn.domset.ds_trans_on ? dbp : "<>");
44160Sstevel@tonic-gate 	domainset2str(idn.domset.ds_trans_off, dbp);
44170Sstevel@tonic-gate 	(void) mi_mpprintf(mp, "    Pending Domain Unlinks = %s",
44187656SSherry.Moore@Sun.COM 	    idn.domset.ds_trans_off ? dbp : "<>");
44190Sstevel@tonic-gate 	mutex_enter(&idn.retryqueue.rq_mutex);
44200Sstevel@tonic-gate 	nretry = idn.retryqueue.rq_count;
44210Sstevel@tonic-gate 	retryset = 0;
44220Sstevel@tonic-gate 	for (i = 0, rp = idn.retryqueue.rq_jobs; i < nretry; i++,
44237656SSherry.Moore@Sun.COM 	    rp = rp->rj_next) {
44240Sstevel@tonic-gate 		int	domid;
44250Sstevel@tonic-gate 
44260Sstevel@tonic-gate 		domid = IDN_RETRY_TOKEN2DOMID(rp->rj_token);
44270Sstevel@tonic-gate 		if (VALID_DOMAINID(domid)) {
44280Sstevel@tonic-gate 			DOMAINSET_ADD(retryset, domid);
44290Sstevel@tonic-gate 		}
44300Sstevel@tonic-gate 	}
44310Sstevel@tonic-gate 	mutex_exit(&idn.retryqueue.rq_mutex);
44320Sstevel@tonic-gate 	domainset2str(retryset, dbp);
44330Sstevel@tonic-gate 	(void) mi_mpprintf(mp, "    Retry Jobs:Domains     = %d:%s",
44347656SSherry.Moore@Sun.COM 	    nretry, retryset ? dbp : "<>");
44350Sstevel@tonic-gate 	domainset2str(idn.domset.ds_hitlist, dbp);
44360Sstevel@tonic-gate 	(void) mi_mpprintf(mp, "    Hitlist Domains        = %s",
44377656SSherry.Moore@Sun.COM 	    idn.domset.ds_hitlist ? dbp : "<>");
44380Sstevel@tonic-gate 	domainset2str(idn.domset.ds_relink, dbp);
44390Sstevel@tonic-gate 	(void) mi_mpprintf(mp, "    Reconfig Domains       = %s",
44407656SSherry.Moore@Sun.COM 	    idn.domset.ds_relink ? dbp : "<>");
44410Sstevel@tonic-gate 	if (idn.domset.ds_relink)
44420Sstevel@tonic-gate 		(void) mi_mpprintf(mp, "         new master id = %d",
44437656SSherry.Moore@Sun.COM 		    IDN_GET_NEW_MASTERID());
44440Sstevel@tonic-gate 	if (masterid == IDN_NIL_DOMID) {
44450Sstevel@tonic-gate 		(void) mi_mpprintf(mp, "    Master Domain: no master");
44460Sstevel@tonic-gate 	} else {
44470Sstevel@tonic-gate 		idn_domain_t	*mdp;
44480Sstevel@tonic-gate 
44490Sstevel@tonic-gate 		mdp = &idn_domain[masterid];
44500Sstevel@tonic-gate 
44510Sstevel@tonic-gate 		(void) mi_mpprintf(mp,
44527656SSherry.Moore@Sun.COM 		    "    Master Domain (id:name/brds - state):");
44530Sstevel@tonic-gate 
44540Sstevel@tonic-gate 		if (strlen(mdp->dname) > 0)
4455*11311SSurya.Prakki@Sun.COM 			(void) strcpy(dbp, mdp->dname);
44560Sstevel@tonic-gate 		else
44570Sstevel@tonic-gate 			boardset2str(mdp->dhw.dh_boardset, dbp);
44580Sstevel@tonic-gate 		if (masterid < 10)
44590Sstevel@tonic-gate 			(void) mi_mpprintf(mp, "         %d: %s - %s",
44607656SSherry.Moore@Sun.COM 			    masterid, dbp,
44617656SSherry.Moore@Sun.COM 			    idnds_str[mdp->dstate]);
44620Sstevel@tonic-gate 		else
44630Sstevel@tonic-gate 			(void) mi_mpprintf(mp, "        %d: %s - %s",
44647656SSherry.Moore@Sun.COM 			    masterid, dbp,
44657656SSherry.Moore@Sun.COM 			    idnds_str[mdp->dstate]);
44660Sstevel@tonic-gate 	}
44670Sstevel@tonic-gate 	if (idn.ndomains <= 1) {
44680Sstevel@tonic-gate 		(void) mi_mpprintf(mp, "    Slave Domains: none");
44690Sstevel@tonic-gate 	} else {
44700Sstevel@tonic-gate 		int	d;
44710Sstevel@tonic-gate 
44720Sstevel@tonic-gate 		(void) mi_mpprintf(mp,
44737656SSherry.Moore@Sun.COM 		    "    Slave Domains (id:name/brds - state):");
44740Sstevel@tonic-gate 		for (d = 0; d < MAX_DOMAINS; d++) {
44750Sstevel@tonic-gate 			dp = &idn_domain[d];
44760Sstevel@tonic-gate 
44770Sstevel@tonic-gate 			if ((dp->dcpu == IDN_NIL_DCPU) || (d == masterid))
44780Sstevel@tonic-gate 				continue;
44790Sstevel@tonic-gate 
44800Sstevel@tonic-gate 			if (strlen(dp->dname) > 0)
4481*11311SSurya.Prakki@Sun.COM 				(void) strcpy(dbp, dp->dname);
44820Sstevel@tonic-gate 			else
44830Sstevel@tonic-gate 				boardset2str(dp->dhw.dh_boardset, dbp);
44840Sstevel@tonic-gate 			if (d < 10)
44850Sstevel@tonic-gate 				(void) mi_mpprintf(mp, "         %d: %s - %s",
44867656SSherry.Moore@Sun.COM 				    d, dbp,
44877656SSherry.Moore@Sun.COM 				    idnds_str[dp->dstate]);
44880Sstevel@tonic-gate 			else
44890Sstevel@tonic-gate 				(void) mi_mpprintf(mp, "        %d: %s - %s",
44907656SSherry.Moore@Sun.COM 				    d, dbp,
44917656SSherry.Moore@Sun.COM 				    idnds_str[dp->dstate]);
44920Sstevel@tonic-gate 		}
44930Sstevel@tonic-gate 	}
44940Sstevel@tonic-gate 
44950Sstevel@tonic-gate 	if (idn.nawols == 0) {
44960Sstevel@tonic-gate 		(void) mi_mpprintf(mp, "    AWOL Domains: none");
44970Sstevel@tonic-gate 	} else {
44980Sstevel@tonic-gate 		int	d;
44990Sstevel@tonic-gate 
45000Sstevel@tonic-gate 		(void) mi_mpprintf(mp, "    AWOL Domains (id:name/brds):");
45010Sstevel@tonic-gate 		for (d = 0; d < MAX_DOMAINS; d++) {
45020Sstevel@tonic-gate 			dp = &idn_domain[d];
45030Sstevel@tonic-gate 
45040Sstevel@tonic-gate 			if (!DOMAIN_IN_SET(idn.domset.ds_awol, d) ||
45057656SSherry.Moore@Sun.COM 			    (dp->dcpu == IDN_NIL_DCPU))
45060Sstevel@tonic-gate 				continue;
45070Sstevel@tonic-gate 
45080Sstevel@tonic-gate 			if (strlen(dp->dname) > 0)
4509*11311SSurya.Prakki@Sun.COM 				(void) strcpy(dbp, dp->dname);
45100Sstevel@tonic-gate 			else
45110Sstevel@tonic-gate 				boardset2str(dp->dhw.dh_boardset, dbp);
45120Sstevel@tonic-gate 			if (d < 10)
45130Sstevel@tonic-gate 				(void) mi_mpprintf(mp, "         %d: %s",
45147656SSherry.Moore@Sun.COM 				    d, dbp);
45150Sstevel@tonic-gate 			else
45160Sstevel@tonic-gate 				(void) mi_mpprintf(mp, "        %d: %s",
45177656SSherry.Moore@Sun.COM 				    d, dbp);
45180Sstevel@tonic-gate 		}
45190Sstevel@tonic-gate 	}
45200Sstevel@tonic-gate 
45210Sstevel@tonic-gate 	/*CONSTCOND*/
45220Sstevel@tonic-gate 	i = IDN_SYNC_GETZONE(IDNSYNC_CONNECT);
45230Sstevel@tonic-gate 	zp = &idn.sync.sz_zone[i];
45240Sstevel@tonic-gate 	if (zp->sc_cnt == 0) {
45250Sstevel@tonic-gate 		(void) mi_mpprintf(mp, "    Sync Zone (con): [empty]");
45260Sstevel@tonic-gate 	} else {
45270Sstevel@tonic-gate 		(void) mi_mpprintf(mp, "    Sync Zone (con): [%d domains]",
45287656SSherry.Moore@Sun.COM 		    zp->sc_cnt);
45290Sstevel@tonic-gate 		sp = zp->sc_op;
45300Sstevel@tonic-gate 		for (i = 0; (i < zp->sc_cnt) && sp; i++) {
45310Sstevel@tonic-gate 			(void) mi_mpprintf(mp,
45327656SSherry.Moore@Sun.COM 			    "	             "
45337656SSherry.Moore@Sun.COM 			    "%x: x_set =%s0x%x, r_set =%s0x%x",
45347656SSherry.Moore@Sun.COM 			    sp->s_domid,
45357656SSherry.Moore@Sun.COM 			    HEXSPACE(sp->s_set_exp,
45367656SSherry.Moore@Sun.COM 			    sp->s_set_exp, 4, 1),
45377656SSherry.Moore@Sun.COM 			    sp->s_set_exp,
45387656SSherry.Moore@Sun.COM 			    HEXSPACE(sp->s_set_rdy,
45397656SSherry.Moore@Sun.COM 			    sp->s_set_rdy, 4, 1),
45407656SSherry.Moore@Sun.COM 			    sp->s_set_rdy);
45410Sstevel@tonic-gate 			sp = sp->s_next;
45420Sstevel@tonic-gate 		}
45430Sstevel@tonic-gate 	}
45440Sstevel@tonic-gate 	/*CONSTCOND*/
45450Sstevel@tonic-gate 	i = IDN_SYNC_GETZONE(IDNSYNC_DISCONNECT);
45460Sstevel@tonic-gate 	zp = &idn.sync.sz_zone[i];
45470Sstevel@tonic-gate 	if (zp->sc_cnt == 0) {
45480Sstevel@tonic-gate 		(void) mi_mpprintf(mp, "    Sync Zone (dis): [empty]");
45490Sstevel@tonic-gate 	} else {
45500Sstevel@tonic-gate 		(void) mi_mpprintf(mp, "    Sync Zone (dis): [%d domains]",
45517656SSherry.Moore@Sun.COM 		    zp->sc_cnt);
45520Sstevel@tonic-gate 		sp = zp->sc_op;
45530Sstevel@tonic-gate 		for (i = 0; (i < zp->sc_cnt) && sp; i++) {
45540Sstevel@tonic-gate 			(void) mi_mpprintf(mp,
45557656SSherry.Moore@Sun.COM 			    "	             "
45567656SSherry.Moore@Sun.COM 			    "%x: x_set =%s0x%x, r_set =%s0x%x",
45577656SSherry.Moore@Sun.COM 			    sp->s_domid,
45587656SSherry.Moore@Sun.COM 			    HEXSPACE(sp->s_set_exp,
45597656SSherry.Moore@Sun.COM 			    sp->s_set_exp, 4, 1),
45607656SSherry.Moore@Sun.COM 			    sp->s_set_exp,
45617656SSherry.Moore@Sun.COM 			    HEXSPACE(sp->s_set_rdy,
45627656SSherry.Moore@Sun.COM 			    sp->s_set_rdy, 4, 1),
45637656SSherry.Moore@Sun.COM 			    sp->s_set_rdy);
45640Sstevel@tonic-gate 			sp = sp->s_next;
45650Sstevel@tonic-gate 		}
45660Sstevel@tonic-gate 	}
45670Sstevel@tonic-gate 
45680Sstevel@tonic-gate 	IDN_GUNLOCK();
45690Sstevel@tonic-gate 	IDN_SYNC_UNLOCK();
45700Sstevel@tonic-gate 
45710Sstevel@tonic-gate 	if (dbuffer) {
45720Sstevel@tonic-gate 		FREE_DISPSTRING(dbuffer);
45730Sstevel@tonic-gate 	}
45740Sstevel@tonic-gate 
45750Sstevel@tonic-gate 	return (0);
45760Sstevel@tonic-gate }
45770Sstevel@tonic-gate 
45780Sstevel@tonic-gate /*ARGSUSED*/
45790Sstevel@tonic-gate static int
idn_domain_report(queue_t * wq,mblk_t * mp,caddr_t cp,cred_t * cr)45800Sstevel@tonic-gate idn_domain_report(queue_t *wq, mblk_t *mp, caddr_t cp, cred_t *cr)
45810Sstevel@tonic-gate {
45820Sstevel@tonic-gate 	int		d, nchan;
45830Sstevel@tonic-gate 	uint_t		domset;
45840Sstevel@tonic-gate 	idn_chanset_t	chanset;
45850Sstevel@tonic-gate 	idn_domain_t	*dp;
45860Sstevel@tonic-gate 	uint_t		pset_upper, pset_lower;
45870Sstevel@tonic-gate 	char		*dbuffer, *dbp;
45880Sstevel@tonic-gate 	char		alt_dbuffer[64];
45890Sstevel@tonic-gate 
45900Sstevel@tonic-gate 
45910Sstevel@tonic-gate 	if (IDN_SYNC_TRYLOCK() == 0) {
45920Sstevel@tonic-gate 		(void) mi_mpprintf(mp, "Sync lock busy, try again.");
45930Sstevel@tonic-gate 		return (0);
45940Sstevel@tonic-gate 	}
45950Sstevel@tonic-gate 
45960Sstevel@tonic-gate 	if (IDN_GLOCK_TRY_SHARED() == 0) {
45970Sstevel@tonic-gate 		(void) mi_mpprintf(mp, "Local domain busy, try again.");
45980Sstevel@tonic-gate 		IDN_SYNC_UNLOCK();
45990Sstevel@tonic-gate 		return (0);
46000Sstevel@tonic-gate 	}
46010Sstevel@tonic-gate 
46020Sstevel@tonic-gate 	if ((dbp = dbuffer = ALLOC_DISPSTRING()) == NULL)
46030Sstevel@tonic-gate 		dbp = alt_dbuffer;
46040Sstevel@tonic-gate 
4605931Smathue 	if (cp == NULL)
46060Sstevel@tonic-gate 		domset = DOMAINSET(idn.localid);
46070Sstevel@tonic-gate 	else
46080Sstevel@tonic-gate 		domset = DOMAINSET_ALL;
46090Sstevel@tonic-gate 
46100Sstevel@tonic-gate 	for (d = 0; d < MAX_DOMAINS; d++) {
46110Sstevel@tonic-gate 
46120Sstevel@tonic-gate 		if (DOMAIN_IN_SET(domset, d) == 0)
46130Sstevel@tonic-gate 			continue;
46140Sstevel@tonic-gate 
46150Sstevel@tonic-gate 		dp = &idn_domain[d];
46160Sstevel@tonic-gate 
46170Sstevel@tonic-gate 		if (dp->dcpu == IDN_NIL_DCPU)
46180Sstevel@tonic-gate 			continue;
46190Sstevel@tonic-gate 
46200Sstevel@tonic-gate 		if (IDN_DLOCK_TRY_SHARED(d) == 0) {
46210Sstevel@tonic-gate 			if (d < 10)
46220Sstevel@tonic-gate 				(void) mi_mpprintf(mp,
46237656SSherry.Moore@Sun.COM 				    "Domain %d   (0x%p) busy...",
4624*11311SSurya.Prakki@Sun.COM 				    d, (void *)dp);
46250Sstevel@tonic-gate 			else
46260Sstevel@tonic-gate 				(void) mi_mpprintf(mp,
46277656SSherry.Moore@Sun.COM 				    "Domain %d  (0x%p) busy...",
4628*11311SSurya.Prakki@Sun.COM 				    d, (void *)dp);
46290Sstevel@tonic-gate 			continue;
46300Sstevel@tonic-gate 		}
46310Sstevel@tonic-gate 		if (dp->dcpu == IDN_NIL_DCPU) {
46320Sstevel@tonic-gate 			IDN_DUNLOCK(d);
46330Sstevel@tonic-gate 			continue;
46340Sstevel@tonic-gate 		}
46350Sstevel@tonic-gate 		if (d < 10)
46360Sstevel@tonic-gate 			(void) mi_mpprintf(mp, "%sDomain %d   (0x%p)",
46377656SSherry.Moore@Sun.COM 			    (d && (idn.ndomains > 1)) ? "\n" : "",
4638*11311SSurya.Prakki@Sun.COM 			    d, (void *)dp);
46390Sstevel@tonic-gate 		else
46400Sstevel@tonic-gate 			(void) mi_mpprintf(mp, "%sDomain %d  (0x%p)",
46417656SSherry.Moore@Sun.COM 			    (d && (idn.ndomains > 1)) ? "\n" : "",
4642*11311SSurya.Prakki@Sun.COM 			    d, (void *)dp);
46430Sstevel@tonic-gate 
46440Sstevel@tonic-gate 		if (d == idn.localid)
46450Sstevel@tonic-gate 			(void) mi_mpprintf(mp, "  (local)  State = %s (%d)",
46467656SSherry.Moore@Sun.COM 			    idnds_str[dp->dstate], dp->dstate);
46470Sstevel@tonic-gate 		else
46480Sstevel@tonic-gate 			(void) mi_mpprintf(mp, "           State = %s (%d)",
46497656SSherry.Moore@Sun.COM 			    idnds_str[dp->dstate], dp->dstate);
46500Sstevel@tonic-gate 		(void) mi_mpprintf(mp, "           Name = %s, Netid = %d",
46517656SSherry.Moore@Sun.COM 		    (strlen(dp->dname) > 0) ? dp->dname : "<>",
46527656SSherry.Moore@Sun.COM 		    (int)dp->dnetid);
46530Sstevel@tonic-gate 
46540Sstevel@tonic-gate 		CHANSET_ZERO(chanset);
46550Sstevel@tonic-gate 		nchan = idn_domain_is_registered(d, -1, &chanset);
46560Sstevel@tonic-gate 		if (dbuffer)
46570Sstevel@tonic-gate 			mask2str(chanset, dbp, 32);
46580Sstevel@tonic-gate 		else
46590Sstevel@tonic-gate 			(void) sprintf(dbp, "0x%x", chanset);
46600Sstevel@tonic-gate 		(void) mi_mpprintf(mp, "           Nchans = %d, Chanset = %s",
46617656SSherry.Moore@Sun.COM 		    nchan, nchan ? dbp : "<>");
46620Sstevel@tonic-gate 		pset_upper = UPPER32_CPUMASK(dp->dcpuset);
46630Sstevel@tonic-gate 		pset_lower = LOWER32_CPUMASK(dp->dcpuset);
46640Sstevel@tonic-gate 		if (dbuffer)
46650Sstevel@tonic-gate 			boardset2str(dp->dhw.dh_boardset, dbp);
46660Sstevel@tonic-gate 		else
46670Sstevel@tonic-gate 			(void) sprintf(dbp, "0x%x", dp->dhw.dh_boardset);
46680Sstevel@tonic-gate 
46690Sstevel@tonic-gate 		(void) mi_mpprintf(mp, "           Nboards = %d, Brdset = %s",
46707656SSherry.Moore@Sun.COM 		    dp->dhw.dh_nboards,
46717656SSherry.Moore@Sun.COM 		    dp->dhw.dh_nboards ? dbp : "<>");
46720Sstevel@tonic-gate 		(void) sprintf(dbp, "0x%x.%x", pset_upper, pset_lower);
46730Sstevel@tonic-gate 		(void) mi_mpprintf(mp, "           Ncpus = %d, Cpuset = %s",
46747656SSherry.Moore@Sun.COM 		    dp->dncpus, dp->dncpus ? dbp : "<>");
46750Sstevel@tonic-gate 		(void) mi_mpprintf(mp, "           Nmcadr = %d",
46767656SSherry.Moore@Sun.COM 		    dp->dhw.dh_nmcadr);
46770Sstevel@tonic-gate 		(void) mi_mpprintf(mp,
46787656SSherry.Moore@Sun.COM 		    "	   MsgTimer = %s  (cnt = %d)",
46797656SSherry.Moore@Sun.COM 		    (dp->dtimerq.tq_count > 0)
46807656SSherry.Moore@Sun.COM 		    ? "active" : "idle",
46817656SSherry.Moore@Sun.COM 		    dp->dtimerq.tq_count);
46820Sstevel@tonic-gate 		(void) mi_mpprintf(mp, "           Dcpu = %d  "
46837656SSherry.Moore@Sun.COM 		    "(lastcpu = %d, cpuindex = %d)",
46847656SSherry.Moore@Sun.COM 		    dp->dcpu, dp->dcpu_last, dp->dcpuindex);
46850Sstevel@tonic-gate 		(void) mi_mpprintf(mp, "           Dio = %d  "
46867656SSherry.Moore@Sun.COM 		    "(ioerr = %d, iochk = %d, iowanted = %d)",
46877656SSherry.Moore@Sun.COM 		    dp->dio, dp->dioerr, dp->diocheck ? 1 : 0,
46887656SSherry.Moore@Sun.COM 		    dp->diowanted ? 1 : 0);
46890Sstevel@tonic-gate 		if (dp->dsync.s_cmd == IDNSYNC_NIL) {
46900Sstevel@tonic-gate 			(void) mi_mpprintf(mp, "           Dsync = %s",
46917656SSherry.Moore@Sun.COM 			    idnsync_str[IDNSYNC_NIL]);
46920Sstevel@tonic-gate 		} else {
46930Sstevel@tonic-gate 			(void) mi_mpprintf(mp,
46947656SSherry.Moore@Sun.COM 			    "	   Dsync = %s "
46957656SSherry.Moore@Sun.COM 			    "(x_set = 0x%x, r_set = 0x%x)",
46967656SSherry.Moore@Sun.COM 			    idnsync_str[dp->dsync.s_cmd],
46977656SSherry.Moore@Sun.COM 			    (uint_t)dp->dsync.s_set_exp,
46987656SSherry.Moore@Sun.COM 			    (uint_t)dp->dsync.s_set_rdy);
46990Sstevel@tonic-gate 		}
47000Sstevel@tonic-gate 		(void) mi_mpprintf(mp, "           Dvote = 0x%x",
47017656SSherry.Moore@Sun.COM 		    dp->dvote.ticket);
47020Sstevel@tonic-gate 		(void) mi_mpprintf(mp, "           Dfin = %s (Sync = %s)",
47037656SSherry.Moore@Sun.COM 		    idnfin_str[dp->dfin],
47047656SSherry.Moore@Sun.COM 		    (dp->dfin_sync == IDNFIN_SYNC_OFF) ? "OFF" :
47057656SSherry.Moore@Sun.COM 		    (dp->dfin_sync == IDNFIN_SYNC_YES) ? "YES" :
47067656SSherry.Moore@Sun.COM 		    "NO");
47070Sstevel@tonic-gate 		(void) mi_mpprintf(mp, "           Dcookie_err = %s (cnt = %d)",
47087656SSherry.Moore@Sun.COM 		    dp->dcookie_err ? "YES" : "NO",
47097656SSherry.Moore@Sun.COM 		    dp->dcookie_errcnt);
47100Sstevel@tonic-gate 		IDN_DUNLOCK(d);
47110Sstevel@tonic-gate 	}
47120Sstevel@tonic-gate 
47130Sstevel@tonic-gate 	IDN_GUNLOCK();
47140Sstevel@tonic-gate 
47150Sstevel@tonic-gate 	if (dbuffer) {
47160Sstevel@tonic-gate 		FREE_DISPSTRING(dbuffer);
47170Sstevel@tonic-gate 	}
47180Sstevel@tonic-gate 
47190Sstevel@tonic-gate 	IDN_SYNC_UNLOCK();
47200Sstevel@tonic-gate 
47210Sstevel@tonic-gate 	return (0);
47220Sstevel@tonic-gate }
47230Sstevel@tonic-gate 
47240Sstevel@tonic-gate #define	SNOOP_ENTRIES	2048	/* power of 2 */
47250Sstevel@tonic-gate 
47260Sstevel@tonic-gate struct snoop_buffer {
47270Sstevel@tonic-gate /*  0 */	char	io;
47280Sstevel@tonic-gate /*  1 */	char	board;
47290Sstevel@tonic-gate /*  2 */	char	trans[14];
47300Sstevel@tonic-gate 
47310Sstevel@tonic-gate /* 10 */	uint_t	xargs[4];
47320Sstevel@tonic-gate } *snoop_data, snoop_buffer[SNOOP_ENTRIES+1];
47330Sstevel@tonic-gate 
47340Sstevel@tonic-gate 
47350Sstevel@tonic-gate int		snoop_index;
47360Sstevel@tonic-gate kmutex_t	snoop_mutex;
47370Sstevel@tonic-gate static char	_bd2hexascii[] = {
47380Sstevel@tonic-gate 	'0', '1', '2', '3', '4', '5', '6', '7',
47390Sstevel@tonic-gate 	'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
47400Sstevel@tonic-gate };
47410Sstevel@tonic-gate 
47420Sstevel@tonic-gate #define	SNOOP_IDN(in, tr, bd, arg1, arg2, arg3, arg4) \
47430Sstevel@tonic-gate { \
47440Sstevel@tonic-gate 	if (idn_snoop) { \
47450Sstevel@tonic-gate 		mutex_enter(&snoop_mutex); \
47460Sstevel@tonic-gate 		if (snoop_data == NULL) { \
47470Sstevel@tonic-gate 			snoop_data = (struct snoop_buffer *) \
47480Sstevel@tonic-gate 				(((uint_t)snoop_buffer + 0xf) & ~0xf); \
47490Sstevel@tonic-gate 		} \
47500Sstevel@tonic-gate 		snoop_data[snoop_index].io = ((in) == 0) ? 'o' : 'i'; \
47510Sstevel@tonic-gate 		snoop_data[snoop_index].board = \
47520Sstevel@tonic-gate 				((bd) == -1) ? 'X' : _bd2hexascii[bd]; \
47530Sstevel@tonic-gate 		(void) strncpy(snoop_data[snoop_index].trans, (tr), 14); \
47540Sstevel@tonic-gate 		snoop_data[snoop_index].xargs[0] = (arg1); \
47550Sstevel@tonic-gate 		snoop_data[snoop_index].xargs[1] = (arg2); \
47560Sstevel@tonic-gate 		snoop_data[snoop_index].xargs[2] = (arg3); \
47570Sstevel@tonic-gate 		snoop_data[snoop_index].xargs[3] = (arg4); \
47580Sstevel@tonic-gate 		snoop_index++; \
47590Sstevel@tonic-gate 		snoop_index &= SNOOP_ENTRIES - 1; \
47600Sstevel@tonic-gate 		mutex_exit(&snoop_mutex); \
47610Sstevel@tonic-gate 	} \
47620Sstevel@tonic-gate }
47630Sstevel@tonic-gate 
47640Sstevel@tonic-gate /*
47650Sstevel@tonic-gate  * Allocate the circular buffers to be used for
47660Sstevel@tonic-gate  * DMV interrupt processing.
47670Sstevel@tonic-gate  */
47680Sstevel@tonic-gate static int
idn_init_handler()47690Sstevel@tonic-gate idn_init_handler()
47700Sstevel@tonic-gate {
47710Sstevel@tonic-gate 	int		i, c;
47720Sstevel@tonic-gate 	size_t		len;
47730Sstevel@tonic-gate 	idn_dmv_msg_t	*basep, *ivp;
47740Sstevel@tonic-gate 	uint32_t	ivp_offset;
47750Sstevel@tonic-gate 	procname_t	proc = "idn_init_handler";
47760Sstevel@tonic-gate 
47770Sstevel@tonic-gate 	if (idn.intr.dmv_data != NULL) {
47780Sstevel@tonic-gate 		cmn_err(CE_WARN,
47797656SSherry.Moore@Sun.COM 		    "IDN: 130: IDN DMV handler already initialized");
47800Sstevel@tonic-gate 		return (-1);
47810Sstevel@tonic-gate 	}
47820Sstevel@tonic-gate 
47830Sstevel@tonic-gate 	/*
47840Sstevel@tonic-gate 	 * This memory will be touched by the low-level
47850Sstevel@tonic-gate 	 * DMV trap handler for IDN.
47860Sstevel@tonic-gate 	 */
47870Sstevel@tonic-gate 	len = sizeof (idn_dmv_data_t);
47880Sstevel@tonic-gate 	len = roundup(len, sizeof (uint64_t));
47890Sstevel@tonic-gate 	len += NCPU * idn_dmv_pending_max * sizeof (idn_dmv_msg_t);
47900Sstevel@tonic-gate 	len = roundup(len, PAGESIZE);
47910Sstevel@tonic-gate 
4792931Smathue 	PR_PROTO("%s: sizeof (idn_dmv_data_t) = %lu\n",
47937656SSherry.Moore@Sun.COM 	    proc, sizeof (idn_dmv_data_t));
4794931Smathue 	PR_PROTO("%s: allocating %lu bytes for dmv data area\n", proc, len);
47950Sstevel@tonic-gate 
47960Sstevel@tonic-gate 	idn.intr.dmv_data_len = len;
47970Sstevel@tonic-gate 	idn.intr.dmv_data = kmem_zalloc(len, KM_SLEEP);
47980Sstevel@tonic-gate 
4799*11311SSurya.Prakki@Sun.COM 	PR_PROTO("%s: DMV data area = %p\n", proc, (void *)idn.intr.dmv_data);
48000Sstevel@tonic-gate 
48010Sstevel@tonic-gate 	idn_dmv_data = (idn_dmv_data_t *)idn.intr.dmv_data;
48020Sstevel@tonic-gate 	basep = (idn_dmv_msg_t *)roundup((size_t)idn.intr.dmv_data +
48037656SSherry.Moore@Sun.COM 	    sizeof (idn_dmv_data_t),
48047656SSherry.Moore@Sun.COM 	    sizeof (uint64_t));
48050Sstevel@tonic-gate 	idn_dmv_data->idn_dmv_qbase = (uint64_t)basep;
48060Sstevel@tonic-gate 
48070Sstevel@tonic-gate 	ivp = basep;
48080Sstevel@tonic-gate 	ivp_offset = 0;
48090Sstevel@tonic-gate 	/*
48100Sstevel@tonic-gate 	 * The buffer queues are allocated per-cpu.
48110Sstevel@tonic-gate 	 */
48120Sstevel@tonic-gate 	for (c = 0, ivp = basep; c < NCPU; ivp++, c++) {
48130Sstevel@tonic-gate 		idn_dmv_data->idn_dmv_cpu[c].idn_dmv_current = ivp_offset;
48140Sstevel@tonic-gate 		idn_iv_queue[c] = ivp;
48150Sstevel@tonic-gate 		ivp_offset += sizeof (idn_dmv_msg_t);
48160Sstevel@tonic-gate 		for (i = 1; i < idn_dmv_pending_max; ivp++, i++) {
48170Sstevel@tonic-gate 			ivp->iv_next = ivp_offset;
48180Sstevel@tonic-gate 			ivp->iv_ready = 0;
48190Sstevel@tonic-gate 			lock_set(&ivp->iv_ready);
48200Sstevel@tonic-gate 			ivp_offset += sizeof (idn_dmv_msg_t);
48210Sstevel@tonic-gate 		}
48220Sstevel@tonic-gate 		ivp->iv_next = idn_dmv_data->idn_dmv_cpu[c].idn_dmv_current;
48230Sstevel@tonic-gate 		ivp->iv_ready = 0;
48240Sstevel@tonic-gate 		lock_set(&ivp->iv_ready);
48250Sstevel@tonic-gate 	}
48260Sstevel@tonic-gate 
48270Sstevel@tonic-gate 	idn.intr.dmv_inum = STARFIRE_DMV_IDN_BASE;
48282973Sgovinda 	idn.intr.soft_inum = add_softintr((uint_t)idn_pil, idn_handler, 0,
48292973Sgovinda 	    SOFTINT_ST);
48300Sstevel@tonic-gate 	idn_dmv_data->idn_soft_inum = idn.intr.soft_inum;
48310Sstevel@tonic-gate 	/*
48320Sstevel@tonic-gate 	 * Make sure everything is out there before
48330Sstevel@tonic-gate 	 * we effectively set it free for use.
48340Sstevel@tonic-gate 	 */
48350Sstevel@tonic-gate 	membar_stld_stst();
48360Sstevel@tonic-gate 
48370Sstevel@tonic-gate 	if (dmv_add_intr(idn.intr.dmv_inum, idn_dmv_handler,
48387656SSherry.Moore@Sun.COM 	    (caddr_t)idn_dmv_data)) {
48390Sstevel@tonic-gate 		idn_deinit_handler();
48400Sstevel@tonic-gate 		cmn_err(CE_WARN, "IDN: 132: failed to add IDN DMV handler");
48410Sstevel@tonic-gate 		return (-1);
48420Sstevel@tonic-gate 	}
48430Sstevel@tonic-gate 
48440Sstevel@tonic-gate 	return (0);
48450Sstevel@tonic-gate }
48460Sstevel@tonic-gate 
48470Sstevel@tonic-gate static void
idn_deinit_handler()48480Sstevel@tonic-gate idn_deinit_handler()
48490Sstevel@tonic-gate {
48500Sstevel@tonic-gate 	if (idn.intr.dmv_data == NULL)
48510Sstevel@tonic-gate 		return;
48520Sstevel@tonic-gate 
48530Sstevel@tonic-gate 	(void) dmv_rem_intr(idn.intr.dmv_inum);
48542973Sgovinda 	(void) rem_softintr(idn.intr.soft_inum);
48550Sstevel@tonic-gate 	kmem_free(idn.intr.dmv_data, idn.intr.dmv_data_len);
48560Sstevel@tonic-gate 	idn.intr.dmv_data = NULL;
48570Sstevel@tonic-gate }
48580Sstevel@tonic-gate 
48590Sstevel@tonic-gate /*
48600Sstevel@tonic-gate  * High-level (soft interrupt) handler for DMV interrupts
48610Sstevel@tonic-gate  */
48620Sstevel@tonic-gate /*ARGSUSED0*/
48630Sstevel@tonic-gate static uint_t
idn_handler(caddr_t unused,caddr_t unused2)48640Sstevel@tonic-gate idn_handler(caddr_t unused, caddr_t unused2)
48650Sstevel@tonic-gate {
48660Sstevel@tonic-gate #ifdef DEBUG
48670Sstevel@tonic-gate 	int		count = 0;
48680Sstevel@tonic-gate #endif /* DEBUG */
48690Sstevel@tonic-gate 	int		cpuid = (int)CPU->cpu_id;
48700Sstevel@tonic-gate 	ushort_t	mtype, atype;
48710Sstevel@tonic-gate 	idn_dmv_msg_t	*xp, *xplimit;
48720Sstevel@tonic-gate 	procname_t	proc = "idn_handler";
48730Sstevel@tonic-gate 
48740Sstevel@tonic-gate 	ASSERT(getpil() >= idn_pil);
48750Sstevel@tonic-gate 	flush_windows();
48760Sstevel@tonic-gate 
48770Sstevel@tonic-gate 	/*
48780Sstevel@tonic-gate 	 * Clear the synchronization flag to indicate that
48790Sstevel@tonic-gate 	 * processing has started.  As long as idn_dmv_active
48800Sstevel@tonic-gate 	 * is non-zero, idn_dmv_handler will queue work without
48810Sstevel@tonic-gate 	 * initiating a soft interrupt.  Since we clear it
48820Sstevel@tonic-gate 	 * first thing at most one pil-interrupt for IDN will
48830Sstevel@tonic-gate 	 * queue up behind the currently active one.  We don't
48840Sstevel@tonic-gate 	 * want to clear this flag at the end because it leaves
48850Sstevel@tonic-gate 	 * a window where an interrupt could get lost (unless it's
48860Sstevel@tonic-gate 	 * pushed by a subsequent interrupt).  The objective in
48872973Sgovinda 	 * doing this is to prevent exhausting a cpu's intr_vec
48880Sstevel@tonic-gate 	 * structures with interrupts of the same pil level.
48890Sstevel@tonic-gate 	 */
48900Sstevel@tonic-gate 	lock_clear(&idn_dmv_data->idn_dmv_cpu[cpuid].idn_dmv_active);
48910Sstevel@tonic-gate 
48920Sstevel@tonic-gate 	xp = idn_iv_queue[cpuid];
48930Sstevel@tonic-gate 	xplimit = xp + idn_dmv_pending_max;
48940Sstevel@tonic-gate 	xp += idn_intr_index[cpuid];
48950Sstevel@tonic-gate 	/*
48960Sstevel@tonic-gate 	 * As long as there's stuff that's READY in the
48970Sstevel@tonic-gate 	 * queue, keep processing.
48980Sstevel@tonic-gate 	 */
48990Sstevel@tonic-gate 	while (lock_try(&xp->iv_ready)) {
49000Sstevel@tonic-gate 
49010Sstevel@tonic-gate 		ASSERT(lock_try(&xp->iv_inuse) == 0);
49020Sstevel@tonic-gate 
49030Sstevel@tonic-gate 		mtype = (ushort_t)xp->iv_mtype;
49040Sstevel@tonic-gate 		mtype &= IDNP_MSGTYPE_MASK | IDNP_ACKNACK_MASK;
49050Sstevel@tonic-gate 		atype = (ushort_t)xp->iv_atype;
49060Sstevel@tonic-gate 
49070Sstevel@tonic-gate 		if (((int)xp->iv_ver == idn.version) && mtype) {
49080Sstevel@tonic-gate 			idn_protojob_t	*jp;
49090Sstevel@tonic-gate #ifdef DEBUG
49100Sstevel@tonic-gate 			STRING(mstr);
49110Sstevel@tonic-gate 			STRING(astr);
49120Sstevel@tonic-gate 
49130Sstevel@tonic-gate 			INUM2STR(mtype, mstr);
49140Sstevel@tonic-gate 			if ((mtype & IDNP_MSGTYPE_MASK) == 0) {
49150Sstevel@tonic-gate 				INUM2STR(atype, astr);
4916*11311SSurya.Prakki@Sun.COM 				(void) strcat(mstr, "/");
4917*11311SSurya.Prakki@Sun.COM 				(void) strcat(mstr, astr);
49180Sstevel@tonic-gate 			}
49190Sstevel@tonic-gate 
49200Sstevel@tonic-gate 			count++;
49210Sstevel@tonic-gate 
49220Sstevel@tonic-gate 			PR_XDC("%s:%d:%d RECV: scpu = %d, msg = 0x%x(%s)\n",
49237656SSherry.Moore@Sun.COM 			    proc, (int)xp->iv_domid, count,
49247656SSherry.Moore@Sun.COM 			    (int)xp->iv_cpuid, mtype, mstr);
49250Sstevel@tonic-gate 			PR_XDC("%s:%d:%d R-DATA: a0 = 0x%x, a1 = 0x%x\n",
49267656SSherry.Moore@Sun.COM 			    proc, (int)xp->iv_domid, count,
49277656SSherry.Moore@Sun.COM 			    xp->iv_xargs0, xp->iv_xargs1);
49280Sstevel@tonic-gate 			PR_XDC("%s:%d:%d R-DATA: a2 = 0x%x, a3 = 0x%x\n",
49297656SSherry.Moore@Sun.COM 			    proc, (int)xp->iv_domid, count,
49307656SSherry.Moore@Sun.COM 			    xp->iv_xargs2, xp->iv_xargs3);
49310Sstevel@tonic-gate #endif /* DEBUG */
49320Sstevel@tonic-gate 
49330Sstevel@tonic-gate 			if (mtype == IDNP_DATA) {
49340Sstevel@tonic-gate 				jp = NULL;
49350Sstevel@tonic-gate 				/*
49360Sstevel@tonic-gate 				 * The only time we receive pure
49370Sstevel@tonic-gate 				 * data messages at this level is
49380Sstevel@tonic-gate 				 * to wake up the channel server.
49390Sstevel@tonic-gate 				 * Since this is often an urgent
49400Sstevel@tonic-gate 				 * request we'll do it from here
49410Sstevel@tonic-gate 				 * instead of waiting for a proto
49420Sstevel@tonic-gate 				 * server to do it.
49430Sstevel@tonic-gate 				 */
49440Sstevel@tonic-gate 				idn_signal_data_server((int)xp->iv_domid,
49457656SSherry.Moore@Sun.COM 				    (ushort_t)xp->iv_xargs0);
49460Sstevel@tonic-gate 			} else {
49470Sstevel@tonic-gate 				jp = idn_protojob_alloc(KM_NOSLEEP);
49480Sstevel@tonic-gate 				/*
49490Sstevel@tonic-gate 				 * If the allocation fails, just drop
49500Sstevel@tonic-gate 				 * the message and get on with life.
49510Sstevel@tonic-gate 				 * If memory pressure is this great then
49520Sstevel@tonic-gate 				 * dropping this message is probably
49530Sstevel@tonic-gate 				 * the least of our worries!
49540Sstevel@tonic-gate 				 */
49550Sstevel@tonic-gate 				if (jp) {
49560Sstevel@tonic-gate 					jp->j_msg.m_domid = (int)xp->iv_domid;
49570Sstevel@tonic-gate 					jp->j_msg.m_cpuid = (int)xp->iv_cpuid;
49580Sstevel@tonic-gate 					jp->j_msg.m_msgtype = mtype;
49590Sstevel@tonic-gate 					jp->j_msg.m_acktype = atype;
49600Sstevel@tonic-gate 					jp->j_msg.m_cookie = xp->iv_cookie;
49610Sstevel@tonic-gate 					SET_XARGS(jp->j_msg.m_xargs,
49627656SSherry.Moore@Sun.COM 					    xp->iv_xargs0, xp->iv_xargs1,
49637656SSherry.Moore@Sun.COM 					    xp->iv_xargs2, xp->iv_xargs3);
49640Sstevel@tonic-gate 				}
49650Sstevel@tonic-gate 
49660Sstevel@tonic-gate 			}
49670Sstevel@tonic-gate 			membar_ldst_stst();
49680Sstevel@tonic-gate 
49690Sstevel@tonic-gate 			lock_clear(&xp->iv_inuse);
49700Sstevel@tonic-gate 
49710Sstevel@tonic-gate 			if (jp)
49720Sstevel@tonic-gate 				idn_protojob_submit(jp->j_msg.m_domid, jp);
49730Sstevel@tonic-gate 		} else {
49740Sstevel@tonic-gate 			membar_ldst_stst();
49750Sstevel@tonic-gate 			IDN_GKSTAT_INC(gk_dropped_intrs);
49760Sstevel@tonic-gate 			lock_clear(&xp->iv_inuse);
49770Sstevel@tonic-gate 		}
49780Sstevel@tonic-gate 
49790Sstevel@tonic-gate 		if (++xp == xplimit)
49800Sstevel@tonic-gate 			xp = idn_iv_queue[cpuid];
49810Sstevel@tonic-gate 	}
49820Sstevel@tonic-gate 
49830Sstevel@tonic-gate 	idn_intr_index[cpuid] = xp - idn_iv_queue[cpuid];
49840Sstevel@tonic-gate 
49850Sstevel@tonic-gate 	return (DDI_INTR_CLAIMED);
49860Sstevel@tonic-gate }
49870Sstevel@tonic-gate 
49880Sstevel@tonic-gate void
idn_awol_event_set(boardset_t boardset)49890Sstevel@tonic-gate idn_awol_event_set(boardset_t boardset)
49900Sstevel@tonic-gate {
49910Sstevel@tonic-gate 	idnsb_event_t	*sbp;
49920Sstevel@tonic-gate 	procname_t	proc = "idn_awol_event_set";
49930Sstevel@tonic-gate 
49940Sstevel@tonic-gate 	ASSERT(IDN_GLOCK_IS_EXCL());
49950Sstevel@tonic-gate 
49960Sstevel@tonic-gate 	mutex_enter(&idn.idnsb_mutex);
49970Sstevel@tonic-gate 	sbp = idn.idnsb_eventp;
49980Sstevel@tonic-gate 	if (sbp == NULL) {
49990Sstevel@tonic-gate 		cmn_err(CE_WARN, "IDN: 133: sigblock event area missing");
50000Sstevel@tonic-gate 		cmn_err(CE_CONT,
50017656SSherry.Moore@Sun.COM 		    "IDN: 134: unable to mark boardset (0x%x) AWOL\n",
50027656SSherry.Moore@Sun.COM 		    boardset);
50030Sstevel@tonic-gate 		mutex_exit(&idn.idnsb_mutex);
50040Sstevel@tonic-gate 		return;
50050Sstevel@tonic-gate 	}
50060Sstevel@tonic-gate 
50070Sstevel@tonic-gate 	if (boardset == 0) {
50080Sstevel@tonic-gate 		PR_PROTO("%s: AWOL BOARDSET is 0, NO EVENT <<<<<<<<<<<<<<<\n",
50097656SSherry.Moore@Sun.COM 		    proc);
50100Sstevel@tonic-gate 		mutex_exit(&idn.idnsb_mutex);
50110Sstevel@tonic-gate 		return;
50120Sstevel@tonic-gate 	} else {
50130Sstevel@tonic-gate 		PR_PROTO("%s: MARKING BOARDSET (0x%x) AWOL\n", proc, boardset);
50140Sstevel@tonic-gate 	}
50150Sstevel@tonic-gate 	SSIEVENT_ADD(sbp, SSIEVENT_AWOL, boardset);
50160Sstevel@tonic-gate 	mutex_exit(&idn.idnsb_mutex);
50170Sstevel@tonic-gate }
50180Sstevel@tonic-gate 
50190Sstevel@tonic-gate void
idn_awol_event_clear(boardset_t boardset)50200Sstevel@tonic-gate idn_awol_event_clear(boardset_t boardset)
50210Sstevel@tonic-gate {
50220Sstevel@tonic-gate 	idnsb_event_t	*sbp;
50230Sstevel@tonic-gate 	procname_t	proc = "idn_awol_event_clear";
50240Sstevel@tonic-gate 
50250Sstevel@tonic-gate 	ASSERT(IDN_GLOCK_IS_EXCL());
50260Sstevel@tonic-gate 
50270Sstevel@tonic-gate 	mutex_enter(&idn.idnsb_mutex);
50280Sstevel@tonic-gate 	sbp = idn.idnsb_eventp;
50290Sstevel@tonic-gate 	if (sbp == NULL) {
50300Sstevel@tonic-gate 		cmn_err(CE_WARN, "IDN: 133: sigblock event area missing");
50310Sstevel@tonic-gate 		cmn_err(CE_CONT,
50327656SSherry.Moore@Sun.COM 		    "IDN: 134: unable to mark boardset (0x%x) AWOL\n",
50337656SSherry.Moore@Sun.COM 		    boardset);
50340Sstevel@tonic-gate 		mutex_exit(&idn.idnsb_mutex);
50350Sstevel@tonic-gate 		return;
50360Sstevel@tonic-gate 	}
50370Sstevel@tonic-gate 
50380Sstevel@tonic-gate 	if (boardset == 0) {
50390Sstevel@tonic-gate 		PR_PROTO("%s: AWOL BOARDSET is 0, NO EVENT <<<<<<<<<<<<<<<\n",
50407656SSherry.Moore@Sun.COM 		    proc);
50410Sstevel@tonic-gate 		mutex_exit(&idn.idnsb_mutex);
50420Sstevel@tonic-gate 		return;
50430Sstevel@tonic-gate 	} else {
50440Sstevel@tonic-gate 		PR_PROTO("%s: CLEARING BOARDSET (0x%x) AWOL\n", proc, boardset);
50450Sstevel@tonic-gate 	}
50460Sstevel@tonic-gate 	SSIEVENT_DEL(sbp, SSIEVENT_AWOL, boardset);
50470Sstevel@tonic-gate 	mutex_exit(&idn.idnsb_mutex);
50480Sstevel@tonic-gate }
50490Sstevel@tonic-gate 
50500Sstevel@tonic-gate static void
idn_gkstat_init()50510Sstevel@tonic-gate idn_gkstat_init()
50520Sstevel@tonic-gate {
50530Sstevel@tonic-gate 	struct	kstat			*ksp;
50540Sstevel@tonic-gate 	struct	idn_gkstat_named	*sgkp;
50550Sstevel@tonic-gate 
50560Sstevel@tonic-gate #ifdef	kstat
50570Sstevel@tonic-gate 	if ((ksp = kstat_create(IDNNAME, ddi_get_instance(idn.dip),
50587656SSherry.Moore@Sun.COM 	    IDNNAME, "net", KSTAT_TYPE_NAMED,
50597656SSherry.Moore@Sun.COM 	    sizeof (struct idn_gkstat_named) / sizeof (kstat_named_t),
50607656SSherry.Moore@Sun.COM 	    KSTAT_FLAG_PERSISTENT)) == NULL) {
50610Sstevel@tonic-gate #else
50620Sstevel@tonic-gate 	if ((ksp = kstat_create(IDNNAME, ddi_get_instance(idn.dip),
50637656SSherry.Moore@Sun.COM 	    IDNNAME, "net", KSTAT_TYPE_NAMED,
50647656SSherry.Moore@Sun.COM 	    sizeof (struct idn_gkstat_named) /
50657656SSherry.Moore@Sun.COM 	    sizeof (kstat_named_t), 0)) == NULL) {
50660Sstevel@tonic-gate #endif /* kstat */
50670Sstevel@tonic-gate 		cmn_err(CE_CONT, "IDN: 135: %s: %s\n",
50687656SSherry.Moore@Sun.COM 		    IDNNAME, "kstat_create failed");
50690Sstevel@tonic-gate 		return;
50700Sstevel@tonic-gate 	}
50710Sstevel@tonic-gate 
50720Sstevel@tonic-gate 	idn.ksp = ksp;
50730Sstevel@tonic-gate 	sgkp = (struct idn_gkstat_named *)(ksp->ks_data);
50740Sstevel@tonic-gate 	kstat_named_init(&sgkp->sk_curtime,		"curtime",
50757656SSherry.Moore@Sun.COM 	    KSTAT_DATA_ULONG);
50760Sstevel@tonic-gate 	kstat_named_init(&sgkp->sk_reconfigs,		"reconfigs",
50777656SSherry.Moore@Sun.COM 	    KSTAT_DATA_ULONG);
50780Sstevel@tonic-gate 	kstat_named_init(&sgkp->sk_reconfig_last,	"reconfig_last",
50797656SSherry.Moore@Sun.COM 	    KSTAT_DATA_ULONG);
50800Sstevel@tonic-gate 	kstat_named_init(&sgkp->sk_reaps,		"reaps",
50817656SSherry.Moore@Sun.COM 	    KSTAT_DATA_ULONG);
50820Sstevel@tonic-gate 	kstat_named_init(&sgkp->sk_reap_last,		"reap_last",
50837656SSherry.Moore@Sun.COM 	    KSTAT_DATA_ULONG);
50840Sstevel@tonic-gate 	kstat_named_init(&sgkp->sk_links,		"links",
50857656SSherry.Moore@Sun.COM 	    KSTAT_DATA_ULONG);
50860Sstevel@tonic-gate 	kstat_named_init(&sgkp->sk_link_last,		"link_last",
50877656SSherry.Moore@Sun.COM 	    KSTAT_DATA_ULONG);
50880Sstevel@tonic-gate 	kstat_named_init(&sgkp->sk_unlinks,		"unlinks",
50897656SSherry.Moore@Sun.COM 	    KSTAT_DATA_ULONG);
50900Sstevel@tonic-gate 	kstat_named_init(&sgkp->sk_unlink_last,		"unlink_last",
50917656SSherry.Moore@Sun.COM 	    KSTAT_DATA_ULONG);
50920Sstevel@tonic-gate 	kstat_named_init(&sgkp->sk_buffail,		"buf_fail",
50937656SSherry.Moore@Sun.COM 	    KSTAT_DATA_ULONG);
50940Sstevel@tonic-gate 	kstat_named_init(&sgkp->sk_buffail_last,	"buf_fail_last",
50957656SSherry.Moore@Sun.COM 	    KSTAT_DATA_ULONG);
50960Sstevel@tonic-gate 	kstat_named_init(&sgkp->sk_slabfail,		"slab_fail",
50977656SSherry.Moore@Sun.COM 	    KSTAT_DATA_ULONG);
50980Sstevel@tonic-gate 	kstat_named_init(&sgkp->sk_slabfail_last,	"slab_fail_last",
50997656SSherry.Moore@Sun.COM 	    KSTAT_DATA_ULONG);
51000Sstevel@tonic-gate 	kstat_named_init(&sgkp->sk_slabfail_last,	"slab_fail_last",
51017656SSherry.Moore@Sun.COM 	    KSTAT_DATA_ULONG);
51020Sstevel@tonic-gate 	kstat_named_init(&sgkp->sk_reap_count,		"reap_count",
51037656SSherry.Moore@Sun.COM 	    KSTAT_DATA_ULONG);
51040Sstevel@tonic-gate 	kstat_named_init(&sgkp->sk_dropped_intrs,	"dropped_intrs",
51057656SSherry.Moore@Sun.COM 	    KSTAT_DATA_ULONG);
51060Sstevel@tonic-gate 	ksp->ks_update = idn_gkstat_update;
51070Sstevel@tonic-gate 	ksp->ks_private = (void *)NULL;
51080Sstevel@tonic-gate 	kstat_install(ksp);
51090Sstevel@tonic-gate }
51100Sstevel@tonic-gate 
51110Sstevel@tonic-gate static void
51120Sstevel@tonic-gate idn_gkstat_deinit()
51130Sstevel@tonic-gate {
51140Sstevel@tonic-gate 	if (idn.ksp)
51150Sstevel@tonic-gate 		kstat_delete(idn.ksp);
51160Sstevel@tonic-gate 	idn.ksp = NULL;
51170Sstevel@tonic-gate }
51180Sstevel@tonic-gate 
51190Sstevel@tonic-gate static int
51200Sstevel@tonic-gate idn_gkstat_update(kstat_t *ksp, int rw)
51210Sstevel@tonic-gate {
51220Sstevel@tonic-gate 	struct idn_gkstat_named	*sgkp;
51230Sstevel@tonic-gate 
51240Sstevel@tonic-gate 	sgkp = (struct idn_gkstat_named *)ksp->ks_data;
51250Sstevel@tonic-gate 
51260Sstevel@tonic-gate 	if (rw == KSTAT_WRITE) {
51270Sstevel@tonic-gate 		sg_kstat.gk_reconfigs	    = sgkp->sk_reconfigs.value.ul;
51280Sstevel@tonic-gate 		sg_kstat.gk_reconfig_last   = sgkp->sk_reconfig_last.value.ul;
51290Sstevel@tonic-gate 		sg_kstat.gk_reaps	    = sgkp->sk_reaps.value.ul;
51300Sstevel@tonic-gate 		sg_kstat.gk_reap_last	    = sgkp->sk_reap_last.value.ul;
51310Sstevel@tonic-gate 		sg_kstat.gk_links	    = sgkp->sk_links.value.ul;
51320Sstevel@tonic-gate 		sg_kstat.gk_link_last	    = sgkp->sk_link_last.value.ul;
51330Sstevel@tonic-gate 		sg_kstat.gk_unlinks	    = sgkp->sk_unlinks.value.ul;
51340Sstevel@tonic-gate 		sg_kstat.gk_unlink_last	    = sgkp->sk_unlink_last.value.ul;
51350Sstevel@tonic-gate 		sg_kstat.gk_buffail	    = sgkp->sk_buffail.value.ul;
51360Sstevel@tonic-gate 		sg_kstat.gk_buffail_last    = sgkp->sk_buffail_last.value.ul;
51370Sstevel@tonic-gate 		sg_kstat.gk_slabfail	    = sgkp->sk_slabfail.value.ul;
51380Sstevel@tonic-gate 		sg_kstat.gk_slabfail_last   = sgkp->sk_slabfail_last.value.ul;
51390Sstevel@tonic-gate 		sg_kstat.gk_reap_count	    = sgkp->sk_reap_count.value.ul;
51400Sstevel@tonic-gate 		sg_kstat.gk_dropped_intrs   = sgkp->sk_dropped_intrs.value.ul;
51410Sstevel@tonic-gate 	} else {
514211066Srafael.vanoni@sun.com 		sgkp->sk_curtime.value.ul	  = ddi_get_lbolt();
51430Sstevel@tonic-gate 		sgkp->sk_reconfigs.value.ul	  = sg_kstat.gk_reconfigs;
51440Sstevel@tonic-gate 		sgkp->sk_reconfig_last.value.ul	  = sg_kstat.gk_reconfig_last;
51450Sstevel@tonic-gate 		sgkp->sk_reaps.value.ul		  = sg_kstat.gk_reaps;
51460Sstevel@tonic-gate 		sgkp->sk_reap_last.value.ul	  = sg_kstat.gk_reap_last;
51470Sstevel@tonic-gate 		sgkp->sk_links.value.ul		  = sg_kstat.gk_links;
51480Sstevel@tonic-gate 		sgkp->sk_link_last.value.ul	  = sg_kstat.gk_link_last;
51490Sstevel@tonic-gate 		sgkp->sk_unlinks.value.ul	  = sg_kstat.gk_unlinks;
51500Sstevel@tonic-gate 		sgkp->sk_unlink_last.value.ul	  = sg_kstat.gk_unlink_last;
51510Sstevel@tonic-gate 		sgkp->sk_buffail.value.ul	  = sg_kstat.gk_buffail;
51520Sstevel@tonic-gate 		sgkp->sk_buffail_last.value.ul    = sg_kstat.gk_buffail_last;
51530Sstevel@tonic-gate 		sgkp->sk_slabfail.value.ul	  = sg_kstat.gk_slabfail;
51540Sstevel@tonic-gate 		sgkp->sk_slabfail_last.value.ul   = sg_kstat.gk_slabfail_last;
51550Sstevel@tonic-gate 		sgkp->sk_reap_count.value.ul	  = sg_kstat.gk_reap_count;
51560Sstevel@tonic-gate 		sgkp->sk_dropped_intrs.value.ul	  = sg_kstat.gk_dropped_intrs;
51570Sstevel@tonic-gate 	}
51580Sstevel@tonic-gate 
51590Sstevel@tonic-gate 	return (0);
51600Sstevel@tonic-gate }
51610Sstevel@tonic-gate 
51620Sstevel@tonic-gate #ifdef DEBUG
51630Sstevel@tonic-gate #define	RW_HISTORY	100
51640Sstevel@tonic-gate static uint_t	rw_history[NCPU][RW_HISTORY];
51650Sstevel@tonic-gate static int	rw_index[NCPU];
51660Sstevel@tonic-gate #endif /* DEBUG */
51670Sstevel@tonic-gate 
51680Sstevel@tonic-gate static int
51690Sstevel@tonic-gate idn_rw_mem(idnop_t *idnop)
51700Sstevel@tonic-gate {
51710Sstevel@tonic-gate 	uint_t		lo_off, hi_off;
51720Sstevel@tonic-gate 	int		rw, blksize, num;
51730Sstevel@tonic-gate 	int		cpuid;
51740Sstevel@tonic-gate 	register int	n, idx;
51750Sstevel@tonic-gate 	char 		*ibuf, *obuf;
51760Sstevel@tonic-gate 	char		*smraddr;
51770Sstevel@tonic-gate 	struct seg	*segp;
51780Sstevel@tonic-gate 	ulong_t		randx;
51790Sstevel@tonic-gate 	kmutex_t	slock;
51800Sstevel@tonic-gate 	kcondvar_t	scv;
51810Sstevel@tonic-gate 	static int	orig_gstate = IDNGS_IGNORE;
51820Sstevel@tonic-gate 	extern struct  seg	ktextseg;
51830Sstevel@tonic-gate 
518411066Srafael.vanoni@sun.com #define	RANDOM_INIT()	(randx = ddi_get_lbolt())
51850Sstevel@tonic-gate #define	RANDOM(a, b)	\
51860Sstevel@tonic-gate 	(((a) >= (b)) ? \
51870Sstevel@tonic-gate 	(a) : (((randx = randx * 1103515245L + 12345) % ((b)-(a))) + (a)))
51880Sstevel@tonic-gate 
51890Sstevel@tonic-gate 	RANDOM_INIT();
51900Sstevel@tonic-gate 
51910Sstevel@tonic-gate 	lo_off  = idnop->rwmem.lo_off;
51920Sstevel@tonic-gate 	hi_off  = idnop->rwmem.hi_off;
51930Sstevel@tonic-gate 	blksize = idnop->rwmem.blksize;
51940Sstevel@tonic-gate 	num	= idnop->rwmem.num;
51950Sstevel@tonic-gate 	rw	= idnop->rwmem.rw;	/* 0 = rd, 1 = wr, 2 = rd/wr */
51960Sstevel@tonic-gate 
51970Sstevel@tonic-gate 	if (((hi_off > (uint_t)MB2B(IDN_SMR_SIZE)) || (lo_off >= hi_off) ||
51980Sstevel@tonic-gate 	    (blksize <= 0) || (blksize > (hi_off - lo_off)) || (num <= 0)) &&
51990Sstevel@tonic-gate 	    (idnop->rwmem.goawol == -1)) {
52000Sstevel@tonic-gate 		return (EINVAL);
52010Sstevel@tonic-gate 	}
52020Sstevel@tonic-gate 
52030Sstevel@tonic-gate 	if (idnop->rwmem.goawol && (orig_gstate == IDNGS_IGNORE)) {
52040Sstevel@tonic-gate 		IDN_GLOCK_EXCL();
52050Sstevel@tonic-gate 		cmn_err(CE_WARN, "IDN: Local domain going into IGNORE MODE!!");
52060Sstevel@tonic-gate 		orig_gstate = idn.state;
52070Sstevel@tonic-gate 		IDN_GSTATE_TRANSITION(IDNGS_IGNORE);
52080Sstevel@tonic-gate 		IDN_GUNLOCK();
52090Sstevel@tonic-gate 
52100Sstevel@tonic-gate 	} else if (!idnop->rwmem.goawol && (orig_gstate != IDNGS_IGNORE)) {
52110Sstevel@tonic-gate 		IDN_GLOCK_EXCL();
52120Sstevel@tonic-gate 		cmn_err(CE_WARN,
52137656SSherry.Moore@Sun.COM 		    "IDN: Local domain restoring original state %s(%d)",
52147656SSherry.Moore@Sun.COM 		    idngs_str[orig_gstate], (int)orig_gstate);
52150Sstevel@tonic-gate 		IDN_GSTATE_TRANSITION(orig_gstate);
52160Sstevel@tonic-gate 		orig_gstate = IDNGS_IGNORE;
52170Sstevel@tonic-gate 		IDN_GUNLOCK();
52180Sstevel@tonic-gate 	}
52190Sstevel@tonic-gate 	/*
52200Sstevel@tonic-gate 	 * Just requested AWOL.
52210Sstevel@tonic-gate 	 */
52220Sstevel@tonic-gate 	if (num == 0)
52230Sstevel@tonic-gate 		return (0);
52240Sstevel@tonic-gate 	/*
52250Sstevel@tonic-gate 	 * Default READ only.
52260Sstevel@tonic-gate 	 */
52270Sstevel@tonic-gate 	ibuf = (char *)kmem_alloc(blksize, KM_SLEEP);
52280Sstevel@tonic-gate 	if (rw == 1) {
52290Sstevel@tonic-gate 		/*
52300Sstevel@tonic-gate 		 * WRITE only.
52310Sstevel@tonic-gate 		 */
52320Sstevel@tonic-gate 		obuf = ibuf;
52330Sstevel@tonic-gate 		ibuf = NULL;
52340Sstevel@tonic-gate 	} else if (rw == 2) {
52350Sstevel@tonic-gate 		/*
52360Sstevel@tonic-gate 		 * READ/WRITE.
52370Sstevel@tonic-gate 		 */
52380Sstevel@tonic-gate 		obuf = (char *)kmem_alloc(blksize, KM_SLEEP);
52390Sstevel@tonic-gate 		for (segp = &ktextseg; segp; segp = AS_SEGNEXT(&kas, segp)) {
52400Sstevel@tonic-gate 			if (segp->s_size >= blksize)
52410Sstevel@tonic-gate 				break;
52420Sstevel@tonic-gate 		}
52430Sstevel@tonic-gate 		if (segp == NULL) {
52440Sstevel@tonic-gate 			cmn_err(CE_WARN,
52457656SSherry.Moore@Sun.COM 			    "IDN: blksize (%d) too large", blksize);
52460Sstevel@tonic-gate 			return (EINVAL);
52470Sstevel@tonic-gate 		}
52480Sstevel@tonic-gate 		bcopy(segp->s_base, obuf, blksize);
52490Sstevel@tonic-gate 	}
52500Sstevel@tonic-gate 
52510Sstevel@tonic-gate 	mutex_init(&slock, NULL, MUTEX_DEFAULT, NULL);
52520Sstevel@tonic-gate 	cv_init(&scv, NULL, CV_DEFAULT, NULL);
52530Sstevel@tonic-gate 
52540Sstevel@tonic-gate 	cmn_err(CE_NOTE,
52557656SSherry.Moore@Sun.COM 	    "IDN: starting %s of %d blocks of %d bytes each...",
52567656SSherry.Moore@Sun.COM 	    (rw == 1) ? "W-ONLY" : (rw == 2) ? "RW" : "R-ONLY",
52577656SSherry.Moore@Sun.COM 	    num, blksize);
52580Sstevel@tonic-gate 
52590Sstevel@tonic-gate 	for (n = 0; n < num; n++) {
52600Sstevel@tonic-gate 		uint_t	rpos;
52610Sstevel@tonic-gate 
52620Sstevel@tonic-gate 		if ((hi_off - lo_off) > blksize)
52630Sstevel@tonic-gate 			rpos = RANDOM(lo_off, (hi_off - blksize));
52640Sstevel@tonic-gate 		else
52650Sstevel@tonic-gate 			rpos = lo_off;
52660Sstevel@tonic-gate 		smraddr = IDN_OFFSET2ADDR(rpos);
52670Sstevel@tonic-gate 
52680Sstevel@tonic-gate 		cpuid = (int)CPU->cpu_id;
52690Sstevel@tonic-gate #ifdef DEBUG
52700Sstevel@tonic-gate 		idx = rw_index[cpuid]++ % RW_HISTORY;
52710Sstevel@tonic-gate 		rw_history[cpuid][idx] = rpos;
52720Sstevel@tonic-gate #endif /* DEBUG */
52730Sstevel@tonic-gate 
52740Sstevel@tonic-gate 		switch (rw) {
52750Sstevel@tonic-gate 		case 0:
52760Sstevel@tonic-gate 			bcopy(smraddr, ibuf, blksize);
52770Sstevel@tonic-gate 			break;
52780Sstevel@tonic-gate 		case 1:
52790Sstevel@tonic-gate 			bcopy(obuf, smraddr, blksize);
52800Sstevel@tonic-gate 			break;
52810Sstevel@tonic-gate 		case 2:
52820Sstevel@tonic-gate 			if (n & 1)
52830Sstevel@tonic-gate 				bcopy(obuf, smraddr, blksize);
52840Sstevel@tonic-gate 			else
52850Sstevel@tonic-gate 				bcopy(smraddr, ibuf, blksize);
52860Sstevel@tonic-gate 			break;
52870Sstevel@tonic-gate 		default:
52880Sstevel@tonic-gate 			break;
52890Sstevel@tonic-gate 		}
52900Sstevel@tonic-gate 		if (!(n % 1000)) {
52910Sstevel@tonic-gate 			int	rv;
52920Sstevel@tonic-gate 
52930Sstevel@tonic-gate 			mutex_enter(&slock);
529411066Srafael.vanoni@sun.com 			rv = cv_reltimedwait_sig(&scv, &slock, hz,
529511066Srafael.vanoni@sun.com 			    TR_CLOCK_TICK);
52960Sstevel@tonic-gate 			mutex_exit(&slock);
52970Sstevel@tonic-gate 			if (rv == 0)
52980Sstevel@tonic-gate 				break;
52990Sstevel@tonic-gate 		}
53000Sstevel@tonic-gate 	}
53010Sstevel@tonic-gate 
53020Sstevel@tonic-gate 	cv_destroy(&scv);
53030Sstevel@tonic-gate 	mutex_destroy(&slock);
53040Sstevel@tonic-gate 
53050Sstevel@tonic-gate 	if (ibuf)
53060Sstevel@tonic-gate 		kmem_free(ibuf, blksize);
53070Sstevel@tonic-gate 	if (obuf)
53080Sstevel@tonic-gate 		kmem_free(obuf, blksize);
53090Sstevel@tonic-gate 
53100Sstevel@tonic-gate 	return (0);
53110Sstevel@tonic-gate }
53120Sstevel@tonic-gate 
53130Sstevel@tonic-gate void
53140Sstevel@tonic-gate inum2str(uint_t inum, char str[])
53150Sstevel@tonic-gate {
53160Sstevel@tonic-gate 	uint_t	acknack;
53170Sstevel@tonic-gate 
53180Sstevel@tonic-gate 	str[0] = '\0';
53190Sstevel@tonic-gate 
53200Sstevel@tonic-gate 	acknack = (inum & IDNP_ACKNACK_MASK);
53210Sstevel@tonic-gate 	inum &= ~IDNP_ACKNACK_MASK;
53220Sstevel@tonic-gate 
53230Sstevel@tonic-gate 	if (!inum && !acknack) {
5324*11311SSurya.Prakki@Sun.COM 		(void) strcpy(str, idnm_str[0]);
53250Sstevel@tonic-gate 		return;
53260Sstevel@tonic-gate 	}
53270Sstevel@tonic-gate 
53280Sstevel@tonic-gate 	if (inum == 0) {
5329*11311SSurya.Prakki@Sun.COM 		(void) strcpy(str, (acknack & IDNP_ACK) ? "ack" : "nack");
53300Sstevel@tonic-gate 	} else {
53310Sstevel@tonic-gate 		if (inum < IDN_NUM_MSGTYPES)
5332*11311SSurya.Prakki@Sun.COM 			(void) strcpy(str, idnm_str[inum]);
53330Sstevel@tonic-gate 		else
5334*11311SSurya.Prakki@Sun.COM 			(void) sprintf(str, "0x%x?", inum);
53350Sstevel@tonic-gate 		if (acknack) {
53360Sstevel@tonic-gate 			if (acknack & IDNP_ACK)
5337*11311SSurya.Prakki@Sun.COM 				(void) strcat(str, "+ack");
53380Sstevel@tonic-gate 			else
5339*11311SSurya.Prakki@Sun.COM 				(void) strcat(str, "+nack");
53400Sstevel@tonic-gate 		}
53410Sstevel@tonic-gate 	}
53420Sstevel@tonic-gate }
53430Sstevel@tonic-gate 
53440Sstevel@tonic-gate boardset_t
53450Sstevel@tonic-gate cpuset2boardset(cpuset_t portset)
53460Sstevel@tonic-gate {
53470Sstevel@tonic-gate 	register int		c;
53480Sstevel@tonic-gate 	register boardset_t	bset;
53490Sstevel@tonic-gate 
53500Sstevel@tonic-gate 	bset = 0;
53510Sstevel@tonic-gate 	for (c = 0; c < NCPU; )
53520Sstevel@tonic-gate 		if (CPU_IN_SET(portset, c)) {
53530Sstevel@tonic-gate 			BOARDSET_ADD(bset, CPUID_TO_BOARDID(c));
53540Sstevel@tonic-gate 			c = (c + 4) & ~3;
53550Sstevel@tonic-gate 		} else {
53560Sstevel@tonic-gate 			c++;
53570Sstevel@tonic-gate 		}
53580Sstevel@tonic-gate 
53590Sstevel@tonic-gate 	return (bset);
53600Sstevel@tonic-gate }
53610Sstevel@tonic-gate 
53620Sstevel@tonic-gate void
53630Sstevel@tonic-gate cpuset2str(cpuset_t cset, char buffer[])
53640Sstevel@tonic-gate {
53650Sstevel@tonic-gate 	register int	c, n;
53660Sstevel@tonic-gate 
53670Sstevel@tonic-gate 	buffer[0] = '\0';
53680Sstevel@tonic-gate 	for (c = n = 0; c < NCPU; c++) {
53690Sstevel@tonic-gate 		if (!CPU_IN_SET(cset, c))
53700Sstevel@tonic-gate 			continue;
53710Sstevel@tonic-gate #ifdef DEBUG
53720Sstevel@tonic-gate 		if (strlen(buffer) >= _DSTRLEN) {
53730Sstevel@tonic-gate 			PR_PROTO("************* WARNING WARNING WARNING\n");
53740Sstevel@tonic-gate 			PR_PROTO("cpuset2str(cpu = %d) buffer "
53757656SSherry.Moore@Sun.COM 			    "OVERFLOW <<<<<<\n", c);
53760Sstevel@tonic-gate 			PR_PROTO("*******************************\n");
5377931Smathue 			(void) sprintf(&buffer[_DSTRLEN-6], "*OVER");
53780Sstevel@tonic-gate 			return;
53790Sstevel@tonic-gate 		}
53800Sstevel@tonic-gate #endif /* DEBUG */
53810Sstevel@tonic-gate 		if (n == 0)
5382931Smathue 			(void) sprintf(buffer, "%d", c);
53830Sstevel@tonic-gate 		else
5384931Smathue 			(void) sprintf(buffer, "%s, %d", buffer, c);
53850Sstevel@tonic-gate 		n++;
53860Sstevel@tonic-gate 	}
53870Sstevel@tonic-gate }
53880Sstevel@tonic-gate 
53890Sstevel@tonic-gate void
53900Sstevel@tonic-gate domainset2str(domainset_t dset, char buffer[])
53910Sstevel@tonic-gate {
53920Sstevel@tonic-gate 	/*
53930Sstevel@tonic-gate 	 * Since domainset_t and boardset_t are the
53940Sstevel@tonic-gate 	 * same (max = MAX_DOMAINS = MAX_BOARDS) we
53950Sstevel@tonic-gate 	 * can just overload boardset2str().
53960Sstevel@tonic-gate 	 */
53970Sstevel@tonic-gate 	mask2str((uint_t)dset, buffer, MAX_DOMAINS);
53980Sstevel@tonic-gate }
53990Sstevel@tonic-gate 
54000Sstevel@tonic-gate void
54010Sstevel@tonic-gate boardset2str(boardset_t bset, char buffer[])
54020Sstevel@tonic-gate {
54030Sstevel@tonic-gate 	mask2str((uint_t)bset, buffer, MAX_BOARDS);
54040Sstevel@tonic-gate }
54050Sstevel@tonic-gate 
54060Sstevel@tonic-gate void
54070Sstevel@tonic-gate mask2str(uint_t mask, char buffer[], int maxnum)
54080Sstevel@tonic-gate {
54090Sstevel@tonic-gate 	int	n, i;
54100Sstevel@tonic-gate 
54110Sstevel@tonic-gate 	buffer[0] = '\0';
54120Sstevel@tonic-gate 	for (i = n = 0; i < maxnum; i++) {
54130Sstevel@tonic-gate 		if ((mask & (1 << i)) == 0)
54140Sstevel@tonic-gate 			continue;
54150Sstevel@tonic-gate 		if (n == 0)
5416931Smathue 			(void) sprintf(buffer, "%d", i);
54170Sstevel@tonic-gate 		else
5418931Smathue 			(void) sprintf(buffer, "%s, %d", buffer, i);
54190Sstevel@tonic-gate 		n++;
54200Sstevel@tonic-gate 	}
54210Sstevel@tonic-gate }
54220Sstevel@tonic-gate 
54230Sstevel@tonic-gate int
54240Sstevel@tonic-gate idnxdc(int domid, idn_msgtype_t *mtp,
54250Sstevel@tonic-gate 	uint_t arg1, uint_t arg2,
54260Sstevel@tonic-gate 	uint_t arg3, uint_t arg4)
54270Sstevel@tonic-gate {
54280Sstevel@tonic-gate 	int		rv, cpuid, tcpuid;
54290Sstevel@tonic-gate 	uint_t		cookie;
54300Sstevel@tonic-gate 	uint64_t	pdata;
54310Sstevel@tonic-gate 	uint64_t	dmv_word0, dmv_word1, dmv_word2;
54320Sstevel@tonic-gate 	idn_domain_t	*dp = &idn_domain[domid];
54330Sstevel@tonic-gate 	extern kmutex_t	xc_sys_mutex;
54340Sstevel@tonic-gate 	extern int	xc_spl_enter[];
54350Sstevel@tonic-gate 	procname_t	proc = "idnxdc";
54360Sstevel@tonic-gate 
54370Sstevel@tonic-gate 
54380Sstevel@tonic-gate 	if (idn_snoop) {
54390Sstevel@tonic-gate 		int	bd;
54400Sstevel@tonic-gate 		STRING(str);
54410Sstevel@tonic-gate 		STRING(mstr);
54420Sstevel@tonic-gate 		STRING(astr);
54430Sstevel@tonic-gate 
54440Sstevel@tonic-gate 		INUM2STR(mtp->mt_mtype, mstr);
54450Sstevel@tonic-gate 		if ((mtp->mt_mtype & IDNP_MSGTYPE_MASK) == 0) {
54460Sstevel@tonic-gate 			INUM2STR(arg1, astr);
5447*11311SSurya.Prakki@Sun.COM 			(void) sprintf(str, "%s/%s", mstr, astr);
54480Sstevel@tonic-gate 		} else {
5449*11311SSurya.Prakki@Sun.COM 			(void) strcpy(str, mstr);
54500Sstevel@tonic-gate 		}
54510Sstevel@tonic-gate 		if (dp->dcpu == IDN_NIL_DCPU)
54520Sstevel@tonic-gate 			bd = -1;
54530Sstevel@tonic-gate 		else
54540Sstevel@tonic-gate 			bd = CPUID_TO_BOARDID(dp->dcpu);
54550Sstevel@tonic-gate 		SNOOP_IDN(0, str, bd, arg1, arg2, arg3, arg4);
54560Sstevel@tonic-gate 	}
54570Sstevel@tonic-gate 
54580Sstevel@tonic-gate 	/*
54590Sstevel@tonic-gate 	 * For NEGO messages we send the remote domain the cookie we
54600Sstevel@tonic-gate 	 * expect it to use in subsequent messages that it sends
54610Sstevel@tonic-gate 	 * to us (dcookie_recv).
54620Sstevel@tonic-gate 	 * For other messages, we must use the cookie that the
54630Sstevel@tonic-gate 	 * remote domain assigned to us for sending (dcookie_send).
54640Sstevel@tonic-gate 	 */
54650Sstevel@tonic-gate 	if ((mtp->mt_mtype & IDNP_MSGTYPE_MASK) == IDNP_NEGO)
54660Sstevel@tonic-gate 		cookie = IDN_MAKE_COOKIE(dp->dcookie_recv, mtp->mt_cookie);
54670Sstevel@tonic-gate 	else
54680Sstevel@tonic-gate 		cookie = IDN_MAKE_COOKIE(dp->dcookie_send, mtp->mt_cookie);
54690Sstevel@tonic-gate 
54700Sstevel@tonic-gate 	pdata = IDN_MAKE_PDATA(mtp->mt_mtype, mtp->mt_atype, cookie);
54710Sstevel@tonic-gate 
54720Sstevel@tonic-gate 	dmv_word0 = DMV_MAKE_DMV(idn.intr.dmv_inum, pdata);
54730Sstevel@tonic-gate 	dmv_word1 = ((uint64_t)arg1 << 32) | (uint64_t)arg2;
54740Sstevel@tonic-gate 	dmv_word2 = ((uint64_t)arg3 << 32) | (uint64_t)arg4;
54750Sstevel@tonic-gate 
54760Sstevel@tonic-gate 	ASSERT((dp->dcpu != IDN_NIL_DCPU) ||
54777656SSherry.Moore@Sun.COM 	    (dp->dcpu_last != IDN_NIL_DCPU));
54780Sstevel@tonic-gate 
54790Sstevel@tonic-gate 	tcpuid = (dp->dcpu == IDN_NIL_DCPU) ?
54807656SSherry.Moore@Sun.COM 	    dp->dcpu_last : dp->dcpu;
54810Sstevel@tonic-gate 
54820Sstevel@tonic-gate 	if (tcpuid == IDN_NIL_DCPU) {
54830Sstevel@tonic-gate 		PR_PROTO("%s:%d: cpu/cpu_last == NIL_DCPU\n",
54847656SSherry.Moore@Sun.COM 		    proc, domid);
54850Sstevel@tonic-gate 		return (-1);
54860Sstevel@tonic-gate 	}
54870Sstevel@tonic-gate 
54880Sstevel@tonic-gate 	mutex_enter(&xc_sys_mutex);
54890Sstevel@tonic-gate 	cpuid = (int)CPU->cpu_id;
54900Sstevel@tonic-gate 	xc_spl_enter[cpuid] = 1;
54910Sstevel@tonic-gate 
54920Sstevel@tonic-gate 	idnxf_init_mondo(dmv_word0, dmv_word1, dmv_word2);
54930Sstevel@tonic-gate 
54940Sstevel@tonic-gate 	rv = idnxf_send_mondo(STARFIRE_UPAID2HWMID(tcpuid));
54950Sstevel@tonic-gate 
54960Sstevel@tonic-gate 	xc_spl_enter[cpuid] = 0;
54970Sstevel@tonic-gate 	mutex_exit(&xc_sys_mutex);
54980Sstevel@tonic-gate 
54990Sstevel@tonic-gate 	return (rv);
55000Sstevel@tonic-gate }
55010Sstevel@tonic-gate 
55020Sstevel@tonic-gate void
55030Sstevel@tonic-gate idnxdc_broadcast(domainset_t domset, idn_msgtype_t *mtp,
55040Sstevel@tonic-gate 		uint_t arg1, uint_t arg2,
55050Sstevel@tonic-gate 		uint_t arg3, uint_t arg4)
55060Sstevel@tonic-gate {
55070Sstevel@tonic-gate 	int	d;
55080Sstevel@tonic-gate 
55090Sstevel@tonic-gate 	for (d = 0; d < MAX_DOMAINS; d++) {
55100Sstevel@tonic-gate 		idn_domain_t	*dp;
55110Sstevel@tonic-gate 
55120Sstevel@tonic-gate 		if (!DOMAIN_IN_SET(domset, d))
55130Sstevel@tonic-gate 			continue;
55140Sstevel@tonic-gate 
55150Sstevel@tonic-gate 		dp = &idn_domain[d];
55160Sstevel@tonic-gate 		if (dp->dcpu == IDN_NIL_DCPU)
55170Sstevel@tonic-gate 			continue;
55180Sstevel@tonic-gate 
55190Sstevel@tonic-gate 		(void) IDNXDC(d, mtp, arg1, arg2, arg3, arg4);
55200Sstevel@tonic-gate 	}
55210Sstevel@tonic-gate }
55220Sstevel@tonic-gate 
55230Sstevel@tonic-gate #define	PROM_SMRSIZE	0x1
55240Sstevel@tonic-gate #define	PROM_SMRADDR	0x2
55250Sstevel@tonic-gate #define	PROM_SMRPROPS	(PROM_SMRSIZE | PROM_SMRADDR)
55260Sstevel@tonic-gate /*
55270Sstevel@tonic-gate  * Locate the idn-smr-size property to determine the size of the SMR
55280Sstevel@tonic-gate  * region for the SSI.  Value inherently enables/disables SSI capability.
55290Sstevel@tonic-gate  */
55300Sstevel@tonic-gate static int
55310Sstevel@tonic-gate idn_prom_getsmr(uint_t *smrsz, uint64_t *paddrp, uint64_t *sizep)
55320Sstevel@tonic-gate {
5533789Sahrens 	pnode_t		nodeid;
55340Sstevel@tonic-gate 	int		found = 0;
55350Sstevel@tonic-gate 	int		len;
55360Sstevel@tonic-gate 	uint_t		smrsize = 0;
55370Sstevel@tonic-gate 	uint64_t	obpaddr, obpsize;
55380Sstevel@tonic-gate 	struct smraddr {
55390Sstevel@tonic-gate 		uint32_t	hi_addr;
55400Sstevel@tonic-gate 		uint32_t	lo_addr;
55410Sstevel@tonic-gate 		uint32_t	hi_size;
55420Sstevel@tonic-gate 		uint32_t	lo_size;
55430Sstevel@tonic-gate 	} smraddr;
55440Sstevel@tonic-gate 	procname_t	proc = "idn_prom_getsmr";
55450Sstevel@tonic-gate 
55460Sstevel@tonic-gate 	bzero(&smraddr, sizeof (smraddr));
55470Sstevel@tonic-gate 	/*
55480Sstevel@tonic-gate 	 * idn-smr-size is a property of the "memory" node and
55490Sstevel@tonic-gate 	 * is defined in megabytes.
55500Sstevel@tonic-gate 	 */
55510Sstevel@tonic-gate 	nodeid = prom_finddevice("/memory");
55520Sstevel@tonic-gate 
55530Sstevel@tonic-gate 	if (nodeid != OBP_NONODE) {
55540Sstevel@tonic-gate 		len = prom_getproplen(nodeid, IDN_PROP_SMRSIZE);
55550Sstevel@tonic-gate 		if (len == sizeof (smrsize)) {
55560Sstevel@tonic-gate 			(void) prom_getprop(nodeid, IDN_PROP_SMRSIZE,
55577656SSherry.Moore@Sun.COM 			    (caddr_t)&smrsize);
55580Sstevel@tonic-gate 			found |= PROM_SMRSIZE;
55590Sstevel@tonic-gate 		}
55600Sstevel@tonic-gate 		len = prom_getproplen(nodeid, IDN_PROP_SMRADDR);
55610Sstevel@tonic-gate 		if (len  == sizeof (smraddr)) {
55620Sstevel@tonic-gate 			(void) prom_getprop(nodeid, IDN_PROP_SMRADDR,
55637656SSherry.Moore@Sun.COM 			    (caddr_t)&smraddr);
55640Sstevel@tonic-gate 			found |= PROM_SMRADDR;
55650Sstevel@tonic-gate 		}
55660Sstevel@tonic-gate 	}
55670Sstevel@tonic-gate 
55680Sstevel@tonic-gate 	if (found != PROM_SMRPROPS) {
55690Sstevel@tonic-gate 		if ((found & PROM_SMRSIZE) == 0)
55700Sstevel@tonic-gate 			cmn_err(CE_WARN,
55717656SSherry.Moore@Sun.COM 			    "IDN: 136: \"%s\" property not found, "
55727656SSherry.Moore@Sun.COM 			    "disabling IDN",
55737656SSherry.Moore@Sun.COM 			    IDN_PROP_SMRSIZE);
55740Sstevel@tonic-gate 		if (smrsize && ((found & PROM_SMRADDR) == 0))
55750Sstevel@tonic-gate 			cmn_err(CE_WARN,
55767656SSherry.Moore@Sun.COM 			    "IDN: 136: \"%s\" property not found, "
55777656SSherry.Moore@Sun.COM 			    "disabling IDN",
55787656SSherry.Moore@Sun.COM 			    IDN_PROP_SMRADDR);
55790Sstevel@tonic-gate 		return (-1);
55800Sstevel@tonic-gate 	}
55810Sstevel@tonic-gate 
55820Sstevel@tonic-gate 	if (smrsize == 0) {
55830Sstevel@tonic-gate 		PR_SMR("%s: IDN DISABLED (idn_smr_size = 0)\n", proc);
55840Sstevel@tonic-gate 		cmn_err(CE_NOTE, "!IDN: 137: SMR size is 0, disabling IDN");
55850Sstevel@tonic-gate 
55860Sstevel@tonic-gate 	} else if (smrsize > IDN_SMR_MAXSIZE) {
55870Sstevel@tonic-gate 		PR_SMR("%s: IDN DISABLED (idn_smr_size too big %d > %d MB)\n",
55887656SSherry.Moore@Sun.COM 		    proc, smrsize, IDN_SMR_MAXSIZE);
55890Sstevel@tonic-gate 		cmn_err(CE_WARN,
55907656SSherry.Moore@Sun.COM 		    "!IDN: 138: SMR size (%dMB) is too big (max = %dMB), "
55917656SSherry.Moore@Sun.COM 		    "disabling IDN",
55927656SSherry.Moore@Sun.COM 		    smrsize, IDN_SMR_MAXSIZE);
55930Sstevel@tonic-gate 		smrsize = 0;
55940Sstevel@tonic-gate 	} else {
55950Sstevel@tonic-gate 		*smrsz = smrsize;
55960Sstevel@tonic-gate 		found &= ~PROM_SMRSIZE;
55970Sstevel@tonic-gate 	}
55980Sstevel@tonic-gate 
55990Sstevel@tonic-gate 	obpaddr = ((uint64_t)smraddr.hi_addr << 32) |
56007656SSherry.Moore@Sun.COM 	    (uint64_t)smraddr.lo_addr;
56010Sstevel@tonic-gate 	obpsize = ((uint64_t)smraddr.hi_size << 32) |
56027656SSherry.Moore@Sun.COM 	    (uint64_t)smraddr.lo_size;
56030Sstevel@tonic-gate 
56040Sstevel@tonic-gate 	if (obpsize == 0) {
56050Sstevel@tonic-gate 		if (smrsize > 0) {
56060Sstevel@tonic-gate 			cmn_err(CE_WARN, "!IDN: 139: OBP region for "
56077656SSherry.Moore@Sun.COM 			    "SMR is 0 length");
56080Sstevel@tonic-gate 		}
56090Sstevel@tonic-gate 	} else if (obpsize < (uint64_t)MB2B(smrsize)) {
56100Sstevel@tonic-gate 		cmn_err(CE_WARN,
56117656SSherry.Moore@Sun.COM 		    "!IDN: 140: OBP region (%ld B) smaller "
56127656SSherry.Moore@Sun.COM 		    "than requested size (%ld B)",
56137656SSherry.Moore@Sun.COM 		    obpsize, MB2B(smrsize));
56140Sstevel@tonic-gate 	} else if ((obpaddr & ((uint64_t)IDN_SMR_ALIGN - 1)) != 0) {
56150Sstevel@tonic-gate 		cmn_err(CE_WARN,
56167656SSherry.Moore@Sun.COM 		    "!IDN: 141: OBP region (0x%lx) not on (0x%x) "
56177656SSherry.Moore@Sun.COM 		    "boundary", obpaddr, IDN_SMR_ALIGN);
56180Sstevel@tonic-gate 	} else {
56190Sstevel@tonic-gate 		*sizep = obpsize;
56200Sstevel@tonic-gate 		*paddrp = obpaddr;
56210Sstevel@tonic-gate 		found &= ~PROM_SMRADDR;
56220Sstevel@tonic-gate 	}
56230Sstevel@tonic-gate 
56240Sstevel@tonic-gate 	return (found ? -1 : 0);
56250Sstevel@tonic-gate }
56260Sstevel@tonic-gate 
56270Sstevel@tonic-gate void
56280Sstevel@tonic-gate idn_init_autolink()
56290Sstevel@tonic-gate {
56300Sstevel@tonic-gate 	idnsb_event_t	*sbp;
56310Sstevel@tonic-gate 	procname_t	proc = "idn_init_autolink";
56320Sstevel@tonic-gate 
56330Sstevel@tonic-gate 	mutex_enter(&idn.idnsb_mutex);
56340Sstevel@tonic-gate 	if ((sbp = idn.idnsb_eventp) == NULL) {
56350Sstevel@tonic-gate 		PR_PROTO("%s: IDN private sigb (event) area is NULL\n", proc);
56360Sstevel@tonic-gate 		mutex_exit(&idn.idnsb_mutex);
56370Sstevel@tonic-gate 		return;
56380Sstevel@tonic-gate 	}
56390Sstevel@tonic-gate 
56400Sstevel@tonic-gate 	PR_PROTO("%s: marking domain IDN ready.\n", proc);
56410Sstevel@tonic-gate 
56420Sstevel@tonic-gate 	bzero(sbp, sizeof (*sbp));
56430Sstevel@tonic-gate 
56440Sstevel@tonic-gate 	sbp->idn_version = (uchar_t)idn.version;
56450Sstevel@tonic-gate 	SSIEVENT_SET(sbp, SSIEVENT_BOOT, 0);
56460Sstevel@tonic-gate 	(void) strncpy(sbp->idn_cookie_str, SSIEVENT_COOKIE,
56477656SSherry.Moore@Sun.COM 	    SSIEVENT_COOKIE_LEN);
56480Sstevel@tonic-gate 	mutex_exit(&idn.idnsb_mutex);
56490Sstevel@tonic-gate }
56500Sstevel@tonic-gate 
56510Sstevel@tonic-gate void
56520Sstevel@tonic-gate idn_deinit_autolink()
56530Sstevel@tonic-gate {
56540Sstevel@tonic-gate 	idnsb_event_t	*sbp;
56550Sstevel@tonic-gate 	procname_t	proc = "idn_deinit_autolink";
56560Sstevel@tonic-gate 
56570Sstevel@tonic-gate 	mutex_enter(&idn.idnsb_mutex);
56580Sstevel@tonic-gate 	if ((sbp = idn.idnsb_eventp) == NULL) {
56590Sstevel@tonic-gate 		PR_PROTO("%s: IDN private sigb (event) area is NULL\n", proc);
56600Sstevel@tonic-gate 		mutex_exit(&idn.idnsb_mutex);
56610Sstevel@tonic-gate 		return;
56620Sstevel@tonic-gate 	}
56630Sstevel@tonic-gate 
56640Sstevel@tonic-gate 	PR_PROTO("%s: marking domain IDN unavailable.\n", proc);
56650Sstevel@tonic-gate 
56660Sstevel@tonic-gate 	sbp->idn_version = (uchar_t)idn.version;
56670Sstevel@tonic-gate 	SSIEVENT_CLEAR(sbp, SSIEVENT_BOOT, 0);
56680Sstevel@tonic-gate 	(void) strncpy(sbp->idn_cookie_str, SSIEVENT_COOKIE,
56697656SSherry.Moore@Sun.COM 	    SSIEVENT_COOKIE_LEN);
56700Sstevel@tonic-gate 	mutex_exit(&idn.idnsb_mutex);
56710Sstevel@tonic-gate }
56720Sstevel@tonic-gate 
56730Sstevel@tonic-gate void
56740Sstevel@tonic-gate _make64cpumask(cpuset_t *csetp, uint_t upper, uint_t lower)
56750Sstevel@tonic-gate {
56760Sstevel@tonic-gate 	int	c;
56770Sstevel@tonic-gate 
56780Sstevel@tonic-gate 	CPUSET_ZERO(*csetp);
56790Sstevel@tonic-gate 
56800Sstevel@tonic-gate 	for (c = 0; c < 32; c++) {
56810Sstevel@tonic-gate 		if (lower & (1 << c)) {
56820Sstevel@tonic-gate 			CPUSET_ADD(*csetp, c);
56830Sstevel@tonic-gate 		}
56840Sstevel@tonic-gate 		if (upper & (1 << (c + 32))) {
56850Sstevel@tonic-gate 			CPUSET_ADD(*csetp, c + 32);
56860Sstevel@tonic-gate 		}
56870Sstevel@tonic-gate 	}
56880Sstevel@tonic-gate }
56890Sstevel@tonic-gate 
56900Sstevel@tonic-gate uint_t
56910Sstevel@tonic-gate _lower32cpumask(cpuset_t cset)
56920Sstevel@tonic-gate {
56930Sstevel@tonic-gate 	int	c;
56940Sstevel@tonic-gate 	uint_t	set = 0;
56950Sstevel@tonic-gate 
56960Sstevel@tonic-gate 	for (c = 0; c < 32; c++)
56970Sstevel@tonic-gate 		if (CPU_IN_SET(cset, c))
56980Sstevel@tonic-gate 			set |= 1 << c;
56990Sstevel@tonic-gate 
57000Sstevel@tonic-gate 	return (set);
57010Sstevel@tonic-gate }
57020Sstevel@tonic-gate 
57030Sstevel@tonic-gate uint_t
57040Sstevel@tonic-gate _upper32cpumask(cpuset_t cset)
57050Sstevel@tonic-gate {
57060Sstevel@tonic-gate 	int	c;
57070Sstevel@tonic-gate 	uint_t	set = 0;
57080Sstevel@tonic-gate 
57090Sstevel@tonic-gate 	for (c = 32; c < NCPU; c++)
57100Sstevel@tonic-gate 		if (CPU_IN_SET(cset, c))
57110Sstevel@tonic-gate 			set |= 1 << (c - 32);
57120Sstevel@tonic-gate 
57130Sstevel@tonic-gate 	return (set);
57140Sstevel@tonic-gate }
57150Sstevel@tonic-gate 
57160Sstevel@tonic-gate #ifdef DEBUG
57170Sstevel@tonic-gate int
57180Sstevel@tonic-gate debug_idnxdc(char *f, int domid, idn_msgtype_t *mtp,
57190Sstevel@tonic-gate 		uint_t a1, uint_t a2, uint_t a3, uint_t a4)
57200Sstevel@tonic-gate {
57210Sstevel@tonic-gate 	idn_domain_t	*dp = &idn_domain[domid];
57220Sstevel@tonic-gate 	int		rv, cpuid, bd;
57230Sstevel@tonic-gate 	static int	xx = 0;
57240Sstevel@tonic-gate 	STRING(str);
57250Sstevel@tonic-gate 	STRING(mstr);
57260Sstevel@tonic-gate 	STRING(astr);
57270Sstevel@tonic-gate 
57280Sstevel@tonic-gate 	xx++;
57290Sstevel@tonic-gate 	INUM2STR(mtp->mt_mtype, mstr);
57300Sstevel@tonic-gate 	if ((mtp->mt_mtype & IDNP_MSGTYPE_MASK) == 0) {
57310Sstevel@tonic-gate 		INUM2STR(a1, astr);
5732*11311SSurya.Prakki@Sun.COM 		(void) sprintf(str, "%s/%s", mstr, astr);
57330Sstevel@tonic-gate 	} else {
5734*11311SSurya.Prakki@Sun.COM 		(void) strcpy(str, mstr);
57350Sstevel@tonic-gate 	}
57360Sstevel@tonic-gate 
57370Sstevel@tonic-gate 	if ((cpuid = dp->dcpu) == IDN_NIL_DCPU)
57380Sstevel@tonic-gate 		bd = -1;
57390Sstevel@tonic-gate 	else
57400Sstevel@tonic-gate 		bd = CPUID_TO_BOARDID(cpuid);
57410Sstevel@tonic-gate 
57420Sstevel@tonic-gate 	SNOOP_IDN(0, str, bd, a1, a2, a3, a4);
57430Sstevel@tonic-gate 
57440Sstevel@tonic-gate 	PR_XDC("%s:%d:%d SENT: scpu = %d, msg = 0x%x(%s)\n",
57457656SSherry.Moore@Sun.COM 	    f, domid, xx, cpuid, mtp->mt_mtype, str);
57460Sstevel@tonic-gate 	PR_XDC("%s:%d:%d S-DATA: a1 = 0x%x, a2 = 0x%x\n",
57477656SSherry.Moore@Sun.COM 	    f, domid, xx, a1, a2);
57480Sstevel@tonic-gate 	PR_XDC("%s:%d:%d S-DATA: a3 = 0x%x, a4 = 0x%x\n",
57497656SSherry.Moore@Sun.COM 	    f, domid, xx, a3, a4);
57500Sstevel@tonic-gate 
57510Sstevel@tonic-gate 	rv = idnxdc(domid, mtp, a1, a2, a3, a4);
57520Sstevel@tonic-gate 	if (rv != 0) {
57530Sstevel@tonic-gate 		PR_XDC("%s:%d:%d: WARNING: idnxdc(cpu %d) FAILED\n",
57547656SSherry.Moore@Sun.COM 		    f, domid, xx, cpuid);
57550Sstevel@tonic-gate 	}
57560Sstevel@tonic-gate 
57570Sstevel@tonic-gate 	return (rv);
57580Sstevel@tonic-gate }
57590Sstevel@tonic-gate 
57600Sstevel@tonic-gate caddr_t
57610Sstevel@tonic-gate _idn_getstruct(char *structname, int size)
57620Sstevel@tonic-gate {
57630Sstevel@tonic-gate 	caddr_t		ptr;
57640Sstevel@tonic-gate 	procname_t	proc = "GETSTRUCT";
57650Sstevel@tonic-gate 
57660Sstevel@tonic-gate 	ptr = kmem_zalloc(size, KM_SLEEP);
57670Sstevel@tonic-gate 
5768931Smathue 	PR_ALLOC("%s: ptr 0x%p, struct(%s), size = %d\n",
5769*11311SSurya.Prakki@Sun.COM 	    proc, (void *)ptr, structname, size);
57700Sstevel@tonic-gate 
57710Sstevel@tonic-gate 	return (ptr);
57720Sstevel@tonic-gate }
57730Sstevel@tonic-gate 
57740Sstevel@tonic-gate void
57750Sstevel@tonic-gate _idn_freestruct(caddr_t ptr, char *structname, int size)
57760Sstevel@tonic-gate {
57770Sstevel@tonic-gate 	procname_t	proc = "FREESTRUCT";
57780Sstevel@tonic-gate 
5779931Smathue 	PR_ALLOC("%s: ptr 0x%p, struct(%s), size = %d\n",
5780*11311SSurya.Prakki@Sun.COM 	    proc, (void *)ptr, structname, size);
57810Sstevel@tonic-gate 
57820Sstevel@tonic-gate 	ASSERT(ptr != NULL);
57830Sstevel@tonic-gate 	kmem_free(ptr, size);
57840Sstevel@tonic-gate }
57850Sstevel@tonic-gate #endif /* DEBUG */
5786