xref: /titanic_51/usr/src/uts/sun4u/starfire/sys/idn.h (revision 42487ff1899d230ad6c2d55cf9573489ca5eb770)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  *
26  * Inter-Domain Network
27  */
28 
29 #ifndef	_SYS_IDN_H
30 #define	_SYS_IDN_H
31 
32 #pragma ident	"%Z%%M%	%I%	%E% SMI"
33 
34 #ifndef _ASM
35 
36 #ifdef _KERNEL
37 
38 #include <sys/note.h>
39 
40 #include <sys/cmn_err.h>
41 #include <sys/dditypes.h>
42 #include <sys/stream.h>
43 #include <sys/machsystm.h>
44 #include <sys/ethernet.h>
45 #include <sys/dlpi.h>
46 #include <sys/time.h>
47 #include <sys/kmem.h>
48 #include <sys/atomic.h>
49 #include <sys/cpuvar.h>
50 
51 #include <sys/idn_sigb.h>
52 #include <sys/idn_smr.h>
53 #endif /* _KERNEL */
54 
55 #ifdef	__cplusplus
56 extern "C" {
57 #endif
58 
59 typedef const char * const	procname_t;
60 
61 #define	MB2B(m)		((size_t)(m) << 20)	/* MBytes to Bytes */
62 #define	B2MB(b)		((uint_t)((b) >> 20))	/* Bytes to MBytes */
63 
64 #ifdef _KERNEL
65 
66 /*
67  * IDN_PROP_SMRSIZE	- User specified size in MBytes.
68  * IDN_PROP_SMRADDR	- OBP's internal physical address of the region.
69  *
70  *	OBP properties of "memory" node that define the SMR space.
71  */
72 #define	IDN_PROP_SMRSIZE	"idn-smr-size"
73 #define	IDN_PROP_SMRADDR	"idn-smr-addr"
74 
75 /*
76  * IDN_AWOLMSG_INTERVAL	(driver.conf)
77  *
78  *	Number of seconds between AWOL messages on a per-domain basis.
79  *	The purpose is to throttle the frequency at which these
80  *	messages appear.
81  *
82  * IDN_MSGWAIT_NEGO	(driver.conf)
83  * IDN_MSGWAIT_CFG
84  * IDN_MSGWAIT_CON
85  * IDN_MSGWAIT_FIN
86  * IDN_MSGWAIT_CMD
87  * IDN_MSGWAIT_DATA
88  *
89  *	Number of seconds to wait for response to respective
90  *	message type.
91  *
92  * IDN_RETRYFREQ_NEGO	(driver.conf)
93  * IDN_RETRYFREQ_CON
94  * IDN_RETRYFREQ_FIN
95  *
96  *	Number of seconds to wait between retries of the respective
97  *	message type.
98  *
99  * IDN_SMR_ALIGN	(not tunable)
100  *
101  *	The hardware registers that describe the SMR are based on a 64K
102  *	aligned physical address.
103  *
104  * IDN_SMR_SIZE		(OBP [only])
105  *
106  *	Total size of the SMR (Shared Memory Region) in bytes.
107  *
108  * IDN_NWR_SIZE		(driver.conf)
109  *
110  *	Total size of the NWR (NetWork Region) portion of the SMR which
111  *	is actually used to support network activity.  The NWR is managed
112  *	as simply a pool of I/O buffers which are distributed by the
113  *	Master domain to the Slaves for the purpose of communicating
114  *	between each other.  If not set then the entire SMR is used
115  *	as the NWR.
116  *	Req: IDN_NWR_SIZE <= IDN_SMR_SIZE
117  *
118  * IDN_SMR_BUFSIZE	(driver.conf)
119  *
120  *	Size of individual SMR buffers.  The SMR is divided into chunks
121  *	of IDN_SMR_BUFSIZE bytes.  The IDN_MTU is based on this size
122  *	and thus the IDN_SMR_BUFSIZE should be chosen based on performance.
123  *
124  * IDN_DATA_SIZE	(NOT tunable)
125  *
126  *	Portion of IDN_SMR_BUFSIZE that can contain raw non-IDN dependent
127  *	data.  We subtract IDN_ALIGNSIZE bytes to allow for fast bcopy
128  *	alignment.
129  *	Req: IDN_DATA_SIZE <=
130  *		(IDN_SMR_BUFSIZE - sizeof (smr_pkthdr_t) - IDN_ALIGNSIZE)
131  *
132  * IDN_MTU		(indirectly tunable via IDN_SMR_BUFSIZE)
133  *
134  * 	This size represents the portion of an SMR I/O buffers that can
135  *	contain (ethernet headerless) data.
136  *	Req: IDN_MTU <= IDN_DATA_SIZE - sizeof (ether_header)
137  *
138  * IDN_WINDOW_MAX	(driver.conf)
139  *
140  *	Maximum number of outstanding packets that are allowed per
141  *	domain.  If this value is exceeded for a particular domain
142  *	no further I/Os will be transmitted to that domain until it
143  *	has acknowledged enough of the previous transmission to bring
144  *	down its outstanding I/O count (idn_domain.dio) below this
145  *	value.  In addition, if this value is exceeded then a Timer
146  *	is scheduled to check for any response from the remote domain.
147  *
148  * IDN_WINDOW_INCR	(driver.conf)
149  *
150  *	As more channels/nets are activated on a particular domain
151  *	the greater the number of possible outstanding data packets
152  *	that can be outstanding to a given domain.  Since this natural
153  *	occurence can result in the outstanding-I/O count to a given
154  *	domain to increase we run the risk of dropping into the
155  *	IDN_WINDOW_MAX region even though the receiving domain
156  *	may be fine with handling the load.  In order to compensate
157  *	for this increased activity and to not incur unjustified
158  *	slips into the IDN_WINDOW_MAX region, the IDN_WINDOW_MAX
159  *	value is adjusted by IDN_WINDOW_INCR for each channel/net
160  *	that is activated for a given domain.
161  *
162  * IDN_WINDOW_EMAX	(not tunable)
163  *
164  *	The effective value of IDN_WINDOW_MAX once it has
165  *	been adjusted by IDN_WINDOW_INCR.
166  *
167  * IDN_RECLAIM_MIN	(driver.conf)
168  *
169  *	Minimum number of outstanding packets that our allowed
170  *	before subsequent sends will attempt to reclaim some number
171  *	of outstanding data packets.
172  *
173  * IDN_RECLAIM_MAX	(driver.conf)
174  *	This value represents the maximum number of outstanding
175  *	packets we will try to reclaim during a send once we've
176  *	passed the IDN_RECLAIM_MIN boundary.
177  *
178  * IDN_MODUNLOADABLE	(ndd)
179  *
180  *	By default the IDN driver is unloadable.  Setting this
181  *	variable will allow the IDN driver to be unloaded provided
182  *	it's not in use.
183  *
184  * IDN_LOWAT/IDN_HIWAT	(driver.conf)
185  *
186  *	Low/High water marks for the STREAM interface to IDN.
187  *
188  * IDN_MBOX_PER_NET	(driver.conf)
189  *
190  *	Number of mailbox entries that are allocated per channel/net.
191  *	This value effectively represents the amount of outstanding
192  *	activity that can reside at a domain.  Increasing this value
193  *	allows more packets to be in transit to a domain, however
194  *	at some point there are diminishing returns since the receiver
195  *	can only consume packets so fast.
196  *
197  * IDN_MAX_NETS		(driver.conf)
198  *
199  *	Maximum number of network interfaces (channels) that IDN
200  *	is currently configured to allow.  The absolute max is
201  *	IDN_MAXMAX_NETS.  We don't automatically default IDN_MAX_NETS
202  *	to IDN_MAXMAX_NETS because it would mean wasted space in
203  *	the mailbox region having to reserve mailboxes that will
204  *	very likely go unused.  The smaller this value the fewer
205  *	the number of mailboxes in the SMR and thus the greater the
206  *	number of possible I/O buffers available.
207  *	Req: IDN_MAX_NETS <= IDN_MAXMAX_NETS
208  *
209  * IDN_CHECKSUM		(driver.conf)
210  *
211  *	If enabled, IDN validates the smr_pkthdr_t of incoming packets
212  *	via a checksum, and calculates the checksum for outgoing packets.
213  *	Only the first 3 fields of smr_pkthdr_t are checksummed and
214  *	must be set to their expected values prior to calculating the
215  *	checksum.  Turned OFF by default when compiled DEBUG.
216  *
217  * IDN_SMR_MAXSIZE	(not tunable)
218  *
219  *	The absolute maximum size of the SMR region that we'll allow.
220  *	Note that the virtual address space comes out kernelmap.
221  */
222 #define	IDN_AWOLMSG_INTERVAL	60		/* seconds */
223 #define	IDN_MSGWAIT_NEGO	20		/* seconds */
224 #define	IDN_MSGWAIT_CFG		40
225 #define	IDN_MSGWAIT_CON		20
226 #define	IDN_MSGWAIT_FIN		40
227 #define	IDN_MSGWAIT_CMD		40
228 #define	IDN_MSGWAIT_DATA	30
229 #define	IDN_RETRYFREQ_NEGO	2
230 #define	IDN_RETRYFREQ_CON	2
231 #define	IDN_RETRYFREQ_FIN	3
232 
233 #define	IDN_SMR_BUFSIZE_MIN	512
234 #define	IDN_SMR_BUFSIZE_MAX	(512*1024)
235 #define	IDN_SMR_BUFSIZE_DEF	(16*1024)
236 
237 #define	IDN_SMR_SHIFT		(16)
238 #define	IDN_SMR_ALIGN		(1 << IDN_SMR_SHIFT)	/* 64K */
239 #define	IDN_SMR_SIZE		idn_smr_size
240 #define	IDN_NWR_SIZE		idn_nwr_size
241 #define	IDN_SMR_BUFSIZE		idn_smr_bufsize
242 #define	IDN_DATA_SIZE		(IDN_SMR_BUFSIZE \
243 				    - sizeof (smr_pkthdr_t) \
244 				    - IDN_ALIGNSIZE)
245 #define	IDN_MTU			(IDN_DATA_SIZE - sizeof (struct ether_header))
246 #define	IDN_WINDOW_MAX		idn_window_max
247 #define	IDN_WINDOW_INCR		idn_window_incr
248 #define	IDN_WINDOW_EMAX		idn_window_emax
249 #define	IDN_RECLAIM_MIN		idn_reclaim_min
250 #define	IDN_RECLAIM_MAX		idn_reclaim_max
251 #define	IDN_MODUNLOADABLE	idn_modunloadable
252 #define	IDN_LOWAT		idn_lowat
253 #define	IDN_HIWAT		idn_hiwat
254 #define	IDN_MBOX_PER_NET	idn_mbox_per_net
255 #define	IDN_MAX_NETS		idn_max_nets
256 #define	IDN_CHECKSUM		idn_checksum
257 #define	IDN_SMR_MAXSIZE		96
258 #define	_IDN_SMR_SIZE		32			/* 32M */
259 #define	_IDN_NWR_SIZE		_IDN_SMR_SIZE		/* 32M */
260 #define	_IDN_SMR_BUFSIZE	(16 * 1024)		/* 16K */
261 
262 
263 #define	IDN_TUNEVAR_NAME(v)	(*(char **)((ulong_t)&(v)+(sizeof (ulong_t))))
264 #define	IDN_TUNEVAR_VALUE(v)	(v)
265 
266 /*
267  * History structure to support problem analysis.
268  */
269 #define	IDN_HISTORY_NUM		1024
270 #define	IDN_HISTORY_LOG(op, d0, d1, d2) \
271 	if (idn_history) { \
272 		mutex_enter(&idnhlog.h_mutex); \
273 		idnhlog.h_log[idnhlog.h_index].e_time = TIMESTAMP(); \
274 		idnhlog.h_log[idnhlog.h_index].e_op = (ushort_t)(op); \
275 		idnhlog.h_log[idnhlog.h_index].e_data[0] = (ushort_t)(d0); \
276 		idnhlog.h_log[idnhlog.h_index].e_data[1] = (ushort_t)(d1); \
277 		idnhlog.h_log[idnhlog.h_index].e_data[2] = (ushort_t)(d2); \
278 		idnhlog.h_index++; \
279 		idnhlog.h_index &= (IDN_HISTORY_NUM - 1); \
280 		mutex_exit(&idnhlog.h_mutex); \
281 	}
282 
283 #define	IDNH_GSTATE	0x0001	/* d0=gstate, d1=, d2= */
284 #define	IDNH_DSTATE	0x0002	/* d0=domid, d1=dstate, d2=cpuid */
285 #define	IDNH_AWOL	0x0003	/* d0=domid, d1=dstate, d2=cpuid */
286 #define	IDNH_MASTERID	0x0004	/* d0=masterid, d1=oldid, d2= */
287 #define	IDNH_NEGO	0x0005	/* d0=domid, d1=ds_trans_on, d2=ds_connected */
288 #define	IDNH_FIN	0x0006	/* d0=domid, d1=finstate, d2= */
289 #define	IDNH_RELINK	0x0007	/* d0=domid, d1=dstate, d2=ds_relink */
290 
291 struct idn_h_entry {
292 	hrtime_t	e_time;
293 	ushort_t	e_op;
294 	ushort_t	e_data[3];
295 };
296 
297 struct idn_history {
298 	kmutex_t		h_mutex;
299 	int			h_index;
300 	struct idn_h_entry	h_log[IDN_HISTORY_NUM];
301 };
302 #endif /* _KERNEL */
303 
304 /*
305  * IDN_SIGBPIL - Interrupt level at which IDN driver
306  *		 wakes up idn_sigbhandler_thread
307  */
308 #define	IDN_SIGBPIL	PIL_3
309 
310 /*
311  * Definition of sigbintr.sb_busy values which
312  * represents state of idn_sigbhandler.
313  */
314 #define	IDNSIGB_NOTREADY	((uchar_t)0)
315 #define	IDNSIGB_INACTIVE	((uchar_t)1)
316 #define	IDNSIGB_STARTED		((uchar_t)2)
317 #define	IDNSIGB_ACTIVE		((uchar_t)3)
318 #define	IDNSIGB_DIE		((uchar_t)4)
319 
320 /*
321  * Some Xfire based macros that assume 4 cpus per board.
322  */
323 #define	CPUID_TO_BOARDID(c)	((c) >> 2)
324 #define	MAX_CPU_PER_BRD		4
325 #define	CPUSET_TO_BOARDSET(cset, bset) \
326 	{ \
327 		register int	c, b; \
328 		(bset) = 0; \
329 		for (b = 0; b < MAX_BOARDS; b++) \
330 			for (c = 0; c < MAX_CPU_PER_BRD; c++) \
331 				if (CPU_IN_SET((cset), \
332 						(b * MAX_CPU_PER_BRD) + c)) \
333 					(bset) |= 1 << b; \
334 	}
335 
336 /*
337  * Macros to manipulate boardset and domainset masks.
338  */
339 typedef ushort_t boardset_t;	/* assumes max of 16 boards */
340 typedef ushort_t domainset_t;	/* assumes max of 16 domains */
341 
342 #define	BOARDSET(brd)		((boardset_t)(1 << (brd)))
343 #define	BOARDSET_ALL		((boardset_t)~0)
344 #define	BOARD_IN_SET(set, brd)	((set) & BOARDSET(brd))
345 #define	BOARDSET_ADD(set, brd)	((set) |= BOARDSET(brd))
346 #define	BOARDSET_DEL(set, brd)	((set) &= ~BOARDSET(brd))
347 #define	DOMAINSET(d)		((domainset_t)1 << (d))
348 #define	DOMAINSET_ALL		((domainset_t)~0)
349 #define	DOMAIN_IN_SET(s, d)	((s) & DOMAINSET(d))
350 #define	DOMAINSET_ADD(s, d)	((s) |= DOMAINSET(d))
351 #define	DOMAINSET_DEL(s, d)	((s) &= ~DOMAINSET(d))
352 
353 /*
354  * PFN_TO_SMADDR macro converts a PFN to a IDN_SMR_ALIGN'ed
355  * address suitable for the CIC bar/lar registers.
356  */
357 #if (IDN_SMR_SHIFT <= MMU_PAGESHIFT)
358 #define	PFN_TO_SMADDR(pfn)	((pfn) << (MMU_PAGESHIFT - IDN_SMR_SHIFT))
359 #else
360 #define	PFN_TO_SMADDR(pfn)	((pfn) >> (IDN_SMR_SHIFT - MMU_PAGESHIFT))
361 #endif
362 
363 /*
364  * Translate a physical address to a unique domain identifier.
365  * IMPORTANT - Assumes each board's memory is configured on a 8GB
366  *	       boundary. PA(8G) = PFN(1M).
367  */
368 #define	MEM8G_SHIFT			33	/* (1 << 33) == 8G */
369 #define	PADDR_TO_DOMAINID(paddr)	((int)((paddr) >> MEM8G_SHIFT) & 0xf)
370 
371 #define	VALID_NWROFFSET(off, align)	\
372 				(((uint_t)(off) >= 0) && \
373 				((size_t)(off) < MB2B(IDN_NWR_SIZE)) && \
374 				!((uint_t)(off) & ((align) - 1)))
375 #define	VALID_NWRADDR(addr, align) \
376 		(((caddr_t)(addr) >= idn.smr.vaddr) && \
377 		VALID_NWROFFSET(((caddr_t)(addr) - idn.smr.vaddr), (align)))
378 #define	VALID_DOMAINID(d)	(((d) >= 0) && ((d) < MAX_DOMAINS))
379 #define	VALID_UDOMAINID(d)	((d) < MAX_DOMAINS)
380 #define	VALID_CPUID(c)		(((c) >= 0) && ((c) < NCPU))
381 #define	VALID_CHANNEL(c)	(((c) >= 0) && ((c) < IDN_MAX_NETS))
382 #define	VALID_UCHANNEL(c)	((c) < IDN_MAX_NETS)
383 
384 /*
385  * The following are bit values of idn_debug, currently
386  * only useful if compiled with DEBUG.
387  */
388 #ifdef DEBUG
389 #define	STRING(sss)		char sss[20]
390 #define	INUM2STR(mm, ss)	inum2str((mm), (ss))
391 
392 #define	IDNDBG_XDC	0x00000001
393 #define	IDNDBG_XF	0x00000002
394 #define	IDNDBG_REGS	0x00000004
395 #define	IDNDBG_SMR	0x00000008
396 #define	IDNDBG_PROTO	0x00000010
397 #define	IDNDBG_STR	0x00000020
398 #define	IDNDBG_DRV	0x00000040
399 #define	IDNDBG_DATA	0x00000080
400 #define	IDNDBG_STATE	0x00000100
401 #define	IDNDBG_DLPI	0x00000200
402 #define	IDNDBG_KERN	0x00000400
403 #define	IDNDBG_ALLOC	0x00000800
404 #define	IDNDBG_REMAP	0x00001000
405 #define	IDNDBG_TIMER	0x00002000
406 #define	IDNDBG_CHAN	0x00004000
407 #define	IDNDBG_AWOL	0x00008000
408 #define	IDNDBG_SYNC	0x00010000
409 #define	_IDNDBG_UNUSED0	0x00020000
410 #define	IDNDBG_HITLIST	0x00040000
411 #define	IDNDBG_XMON	0x00080000
412 #define	IDNDBG_TEST	0x80000000
413 #define	IDNDBG_ALL	((uint_t)-1)
414 
415 #define	PR_ALL		if (idn_debug)	printf
416 #define	PR_XDC		if (idn_debug & IDNDBG_XDC)	printf
417 #define	PR_XF		if (idn_debug & IDNDBG_XF)	printf
418 #define	PR_REGS		if (idn_debug & IDNDBG_REGS)	printf
419 #define	PR_SMR		if (idn_debug & IDNDBG_SMR)	printf
420 #define	PR_PROTO	if (idn_debug & IDNDBG_PROTO)	printf
421 #define	PR_STR		if (idn_debug & IDNDBG_STR)	printf
422 #define	PR_DRV		if (idn_debug & IDNDBG_DRV)	printf
423 #define	PR_DATA		if (idn_debug & IDNDBG_DATA)	printf
424 #define	PR_STATE	if (idn_debug & IDNDBG_STATE)	printf
425 #define	PR_DLPI		if (idn_debug & IDNDBG_DLPI)	printf
426 #define	PR_KERN		if (idn_debug & IDNDBG_KERN)	printf
427 #define	PR_ALLOC	if (idn_debug & IDNDBG_ALLOC)	printf
428 #define	PR_REMAP	if (idn_debug & (IDNDBG_SMR|IDNDBG_REMAP))	printf
429 #define	PR_TIMER	if (idn_debug & IDNDBG_TIMER)	printf
430 #define	PR_CHAN		if (idn_debug & IDNDBG_CHAN)	printf
431 #define	PR_AWOL		if (idn_debug & (IDNDBG_PROTO|IDNDBG_AWOL))	printf
432 #define	PR_SYNC		if (idn_debug & IDNDBG_SYNC)	printf
433 #define	_PR_UNUSED0	if (idn_debug & _IDNDBG_UNUSED0)	printf
434 #define	PR_HITLIST	if (idn_debug & IDNDBG_HITLIST)	printf
435 #define	PR_XMON		if (idn_debug & IDNDBG_XMON)	printf
436 #define	PR_TEST		if (idn_debug & IDNDBG_TEST)	printf
437 #else
438 #define	STRING(sss)	char *sss = ""
439 #define	INUM2STR(mm, ss)
440 
441 #define	PR_ALL		if (0) printf
442 #define	PR_XDC		PR_ALL
443 #define	PR_XF		PR_ALL
444 #define	PR_REGS		PR_ALL
445 #define	PR_SMR		PR_ALL
446 #define	PR_PROTO	PR_ALL
447 #define	PR_STR		PR_ALL
448 #define	PR_DRV		PR_ALL
449 #define	PR_DATA		PR_ALL
450 #define	PR_STATE	PR_ALL
451 #define	PR_DLPI		PR_ALL
452 #define	PR_KERN		PR_ALL
453 #define	PR_ALLOC	PR_ALL
454 #define	PR_REMAP	PR_ALL
455 #define	PR_TIMER	PR_ALL
456 #define	PR_CHAN		PR_ALL
457 #define	PR_AWOL		PR_ALL
458 #define	PR_SYNC		PR_ALL
459 #define	PR_SNOOP	PR_ALL
460 #define	PR_HITLIST	PR_ALL
461 #define	PR_XMON		PR_ALL
462 #define	PR_TEST		PR_ALL
463 #endif /* DEBUG */
464 
465 #ifdef _KERNEL
466 /*
467  * IDN drivers fields.
468  *
469  * IDNMINPSZ	Minimum packet size the IDN supports.
470  *
471  * IDNMAXPSZ 	Maximum packet size that IDN supports from upper
472  *		layers.  Is equal to IDN_MTU + ether_header.  Note
473  *		that the IDN driver could support larger packets
474  *		however the infrastructure to support fragmentation
475  *		does not (and should not) exist with respect to
476  *		ethernet packet types.
477  */
478 #ifdef DEBUG
479 #define	IDNDESC		"Inter-Domain Network (DEBUG)"
480 #else
481 #define	IDNDESC		"Inter-Domain Network"
482 #endif /* DEBUG */
483 
484 #define	IDNIDNUM		8264
485 #define	IDNNAME			"idn"
486 #define	IDNMINPSZ		0	/* set at idnopen() */
487 #define	IDNMAXPSZ		0	/* set at idnopen() */
488 
489 #endif /* _KERNEL */
490 
491 /*
492  * IDN Global States.
493  */
494 typedef enum {
495 /*  0 */	IDNGS_OFFLINE = 0,	/* idle */
496 /*  1 */	IDNGS_CONNECT,		/* connecting initial domain */
497 /*  2 */	IDNGS_ONLINE,		/* master selected */
498 /*  3 */	IDNGS_DISCONNECT,	/* local is unlinking */
499 /*  4 */	IDNGS_RECONFIG,		/* selecting new master */
500 /*  5 */	_IDNGS_UNUNSED5,
501 /*  6 */	_IDNGS_UNUNSED6,
502 /*  7 */	_IDNGS_UNUNSED7,
503 /*  8 */	_IDNGS_UNUNSED8,
504 /*  9 */	_IDNGS_UNUNSED9,
505 /* 10 */	IDNGS_IGNORE		/* ignore requests (fault injection) */
506 } idn_gstate_t;
507 
508 #ifdef _KERNEL
509 
510 #define	TIMESTAMP()	(gethrtime() / 1000000ull)
511 
512 /*
513  * Spaced defined in:
514  *	sigblkp[cpu0.cpu_id]->sigb_idn.reserved1.
515  */
516 #define	IDNSB_GSTATE_NEW	0
517 #define	IDNSB_GSTATE_OLD	1
518 #define	IDNSB_MASTERCPU		2
519 #define	IDNSB_RESERVED		3
520 
521 #define	IDNSB_HWCHKPT_MAX	4
522 
523 #define	IDNSB_SIZE		72
524 /*
525  * This structure gets overlay onto:
526  *	sigblkp[cpu0.cpu_id]->sigb_idn.reserved1.
527  *
528  * This structure must be exactly IDNSB_SIZE bytes.
529  */
530 typedef struct idnsb {
531 	uchar_t		id_gstate;
532 	uchar_t		id_pgstate;
533 	uchar_t		id_master_board;
534 	uchar_t		id_pmaster_board;
535 
536 	uchar_t		reserved_DO_NOT_USE[24];	/* idnevent_t field */
537 
538 	struct {
539 		uchar_t	d_board;
540 		uchar_t	d_state;
541 	} id_status[MAX_DOMAINS];
542 	uint_t		id_hwstate;
543 	ushort_t	id_hwchkpt[IDNSB_HWCHKPT_MAX];
544 } idnsb_t;	/* sizeof = 72 (0x48) 18X bytes */
545 
546 
547 #define	IDNSB_DOMAIN_UPDATE(dp) \
548 	{ \
549 		mutex_enter(&idn.idnsb_mutex); \
550 		if (idn.idnsb) { \
551 			int	domid = (dp)->domid; \
552 			if ((dp)->dcpu == IDN_NIL_DCPU) \
553 				idn.idnsb->id_status[domid].d_board = \
554 						(uchar_t)0xff; \
555 			else if ((dp)->dvote.v.board == 0) \
556 				idn.idnsb->id_status[domid].d_board = \
557 					(uchar_t)CPUID_TO_BOARDID((dp)->dcpu); \
558 			else \
559 				idn.idnsb->id_status[domid].d_board = \
560 						(uchar_t)(dp)->dvote.v.board; \
561 			idn.idnsb->id_status[domid].d_state = \
562 				(uchar_t)(dp)->dstate; \
563 		} \
564 		mutex_exit(&idn.idnsb_mutex); \
565 	}
566 /*
567  * The following definitions and macros pertain to the
568  * id_hwstate and id_hwchkpt[] fields.
569  *
570  * id_hwstate (m = mark: 1=open, 2=close)
571  *	  0   1   2   3   4   5   6   7
572  *	---------------------------------
573  *	| m | m | m | m | XX unused XXX |
574  *	---------------------------------
575  *	  |   |   |   |
576  *	  |   |   |   +- CACHE
577  *	  |   |   +- CHAN
578  *	  |   +- LINK
579  *	  +- SMR
580  *
581  * Note that nibble 4 is used in DEBUG for noting cache
582  * flush progress through idnxf_flushall_ecache().  This
583  * will override id_hwchkpt[] since it only has room for
584  * 4 items, however the BBSRAM space is there and
585  * unofficially available :-o
586  *
587  * id_hwchkpt[0] = SMR boardset
588  * id_hwchkpt[1] = LINK boardset
589  * id_hwchkpt[2] = CHAN boardset
590  * id_hwchkpt[3] = CACHE boardset.
591  */
592 #define	IDNSB_CHKPT_SMR		0
593 #define	IDNSB_CHKPT_LINK	1
594 #define	IDNSB_CHKPT_CHAN	2
595 #define	IDNSB_CHKPT_CACHE	3
596 #define	IDNSB_CHKPT_UNUSED	4	/* This is the max you can have */
597 
598 #define	_CHKPT_MARKIT(item, mark) \
599 	{ \
600 		uint_t	mk = (((uint_t)((mark) & 0xf)) << \
601 			(((sizeof (uint_t) << 1) - 1 - (item)) << 2)); \
602 		uint_t	*sp = &idn.idnsb->id_hwstate; \
603 		ASSERT(idn.idnsb); \
604 		*sp &= ~(((uint_t)0xf) << (((sizeof (uint_t) << 1) \
605 			- 1 - (item)) << 2)); \
606 		*sp |= mk; \
607 	}
608 
609 #define	CHECKPOINT_OPENED(item, bset, mark) \
610 	{ \
611 		mutex_enter(&idn.idnsb_mutex); \
612 		if (idn.idnsb) { \
613 			ushort_t *sp = &idn.idnsb->id_hwchkpt[0]; \
614 			_CHKPT_MARKIT((item), (mark));  \
615 			sp[item] |= ((ushort_t)(bset)); \
616 		} \
617 		mutex_exit(&idn.idnsb_mutex); \
618 	}
619 
620 #define	CHECKPOINT_CLOSED(item, bset, mark) \
621 	{ \
622 		mutex_enter(&idn.idnsb_mutex); \
623 		if (idn.idnsb) { \
624 			ushort_t *sp = &idn.idnsb->id_hwchkpt[0]; \
625 			_CHKPT_MARKIT((item), (mark));  \
626 			sp[item] &= (ushort_t)~(bset); \
627 		} \
628 		mutex_exit(&idn.idnsb_mutex); \
629 	}
630 
631 #define	CHECKPOINT_CLEAR(item, mark) \
632 	{ \
633 		mutex_enter(&idn.idnsb_mutex); \
634 		if (idn.idnsb) { \
635 			ushort_t *sp = &idn.idnsb->id_hwchkpt[0]; \
636 			_CHKPT_MARKIT((item), (mark));  \
637 			sp[item] = 0; \
638 		} \
639 		mutex_exit(&idn.idnsb_mutex); \
640 	}
641 #ifdef DEBUG
642 #define	CHECKPOINT_CACHE_CLEAR_DEBUG(mark) \
643 			CHECKPOINT_CLEAR(IDNSB_CHKPT_UNUSED, (mark))
644 #define	CHECKPOINT_CACHE_STEP_DEBUG(bset, mark) \
645 			CHECKPOINT_OPENED(IDNSB_CHKPT_UNUSED, (bset), (mark))
646 #else
647 #define	CHECKPOINT_CACHE_CLEAR_DEBUG(mark)
648 #define	CHECKPOINT_CACHE_STEP_DEBUG(bset, mark)
649 #endif /* DEBUG */
650 
651 
652 #ifdef DEBUG
653 #define	IDN_GSTATE_TRANSITION(ns) \
654 	{ \
655 		hrtime_t	tstamp; \
656 		/*LINTED*/ \
657 		IDN_HISTORY_LOG(IDNH_GSTATE, (ns), 0, 0); \
658 		tstamp = TIMESTAMP(); \
659 		ASSERT(IDN_GLOCK_IS_EXCL()); \
660 		PR_STATE("GSTATE:%ld: (l=%d) %s(%d) -> %s(%d)\n", \
661 			(uint64_t)tstamp, __LINE__, \
662 			idngs_str[idn.state], idn.state, \
663 			idngs_str[ns], (ns)); \
664 		mutex_enter(&idn.idnsb_mutex); \
665 		if (idn.idnsb) { \
666 			idn.idnsb->id_pgstate = (uchar_t)idn.state; \
667 			idn.idnsb->id_gstate = (uchar_t)(ns); \
668 		} \
669 		mutex_exit(&idn.idnsb_mutex); \
670 		idn.state = (ns); \
671 	}
672 #else
673 #define	IDN_GSTATE_TRANSITION(ns) \
674 	{ \
675 		IDN_HISTORY_LOG(IDNH_GSTATE, (ns), 0, 0); \
676 		mutex_enter(&idn.idnsb_mutex); \
677 		if (idn.idnsb) { \
678 			idn.idnsb->id_pgstate = (uchar_t)idn.state; \
679 			idn.idnsb->id_gstate = (uchar_t)(ns); \
680 		} \
681 		mutex_exit(&idn.idnsb_mutex); \
682 		idn.state = (ns); \
683 	}
684 #endif /* DEBUG */
685 
686 /*
687  * IDN link/unlink operations occur asynchronously with respect to the
688  * caller.  The following definitions are to support the return of
689  * success/failure back to the original requesting thread.  It's
690  * unlikely to have multiple outstanding link/unlink requests so we
691  * just provide a very small cache of waiting list entries.  If the
692  * cache becomes exhausted then additional ones are kmem_alloc'd.
693  */
694 #define	IDNOP_CACHE_SIZE	3
695 #define	IDNOP_IN_CACHE(dwl)	\
696 	(((dwl) >= &idn.dopers->_dop_wcache[0]) && \
697 	((dwl) < &idn.dopers->_dop_wcache[IDNOP_CACHE_SIZE]))
698 
699 typedef struct dop_waitlist {
700 	struct dop_waitlist	*dw_next;
701 	domainset_t	dw_reqset;
702 	domainset_t	dw_domset;
703 	short		dw_op;
704 	domainset_t	dw_errset;
705 	idnsb_error_t	*dw_idnerr;
706 	short		dw_errors[MAX_DOMAINS];
707 } dop_waitlist_t;
708 
709 typedef uint_t	idn_xdcargs_t[4];
710 typedef uint_t	idn_chanset_t;
711 
712 /*
713  * Types of synchronization zones which a connection
714  * could be in.
715  */
716 typedef enum {
717 	IDNSYNC_NIL,
718 	IDNSYNC_CONNECT,
719 	IDNSYNC_DISCONNECT
720 } idn_synccmd_t;
721 
722 /*
723  * Type of sync-registration that is being requested.
724  */
725 typedef enum {
726 	IDNSYNC_REG_REG,
727 	IDNSYNC_REG_NEW,
728 	IDNSYNC_REG_QUERY
729 } idn_syncreg_t;
730 
731 #define	IDN_SYNC_NUMZONE	3
732 #define	IDN_SYNC_GETZONE(s)	((((s) != IDNSYNC_CONNECT) && \
733 				((s) != IDNSYNC_DISCONNECT)) ? \
734 				-1 : (int)(s) - 1)
735 #define	IDN_SYNC_GETTRANS(s)	(((s) == IDNSYNC_CONNECT) ? \
736 				idn.domset.ds_trans_on : \
737 				((s) == IDNSYNC_DISCONNECT) ? \
738 				idn.domset.ds_trans_off : 0)
739 
740 /*
741  * Generic states when in a state transition region.
742  * These ultimately map to domain states via
743  * a idn_xphase_t definition.  General model:
744  *
745  *		PEND
746  *		 /\
747  *	        /  \
748  *	       |    |
749  *             V    V
750  *          SENT--->RCVD
751  *	       \    /
752  *	        \  /
753  *	         VV
754  *		FINAL
755  *
756  * Start these types with PEND = 0 so that they're
757  * compatible with idnxs_state_table[] and idn_xphase_t
758  * phases that use the value as an index.
759  */
760 typedef enum {
761 /* 0 */		IDNXS_PEND = 0,
762 /* 1 */		IDNXS_SENT,
763 /* 2 */		IDNXS_RCVD,
764 /* 3 */		IDNXS_FINAL,
765 /* 4 */		IDNXS_NIL
766 } idn_xstate_t;
767 
768 /*
769  * Locking protocol:
770  *
771  *	Each routine is called with SYNC_LOCK and
772  *	the respective domain's DLOCK(EXCL) held.
773  *	The routines must return with these locks
774  *	still held.
775  */
776 struct idn_msgtype;
777 
778 typedef struct {
779 	int	t_state;
780 	int	(*t_check)(int domid, struct idn_msgtype *mtp,
781 				idn_xdcargs_t xargs);
782 	void	(*t_action)(int domid, struct idn_msgtype *mtp,
783 				idn_xdcargs_t xargs);
784 	void	(*t_error)(int domid, struct idn_msgtype *mtp,
785 				idn_xdcargs_t xargs);
786 } idn_trans_t;
787 
788 /*
789  * The callback routines (xt_final & xt_exit) are called with
790  * DLOCK and SYNC_LOCK held and they are required to return
791  * with these locks still held.
792  */
793 typedef struct {
794 	uint_t		xt_msgtype;
795 	idn_trans_t	xt_trans[4];
796 	void		(*xt_final)(int domid);
797 	void		(*xt_exit)(int domid, uint_t msgtype);
798 } idn_xphase_t;
799 
800 /*
801  * Synchronization entry representing the synchronization
802  * state with respect to a given domain for a given zone.
803  */
804 typedef struct idn_syncop {
805 	struct idn_syncop	*s_next;
806 	int			s_domid;
807 	idn_synccmd_t		s_cmd;
808 	int			s_msg;
809 
810 	domainset_t		s_set_exp;
811 	domainset_t		s_set_rdy;
812 	int			(*s_transfunc)(int domid, void *arg);
813 	void			*s_transarg;
814 #ifdef DEBUG
815 	int			s_query[MAX_DOMAINS];
816 #endif /* DEBUG */
817 } idn_syncop_t;
818 
819 #ifdef DEBUG
820 #define	IDN_SYNC_QUERY_INIT(d) \
821 			(bzero((caddr_t)idn_domain[d].dsync.s_query, \
822 				sizeof (idn_domain[d].dsync.s_query)))
823 #define	IDN_SYNC_QUERY_UPDATE(md, sd)	(idn_domain[md].dsync.s_query[sd]++)
824 #else /* DEBUG */
825 #define	IDN_SYNC_QUERY_INIT(d)
826 #define	IDN_SYNC_QUERY_UPDATE(md, sd)
827 #endif /* DEBUG */
828 
829 typedef struct {
830 	idn_syncop_t	*sc_op;
831 	int		sc_cnt;
832 } idn_synczone_t;
833 
834 #endif /* _KERNEL */
835 
836 /*
837  * Vote Ticket used during negotiations and elections.
838  *
839  * 31					  0
840  * -----------------------------------------
841  * |m...|....|pppp|....|Cbbb|bccc|cccB|BBB1|
842  * -----------------------------------------
843  * m	[31]	= master/slave
844  * .	[30:24]	= unused
845  * p	[23:20]	= priority
846  * .	[19:16]	= unused
847  * C	[15]    = connected (has master)
848  * b	[14:11]	= nmembrds-1
849  * c	[10:5]	= ncpus-1
850  * B	[4:1]	= board_id
851  * 1	[0]	= one
852  */
853 typedef union {
854 	struct {
855 		uint_t	master    :1;
856 		uint_t	unused0   :7;
857 		uint_t	priority  :4;
858 		uint_t	unused1   :4;
859 		uint_t	connected :1;
860 		uint_t	nmembrds  :4;
861 		uint_t	ncpus	  :6;
862 		uint_t	board	  :4;
863 		uint_t	one	  :1;
864 	} v;
865 	uint_t	ticket;
866 } idn_vote_t;
867 
868 #define	IDNVOTE_PRI_MASK	0xf
869 #define	IDNVOTE_MAXPRI		0xf
870 #define	IDNVOTE_MINPRI		0
871 #define	IDNVOTE_DEFPRI		1	/* must be larger than MINPRI */
872 /*
873  * Initially:
874  *	vote.v.priority = IDNVOTE_DEFPRI
875  *	vote.v.one	= 1
876  */
877 #define	IDNVOTE_INITIAL_TICKET	((IDNVOTE_DEFPRI << 20) | 1)
878 #define	IDNVOTE_PRIVALUE(vvv) \
879 	((int)vvv.v.priority + ((int)vvv.v.master ? IDNVOTE_MAXPRI : 0))
880 
881 /*
882  * During elections we only use the "elect" attributes of the
883  * election ticket, i.e. those physical attributes pertaining
884  * to the individual domain (priority, nboards, ncpus, board).
885  */
886 #define	IDNVOTE_ELECT_MASK	0x00f07fff
887 #define	IDNVOTE_ELECT(tkt)	((tkt).ticket & IDNVOTE_ELECT_MASK)
888 #define	IDNVOTE_BASICS_MASK	0x00f0ffff
889 #define	IDNVOTE_BASICS(tkt)	((tkt).ticket & IDNVOTE_BASICS_MASK)
890 
891 /*
892  * Values used in idn_select_master().
893  */
894 #define	MASTER_IS_NONE		0	/* index into master_select_table */
895 #define	MASTER_IS_OTHER		1
896 #define	MASTER_IS_LOCAL		2
897 #define	MASTER_IS_REMOTE	3
898 
899 typedef enum {
900 	MASTER_SELECT_VOTE,
901 	MASTER_SELECT_VOTE_RCFG,
902 	MASTER_SELECT_CONNECT,
903 	MASTER_SELECT_REMOTE,
904 	MASTER_SELECT_LOCAL,
905 	MASTER_SELECT_WAIT,
906 	MASTER_SELECT_ERROR
907 } idn_master_select_t;
908 
909 /*
910  * Used to synchronize completion of link/unlink with respect to
911  * the original requester (user).  Necessary since link establishment
912  * occurs asynchronously.
913  */
914 typedef enum {
915 /*  0 */	IDNOP_DISCONNECTED,	/* successfully disconnected */
916 /*  1 */	IDNOP_CONNECTED,	/* successfully established */
917 /*  2 */	IDNOP_ERROR		/* error trying to link/unlink */
918 } idn_opflag_t;
919 
920 /*
921  * IDN Protocol Messages.
922  * These are IDN version (IDN_VERSION) dependent.
923  *
924  *	----- 7, --- 6,5.................0
925  *	|  ack | nack | IDN message type |
926  *	----------------------------------
927  */
928 #define	IDN_VERSION	1
929 
930 /*
931  * Must be no more than 6-bits.  See DMV private data.
932  */
933 #define	IDNP_ACK	0x20
934 #define	IDNP_NACK	0x10
935 #define	IDNP_NULL	0x00
936 #define	IDNP_NEGO	0x01
937 #define	IDNP_CON	0x02
938 #define	IDNP_CFG	0x03
939 #define	IDNP_FIN	0x04
940 #define	IDNP_CMD	0x05
941 #define	IDNP_DATA	0x06
942 
943 #define	IDN_NUM_MSGTYPES	7
944 #define	IDNP_ACKNACK_MASK	(IDNP_ACK | IDNP_NACK)
945 #define	IDNP_MSGTYPE_MASK	0x0f
946 #define	VALID_MSGTYPE(m)	(((m) >= IDNP_NEGO) && ((m) < IDN_NUM_MSGTYPES))
947 
948 typedef struct idn_msgtype {
949 	ushort_t	mt_mtype;
950 	ushort_t	mt_atype;
951 	ushort_t	mt_cookie;
952 } idn_msgtype_t;
953 
954 /*
955  * IDN private data section of DMV layout (48 bits).
956  *
957  * 47......40,39.....34,33.....28,27..24,23......16,15..............0
958  * | version | msgtype | acktype |  did |   cpuid  |     cookie     |
959  * ------------------------------------------------------------------
960  *
961  * version	Local domain's version of IDN software.
962  * msgtype	Type of IDN message, e.g. nego, syn, etc.
963  * acktype	If msgtype is a ACK or NACK, then acktype is the
964  *		type of ack that we're receiving, e.g. ack/nego|ack.
965  * did		Local domain's ID (netid) - system-wide unique.
966  * cpuid	Local domain's CPU->cpu_id that sending message.
967  * cookie	Cookie assigned by remote domain for authentication.
968  *		For NEGO & NEGO+ACK messages, it's the cookie that
969  *		the sender expects the receiver to use in subsequent
970  *		messages.  The upper-eight bits represent a timer
971  *		cookie to associate timers with expected messages.
972  */
973 #endif /* !_ASM */
974 
975 #ifdef _KERNEL
976 
977 #define	_IDNPD_COOKIE_MASK	0xffff
978 #define	_IDNPD_COOKIE_SHIFT	32
979 #define	_IDNPD_VER_MASK		0xff
980 #define	_IDNPD_VER_SHIFT	24
981 #define	_IDNPD_MTYPE_MASK	0x3f
982 #define	_IDNPD_MTYPE_SHIFT	18
983 #define	_IDNPD_ATYPE_MASK	0x3f
984 #define	_IDNPD_ATYPE_SHIFT	12
985 #define	_IDNPD_DOMID_MASK	0xf
986 #define	_IDNPD_DOMID_SHIFT	8
987 #define	_IDNPD_CPUID_MASK	0xff
988 #define	_IDNPD_CPUID_SHIFT	0
989 
990 #define	_IDNPD_COOKIE_LEN	16
991 
992 #ifndef _ASM
993 
994 #define	IDN_PD2COOKIE(pdata) \
995 	(((uint_t)((pdata) >> _IDNPD_COOKIE_SHIFT)) & _IDNPD_COOKIE_MASK)
996 #define	IDN_PD2VER(pdata) \
997 	(((uint_t)((pdata) >> _IDNPD_VER_SHIFT)) & _IDNPD_VER_MASK)
998 #define	IDN_PD2MTYPE(pdata) \
999 	(((uint_t)((pdata) >> _IDNPD_MTYPE_SHIFT)) & _IDNPD_MTYPE_MASK)
1000 #define	IDN_PD2ATYPE(pdata) \
1001 	(((uint_t)((pdata) >> _IDNPD_ATYPE_SHIFT)) & _IDNPD_ATYPE_MASK)
1002 #define	IDN_PD2DOMID(pdata) \
1003 	(((uint_t)((pdata) >> _IDNPD_DOMID_SHIFT)) & _IDNPD_DOMID_MASK)
1004 #define	IDN_PD2CPUID(pdata) \
1005 	(((uint_t)((pdata) >> _IDNPD_CPUID_SHIFT)) & _IDNPD_CPUID_MASK)
1006 
1007 #define	IDN_MAKE_PDATA(mtype, atype, cookie) \
1008 	((((uint64_t)(cookie) & UINT64_C(_IDNPD_COOKIE_MASK))	<< \
1009 					_IDNPD_COOKIE_SHIFT)	| \
1010 	(((uint64_t)idn.version & UINT64_C(_IDNPD_VER_MASK))	<< \
1011 					_IDNPD_VER_SHIFT)	| \
1012 	(((uint64_t)(mtype) & UINT64_C(_IDNPD_MTYPE_MASK))	<< \
1013 					_IDNPD_MTYPE_SHIFT)	| \
1014 	(((uint64_t)(atype) & UINT64_C(_IDNPD_ATYPE_MASK))	<< \
1015 					_IDNPD_ATYPE_SHIFT)	| \
1016 	(((uint64_t)idn.localid & UINT64_C(_IDNPD_DOMID_MASK))	<< \
1017 					_IDNPD_DOMID_SHIFT)	| \
1018 	(((uint64_t)CPU->cpu_id & UINT64_C(_IDNPD_CPUID_MASK))	<< \
1019 					_IDNPD_CPUID_SHIFT))
1020 
1021 #define	IDN_TCOOKIE(ck)		(((ck) >> 8) & 0xff)
1022 #define	IDN_DCOOKIE(ck)		((ck) & 0xff)
1023 #define	IDN_MAKE_COOKIE(d, t)	((((t) & 0xff) << 8) | ((d) & 0xff))
1024 
1025 /*
1026  * IDNP_NEGO
1027  *
1028  * 127........96,95........64,63........32,31.........0
1029  * |   vote     |             domainset               |
1030  * ----------------------------------------------------
1031  * vote		Local/Remote domain's vote ticket.
1032  * domainset	Mask of cpuids of domains to which
1033  *		sender is connected.  Position in domainset
1034  *		designates respective domainid.
1035  *		E.g. domainset[6] = 20 -> domainid 6 is
1036  *		accessible via cpuid 20.
1037  *		The slot for the receiving domain
1038  *		contains the masterid of the sending
1039  *		domain.  If the sending domain does
1040  *		not have a master then the entry will
1041  *		contain IDNNEG_NO_MASTER.
1042  *
1043  * These macros insert a domainid-cpuid pair into the
1044  * domainset to be subsequently passed in a NEGO message,
1045  * also retrieve the cpuid from the domainset for a
1046  * given domainid.
1047  *
1048  * Usage:
1049  *	Sending:
1050  *		mask = IDNNEG_DSET_MYMASK();
1051  *		IDNNEG_DSET_INIT(dset, mask)
1052  *		for (all domains except self)
1053  *			IDNNEG_DSET_SET(dset, domain, cpuid, mask);
1054  *
1055  *	Receiving:
1056  *		IDNNEG_DSET_GET_MASK(dset, recv_domid, recv_mask);
1057  *		for (all domains except recv_domid)
1058  *			IDNNEG_DSET_GET(dset, domid, cpuid, recv_mask);
1059  */
1060 typedef uint_t	idnneg_dset_t[3];
1061 
1062 #define	IDNNEG_NO_MASTER		0x3f
1063 #define	__IDNNEG_DSET_CLEAR(dset)	(bzero((caddr_t)(dset), \
1064 						sizeof (idnneg_dset_t)))
1065 #define	IDNNEG_DSET_MYMASK()		(idn_domain[idn.localid].dcpu)
1066 
1067 #define	IDNNEG_DSET_INIT(dset, mask) \
1068 	{ \
1069 		__IDNNEG_DSET_CLEAR(dset); \
1070 		IDNNEG_DSET_SET((dset), idn.localid, (mask), idn.localid); \
1071 	}
1072 
1073 #define	IDNNEG_DSET_SET(dset, domid, cpuid, mask) \
1074 	{ \
1075 		uint_t	_s = ((domid) & 0xf) * 6; \
1076 		int	_i = _s >> 5; \
1077 		uint_t	_s0 = _s & 0x1f; \
1078 		uint_t	_t = ((cpuid) ^ (mask)) & 0x3f; \
1079 		/*LINTED*/ \
1080 		ASSERT(((domid) == idn.localid) ? \
1081 			((mask) == idn.localid) : ((cpuid) != (mask))); \
1082 		(dset)[_i] |= _t << _s0; \
1083 		if ((_s0 + 6) > 32) \
1084 			(dset)[_i + 1] |= _t >> (32 - _s0);  \
1085 	}
1086 
1087 #define	__IDNNEG_DSET_GET(dset, domid, cpuid, mask, uncond) \
1088 	{ \
1089 		uint_t	_s = ((domid) & 0xf) * 6; \
1090 		int	_i = _s >> 5; \
1091 		uint_t	_s0 = _s & 0x1f; \
1092 		uint_t	_s1 = (_s + 6) & 0x1f; \
1093 		(cpuid) = ((dset)[_i] >> _s0) & 0x3f; \
1094 		if ((_s0 + 6) > 32) \
1095 			(cpuid) |= ((dset)[_i + 1] << (6 - _s1)) & 0x3f; \
1096 		if ((cpuid) || (uncond)) \
1097 			(cpuid) ^= (mask) & 0x3f; \
1098 		else \
1099 			(cpuid) = -1; \
1100 	}
1101 
1102 #define	IDNNEG_DSET_GET_MASK(dset, domid, mask) \
1103 		__IDNNEG_DSET_GET((dset), (domid), (mask), (domid), 1)
1104 
1105 #define	IDNNEG_DSET_GET_MASTER(dset, master) \
1106 		__IDNNEG_DSET_GET((dset), idn.localid, (master), \
1107 				idn.localid+MAX_DOMAINS, 0)
1108 
1109 #define	IDNNEG_DSET_SET_MASTER(dset, domid, master) \
1110 		IDNNEG_DSET_SET((dset), (domid), (master), \
1111 				(domid)+MAX_DOMAINS)
1112 
1113 #define	IDNNEG_DSET_GET(dset, domid, cpuid, mask) \
1114 		__IDNNEG_DSET_GET((dset), (domid), (cpuid), (mask), 0)
1115 
1116 /*
1117  * IDNP_CFG sub-types.
1118  *
1119  * Format of first 32 bit word in XDC:
1120  *	stX  = sub-type.
1121  *	staX = sub-type arg.
1122  *	X    = position in idn_cfgsubtype_t.param.p[] array.
1123  *	num  = number of parameters in this XDC (0-3)
1124  *
1125  *      31...28,27...24,23...20,19...16,15...12,11....8,7.....3,2....0
1126  *	|  st0 .  sta0 |   st1 .  sta1 |   st2 .  sta2 | phase | num |
1127  *	--------------------------------------------------------------
1128  *
1129  * Note that since the first 32-bit word in a (IDNP_CFG) XDC is used
1130  * for a sub-type, subsequent three 32-bits words are used for data that
1131  * pertains to respective sub-type, i.e. first sub-type corresponds
1132  * to first of the 3x32-bit words (pos=0), second sub-type corresponds
1133  * to second of the 3x32-bit words (pos=1), etc.  Obviously, a max of
1134  * only three sub-types can be sent per xdc.
1135  */
1136 #define	IDNCFG_BARLAR		0x1	/* SMR base/limit pfn */
1137 #define	  IDNCFGARG_BARLAR_BAR		0	/* BAR */
1138 #define	  IDNCFGARG_BARLAR_LAR		1	/* LAR */
1139 #define	IDNCFG_MCADR		0x2	/* MC ADR, arg = board number */
1140 #define	IDNCFG_NMCADR		0x3	/* Number of MC ADRs to expect */
1141 #define	IDNCFG_CPUSET		0x4	/* dcpuset of remote domain */
1142 #define	  IDNCFGARG_CPUSET_UPPER  	0	/* 1st word */
1143 #define	  IDNCFGARG_CPUSET_LOWER  	1	/* 2nd word */
1144 #define	IDNCFG_NETID		0x5	/* dnetid, arg = 0 */
1145 #define	IDNCFG_BOARDSET		0x6	/* board set, arg = 0 */
1146 #define	IDNCFG_SIZE		0x7	/* SMR size parameters */
1147 #define	  IDNCFGARG_SIZE_MTU		0	/* IDN_MTU */
1148 #define	  IDNCFGARG_SIZE_BUF		1	/* IDN_SMR_BUFSIZE */
1149 #define	  IDNCFGARG_SIZE_SLAB		2	/* IDN_SLAB_BUFCOUNT */
1150 #define	  IDNCFGARG_SIZE_NWR		3	/* IDN_NWR_SIZE */
1151 #define	IDNCFG_DATAMBOX		0x8	/* SMR data mailbox info */
1152 #define	  IDNCFGARG_DATAMBOX_TABLE  	0	/* recvmbox table */
1153 #define	  IDNCFGARG_DATAMBOX_DOMAIN	1	/* domain's recvmbox */
1154 #define	  IDNCFGARG_DATAMBOX_INDEX	2	/* domain's index into table */
1155 #define	IDNCFG_DATASVR		0x9	/* Data server info */
1156 #define	  IDNCFGARG_DATASVR_MAXNETS	0	/* max # of nets/channels */
1157 #define	  IDNCFGARG_DATASVR_MBXPERNET	1	/* # mbox per net/channel */
1158 #define	IDNCFG_OPTIONS		0xa	/* various options */
1159 #define	  IDNCFGARG_CHECKSUM		0	/* IDN_CHECKSUM */
1160 
1161 #define	IDN_CFGPARAM(st, sta)	((uchar_t)((((st) & 0xf) << 4) | ((sta) & 0xf)))
1162 #define	IDN_CFGPARAM_TYPE(p)	(((p) >> 4) & 0xf)
1163 #define	IDN_CFGPARAM_ARG(p)	((p) & 0xf)
1164 
1165 typedef union {
1166 	struct {
1167 		uchar_t	p[3];
1168 		uchar_t	_num_phase;	/* info.num, info.phase used instead */
1169 	} param;
1170 	struct {
1171 		uint_t	_p	: 24;	/* param.p[] used instead */
1172 		uint_t	num	: 2;
1173 		uint_t	phase	: 6;
1174 	} info;
1175 	uint_t	val;
1176 } idn_cfgsubtype_t;
1177 
1178 /*
1179  * IDN_MASTER_NCFGITEMS
1180  *	Minimum number of config items expected from master.
1181  *
1182  * IDN_SLAVE_NCFGITEMS
1183  *	Number of config items expected from slave.
1184  */
1185 #define	IDN_MASTER_NCFGITEMS	17	/* max = +14 (mcadrs) */
1186 #define	IDN_SLAVE_NCFGITEMS	12
1187 
1188 /*
1189  * IDNP_CMD sub-types.
1190  */
1191 typedef enum {
1192 /*  1 */	IDNCMD_SLABALLOC = 1,	/* Request to allocate a slab */
1193 /*  2 */	IDNCMD_SLABFREE,	/* Request to free a slab */
1194 /*  3 */	IDNCMD_SLABREAP,	/* Reap any free slabs */
1195 /*  4 */	IDNCMD_NODENAME		/* Query nodename of domain */
1196 } idn_cmd_t;
1197 
1198 #define	VALID_IDNCMD(c)		(((int)(c) >= (int)IDNCMD_SLABALLOC) && \
1199 					((int)(c) <= (int)IDNCMD_NODENAME))
1200 /*
1201  * IDNP_NACK
1202  */
1203 typedef enum {
1204 /*  1 */	IDNNACK_NOCONN = 1,
1205 /*  2 */	IDNNACK_BADCHAN,
1206 /*  3 */	IDNNACK_BADCFG,
1207 /*  4 */	IDNNACK_BADCMD,
1208 /*  5 */	IDNNACK_RETRY,
1209 /*  6 */	IDNNACK_DUP,
1210 /*  7 */	IDNNACK_EXIT,
1211 /*  8 */	IDNNACK_RESERVED1,
1212 /*  9 */	IDNNACK_RESERVED2,
1213 /* 10 */	IDNNACK_RESERVED3
1214 } idn_nack_t;
1215 
1216 /*
1217  * IDNP_CON sub-types.
1218  */
1219 typedef enum {
1220 /*  0 */	IDNCON_OFF = 0,
1221 /*  1 */	IDNCON_NORMAL,		/* regular connect sequence */
1222 /*  2 */	IDNCON_QUERY		/* query for connect info */
1223 } idn_con_t;
1224 
1225 /*
1226  * IDNP_FIN sub-types.
1227  */
1228 typedef enum {
1229 /*  0 */	IDNFIN_OFF = 0,		/* active, no fin */
1230 /*  1 */	IDNFIN_NORMAL,		/* normal disconnect req */
1231 /*  2 */	IDNFIN_FORCE_SOFT,	/* normal dis, force if goes AWOL */
1232 /*  3 */	IDNFIN_FORCE_HARD,	/* force disconnect of AWOL domain */
1233 /*  4 */	IDNFIN_QUERY		/* query for fin info */
1234 } idn_fin_t;
1235 
1236 #define	VALID_FIN(f)		(((int)(f) > 0) && \
1237 					((int)(f) < (int)IDNFIN_QUERY))
1238 #define	FIN_IS_FORCE(f)		(((f) == IDNFIN_FORCE_SOFT) || \
1239 					((f) == IDNFIN_FORCE_HARD))
1240 
1241 /*
1242  * FIN ARG types - reasons a FIN was sent.
1243  */
1244 typedef enum {
1245 /*  0 */	IDNFIN_ARG_NONE = 0,		/* no argument */
1246 /*  1 */	IDNFIN_ARG_SMRBAD,		/* SMR is corrupted */
1247 /*  2 */	IDNFIN_ARG_CPUCFG,		/* missing cpu per board */
1248 /*  3 */	IDNFIN_ARG_HWERR,		/* error programming hardware */
1249 /*  4 */	IDNFIN_ARG_CFGERR_FATAL,	/* Fatal error during CONFIG */
1250 /*  5 */	IDNFIN_ARG_CFGERR_MTU,		/* MTU sizes conflict */
1251 /*  6 */	IDNFIN_ARG_CFGERR_BUF,		/* SMR_BUF_SIZE conflicts */
1252 /*  7 */	IDNFIN_ARG_CFGERR_SLAB,		/* SLAB sizes conflict */
1253 /*  8 */	IDNFIN_ARG_CFGERR_NWR,		/* NWR sizes conflict */
1254 /*  9 */	IDNFIN_ARG_CFGERR_NETS,		/* MAX_NETS conflict */
1255 /* 10 */	IDNFIN_ARG_CFGERR_MBOX,		/* MBOX_PER_NET conflict */
1256 /* 11 */	IDNFIN_ARG_CFGERR_NMCADR,	/* NMCADR mismatches actual */
1257 /* 12 */	IDNFIN_ARG_CFGERR_MCADR,	/* missing some MCADRs */
1258 /* 13 */	IDNFIN_ARG_CFGERR_CKSUM,	/* checksum settings conflict */
1259 /* 14 */	IDNFIN_ARG_CFGERR_SMR		/* SMR sizes conflict */
1260 } idn_finarg_t;
1261 
1262 #define	IDNFIN_ARG_IS_FATAL(fa)	((fa) > IDNFIN_ARG_NONE)
1263 
1264 #define	SET_FIN_TYPE(x, t) \
1265 		((x) &= 0xffff, (x) |= (((uint_t)(t) & 0xffff) << 16))
1266 #define	SET_FIN_ARG(x, a) \
1267 		((x) &= ~0xffff, (x) |= ((uint_t)(a) & 0xffff))
1268 #define	GET_FIN_TYPE(x)		((idn_fin_t)(((x) >> 16) & 0xffff))
1269 #define	GET_FIN_ARG(x)		((idn_finarg_t)((x) & 0xffff))
1270 
1271 #define	FINARG2IDNKERR(fa) \
1272 	(((fa) == IDNFIN_ARG_SMRBAD)	   ? IDNKERR_SMR_CORRUPTED : \
1273 	((fa) == IDNFIN_ARG_CPUCFG)	   ? IDNKERR_CPU_CONFIG	   : \
1274 	((fa) == IDNFIN_ARG_HWERR)	   ? IDNKERR_HW_ERROR	   : \
1275 	((fa) == IDNFIN_ARG_CFGERR_FATAL)  ? IDNKERR_HW_ERROR	   : \
1276 	((fa) == IDNFIN_ARG_CFGERR_MTU)    ? IDNKERR_CONFIG_MTU	   : \
1277 	((fa) == IDNFIN_ARG_CFGERR_BUF)    ? IDNKERR_CONFIG_BUF	   : \
1278 	((fa) == IDNFIN_ARG_CFGERR_SLAB)   ? IDNKERR_CONFIG_SLAB   : \
1279 	((fa) == IDNFIN_ARG_CFGERR_NWR)    ? IDNKERR_CONFIG_NWR    : \
1280 	((fa) == IDNFIN_ARG_CFGERR_NETS)   ? IDNKERR_CONFIG_NETS   : \
1281 	((fa) == IDNFIN_ARG_CFGERR_MBOX)   ? IDNKERR_CONFIG_MBOX   : \
1282 	((fa) == IDNFIN_ARG_CFGERR_NMCADR) ? IDNKERR_CONFIG_NMCADR : \
1283 	((fa) == IDNFIN_ARG_CFGERR_MCADR)  ? IDNKERR_CONFIG_MCADR  : \
1284 	((fa) == IDNFIN_ARG_CFGERR_CKSUM)  ? IDNKERR_CONFIG_CKSUM  : \
1285 	((fa) == IDNFIN_ARG_CFGERR_SMR)	   ? IDNKERR_CONFIG_SMR    : 0)
1286 
1287 /*
1288  * FIN SYNC types.
1289  */
1290 #define	IDNFIN_SYNC_OFF		0	/* not set */
1291 #define	IDNFIN_SYNC_NO		1	/* no-sync necessary */
1292 #define	IDNFIN_SYNC_YES		2	/* do fin synchronously */
1293 
1294 typedef short	idn_finsync_t;
1295 
1296 /*
1297  * IDNP_FIN options.
1298  */
1299 typedef enum {
1300 /*  0 */	IDNFIN_OPT_NONE = 0,	/* none (used w/query) */
1301 /*  1 */	IDNFIN_OPT_UNLINK,	/* normal unlink request */
1302 /*  2 */	IDNFIN_OPT_RELINK	/* disconnect and retry link */
1303 } idn_finopt_t;
1304 
1305 #define	VALID_FINOPT(f)		(((f) == IDNFIN_OPT_UNLINK) || \
1306 				((f) == IDNFIN_OPT_RELINK))
1307 
1308 #define	FIN_MASTER_DOMID(x)	(((((x) >> 16) & 0xffff) == 0xffff) ? \
1309 				IDN_NIL_DOMID : (((x) >> 16) & 0xffff))
1310 #define	FIN_MASTER_CPUID(x)	((((x) & 0xffff) == 0xffff) ? \
1311 				IDN_NIL_DCPU : ((x) & 0xfff))
1312 #define	MAKE_FIN_MASTER(d, c)	((((uint_t)(d) & 0xffff) << 16) | \
1313 				((uint_t)(c) & 0xffff))
1314 #define	NIL_FIN_MASTER		MAKE_FIN_MASTER(IDN_NIL_DOMID, IDN_NIL_DCPU)
1315 
1316 #ifdef DEBUG
1317 #define	IDN_FSTATE_TRANSITION(dp, ns) \
1318 	{ \
1319 		int	_id; \
1320 		_id = (dp)->domid; \
1321 		if ((dp)->dfin != (ns)) { \
1322 			hrtime_t	tstamp; \
1323 			tstamp = TIMESTAMP(); \
1324 			IDN_HISTORY_LOG(IDNH_FIN, _id, (ns), 0); \
1325 			PR_STATE("FSTATE:%ld:%d: (l=%d, b/p=%d/%d) " \
1326 				"%s(%d) -> %s(%d)\n", \
1327 				(uint64_t)tstamp, _id, \
1328 				__LINE__, \
1329 				((dp)->dcpu == IDN_NIL_DCPU) ? -1 : \
1330 					CPUID_TO_BOARDID((dp)->dcpu), \
1331 				(dp)->dcpu, \
1332 				idnfin_str[(dp)->dfin], (dp)->dfin, \
1333 				idnfin_str[ns], (ns)); \
1334 			(dp)->dfin = (ns); \
1335 		} \
1336 	}
1337 #else
1338 #define	IDN_FSTATE_TRANSITION(dp, ns) \
1339 	{ \
1340 		IDN_HISTORY_LOG(IDNH_FIN, (dp)->domid, (ns), 0); \
1341 		(dp)->dfin = (ns); \
1342 	}
1343 #endif /* DEBUG */
1344 
1345 #endif /* !_ASM */
1346 #endif /* _KERNEL */
1347 
1348 #ifndef _ASM
1349 /*
1350  * IDN Per-Domain States.
1351  */
1352 typedef enum {
1353 /*  0 */	IDNDS_CLOSED,		/* idle */
1354 /*  1 */	IDNDS_NEGO_PEND,	/* link initiating */
1355 /*  2 */	IDNDS_NEGO_SENT,	/* link initiated, nego sent */
1356 /*  3 */	IDNDS_NEGO_RCVD,	/* link wanted, nego+ack sent */
1357 /*  4 */	IDNDS_CONFIG,		/* passing config info, prgm hw */
1358 /*  5 */	IDNDS_CON_PEND,		/* connection pending */
1359 /*  6 */	IDNDS_CON_SENT,		/* con sent */
1360 /*  7 */	IDNDS_CON_RCVD,		/* con sent & received */
1361 /*  8 */	IDNDS_CON_READY,	/* ready to establish link */
1362 /*  9 */	IDNDS_CONNECTED,	/* established - linked */
1363 /* 10 */	IDNDS_FIN_PEND,		/* unlink initiating */
1364 /* 11 */	IDNDS_FIN_SENT,		/* unlink initiated, fin sent */
1365 /* 12 */	IDNDS_FIN_RCVD,		/* unlink wanted by remote */
1366 /* 13 */	IDNDS_DMAP		/* deprogramming hw */
1367 } idn_dstate_t;
1368 
1369 #define	IDNDS_IS_CLOSED(dp)	(((dp)->dstate == IDNDS_CLOSED) || \
1370 				((dp)->dstate == IDNDS_DMAP))
1371 #define	IDNDS_IS_CONNECTING(dp) (((dp)->dstate > IDNDS_CLOSED) && \
1372 				((dp)->dstate < IDNDS_CONNECTED))
1373 #define	IDNDS_IS_DISCONNECTING(dp)	((dp)->dstate > IDNDS_CONNECTED)
1374 #define	IDNDS_CONFIG_DONE(dp)	(((dp)->dstate == IDNDS_CLOSED) || \
1375 				((dp)->dstate > IDNDS_CONFIG))
1376 #define	IDNDS_SYNC_TYPE(dp)	(((dp)->dfin_sync != IDNFIN_SYNC_OFF) ? \
1377 				(dp)->dfin_sync : \
1378 					((dp)->dstate < IDNDS_CON_READY) ? \
1379 					IDNFIN_SYNC_NO : IDNFIN_SYNC_YES)
1380 
1381 #endif /* !_ASM */
1382 
1383 #ifdef _KERNEL
1384 #ifndef _ASM
1385 /*
1386  * ---------------------------------------------------------------------
1387  */
1388 typedef struct idn_timer {
1389 	struct idn_timer	*t_forw,
1390 				*t_back;
1391 	struct idn_timerq	*t_q;
1392 
1393 	timeout_id_t		t_id;
1394 	short			t_domid;
1395 	short			t_onq;
1396 	ushort_t		t_type;
1397 	ushort_t		t_subtype;
1398 	uint_t			t_cookie;
1399 #ifdef DEBUG
1400 	hrtime_t		t_posttime;
1401 	hrtime_t		t_exectime;
1402 #endif /* DEBUG */
1403 } idn_timer_t;
1404 
1405 #define	IDN_TIMER_PUBLIC_COOKIE		0xf
1406 
1407 #define	IDN_TIMERQ_IS_LOCKED(tq)	(MUTEX_HELD(&(tq)->tq_mutex))
1408 #define	IDN_TIMERQ_LOCK(tq)		(mutex_enter(&(tq)->tq_mutex))
1409 #define	IDN_TIMERQ_UNLOCK(tq)		(mutex_exit(&(tq)->tq_mutex))
1410 
1411 #define	IDN_TIMERQ_INIT(tq) 		(idn_timerq_init(tq))
1412 #define	IDN_TIMERQ_DEINIT(tq) 		(idn_timerq_deinit(tq))
1413 #define	IDN_TIMER_ALLOC()		(idn_timer_alloc())
1414 #define	IDN_TIMER_FREE(tp)		(idn_timer_free(tp))
1415 
1416 #define	IDN_TIMER_START(tq, tp, tim) \
1417 			(idn_timer_start((tq), (tp), (tim)))
1418 #define	IDN_TIMER_STOP(tq, typ, ck) \
1419 			((void) idn_timer_stop((tq), (typ), (ck)))
1420 #define	IDN_TIMER_STOPALL(tp) \
1421 			((void) idn_timer_stopall(tp))
1422 #define	IDN_TIMER_GET(tq, typ, tp, ck) \
1423 	{ \
1424 		mutex_enter(&((tq)->tq_mutex)); \
1425 		(tp) = idn_timer_get((tq), (typ), (ck)); \
1426 		mutex_exit(&((tq)->tq_mutex)); \
1427 	}
1428 #define	IDN_TIMER_DEQUEUE(tq, tp) \
1429 			(idn_timer_dequeue((tq), (tp)))
1430 #ifdef DEBUG
1431 #define	IDN_TIMER_POST(tp) \
1432 	((tp)->t_posttime = gethrtime(), (tp)->t_exectime = 0)
1433 #define	IDN_TIMER_EXEC(tp)	((tp)->t_exectime = gethrtime())
1434 #else /* DEBUG */
1435 #define	IDN_TIMER_POST(tp)
1436 #define	IDN_TIMER_EXEC(tp)
1437 #endif /* DEBUG */
1438 
1439 #define	IDN_MSGTIMER_START(domid, typ, subtyp, tim, ckp) \
1440 	{ \
1441 		idn_timer_t	*_tp; \
1442 		char		_str[15]; \
1443 		ushort_t	*_ckp = (ckp); \
1444 		inum2str((typ), _str); \
1445 		PR_TIMER("msgtimer:%d: START: type = %s (0x%x)\n", \
1446 				(domid), _str, (typ)); \
1447 		_tp = IDN_TIMER_ALLOC(); \
1448 		_tp->t_type	= (ushort_t)(typ); \
1449 		_tp->t_subtype	= (ushort_t)(subtyp); \
1450 		_tp->t_domid	= (short)(domid); \
1451 		_tp->t_cookie	= (_ckp) ? *(_ckp) : 0; \
1452 		IDN_TIMER_POST(_tp); \
1453 		if (_ckp) { \
1454 			*(_ckp) = IDN_TIMER_START(&idn_domain[domid].dtimerq, \
1455 						_tp, (tim)); \
1456 		} else { \
1457 			(void) IDN_TIMER_START(&idn_domain[domid].dtimerq, \
1458 						_tp, (tim)); \
1459 		} \
1460 	}
1461 #define	IDN_MSGTIMER_STOP(domid, typ, ck) \
1462 	{ \
1463 		char	_str[15]; \
1464 		inum2str((typ), _str); \
1465 		PR_TIMER("msgtimer:%d: STOP: type = %s (0x%x), " \
1466 			"cookie = 0x%x\n", \
1467 				(domid), _str, (typ), (ck)); \
1468 		IDN_TIMER_STOP(&idn_domain[domid].dtimerq, (typ), (ck)); \
1469 	}
1470 #define	IDN_MSGTIMER_GET(dp, typ, tp, ck) \
1471 			IDN_TIMER_GET(&(dp)->dtimerq, (typ), (tp), (ck))
1472 
1473 /*
1474  * IDN_SLABALLOC_WAITTIME
1475  *		Max wait time in ticks that local domains waits for
1476  *		master to respond to a slab allocation request.  Has
1477  *		to be at least as long as wait time for a response to
1478  *		the command.
1479  */
1480 #define	IDN_SLABALLOC_WAITTIME	((3 * idn_msg_waittime[IDNP_CMD]) / 2)
1481 
1482 /*
1483  * Domain state transition macros.
1484  */
1485 #ifdef DEBUG
1486 #define	IDN_DSTATE_TRANSITION(dp, ns) \
1487 	{ \
1488 		int		id; \
1489 		hrtime_t	tstamp; \
1490 		tstamp = TIMESTAMP(); \
1491 		ASSERT(RW_WRITE_HELD(&(dp)->drwlock)); \
1492 		id = (dp)->domid; \
1493 		IDN_HISTORY_LOG(IDNH_DSTATE, id, (ns), \
1494 				(uint_t)(dp)->dcpu); \
1495 		PR_STATE("DSTATE:%ld:%d: (l=%d, b/p=%d/%d) " \
1496 			"%s(%d) -> %s(%d)\n", \
1497 			(uint64_t)tstamp, id, \
1498 			__LINE__, \
1499 			((dp)->dcpu == IDN_NIL_DCPU) ? \
1500 				-1 : CPUID_TO_BOARDID((dp)->dcpu), \
1501 			(dp)->dcpu, \
1502 			idnds_str[(dp)->dstate], (dp)->dstate, \
1503 			idnds_str[ns], (ns)); \
1504 		(dp)->dstate = (ns); \
1505 		IDNSB_DOMAIN_UPDATE(dp); \
1506 	}
1507 #else
1508 #define	IDN_DSTATE_TRANSITION(dp, ns) \
1509 	{ \
1510 		IDN_HISTORY_LOG(IDNH_DSTATE, (dp)->domid, \
1511 			(ns), (uint_t)(dp)->dcpu); \
1512 		(dp)->dstate = (ns); \
1513 		IDNSB_DOMAIN_UPDATE(dp); \
1514 	}
1515 #endif /* DEBUG */
1516 
1517 #define	IDN_XSTATE_TRANSITION(dp, xs) \
1518 	{ \
1519 		int	_xs = (xs); \
1520 		(dp)->dxstate = _xs; \
1521 		if (_xs != IDNXS_NIL) { \
1522 			ASSERT((dp)->dxp); \
1523 			IDN_DSTATE_TRANSITION((dp), \
1524 				(dp)->dxp->xt_trans[_xs].t_state); \
1525 		} \
1526 	}
1527 
1528 /*
1529  * ---------------------------------------------------------------------
1530  * IDN Per-Domain Data
1531  *
1532  * The comment to the right of the respective field represents
1533  * what lock protects that field.  If there is no comment then
1534  * no lock is required to access the field.
1535  * ---------------------------------------------------------------------
1536  */
1537 
1538 #define	MAXDNAME	32
1539 
1540 typedef struct idn_domain {
1541 	krwlock_t	drwlock;
1542 			/*
1543 			 * Assigned domid for domain.  Never
1544 			 * changes once idn_domain[] is
1545 			 * initialized.  We are guaranteed that
1546 			 * all domains in IDN will have a
1547 			 * uniqueue domid in the range (0-15).
1548 			 */
1549 	int		domid;
1550 	idn_dstate_t	dstate;			/* drwlock */
1551 	idn_xstate_t	dxstate;		/* drwlock */
1552 			/*
1553 			 * Gotten from uname -n for local
1554 			 * domain.  Remote domains pass
1555 			 * theirs during Config phase.
1556 			 */
1557 	char		dname[MAXDNAME];	/* drwlock */
1558 			/*
1559 			 * IDN-wide unique identifier for the
1560 			 * given domain.  This value will be
1561 			 * the same as the domid.
1562 			 */
1563 	ushort_t	dnetid;			/* drwlock */
1564 	idn_vote_t	dvote;			/* drwlock */
1565 			/*
1566 			 * Used during FIN sequenece to
1567 			 * determine what type of shutdown
1568 			 * (unlink) we're executing with
1569 			 * respect to the given domain.
1570 			 */
1571 	idn_fin_t	dfin;			/* drwlock */
1572 			/*
1573 			 * A non-zero value for dfin_sync
1574 			 * indicates that unlink of respective
1575 			 * domain does not need to be performed
1576 			 * synchronously among all the IDN
1577 			 * member domains.
1578 			 */
1579 	short		dfin_sync;		/* grwlock */
1580 			/*
1581 			 * Cookie used to determine the
1582 			 * proper context in which we're
1583 			 * receiving messages from the given
1584 			 * domain.  Assigned cookies are exchanged
1585 			 * during initial NEGO messages.
1586 			 */
1587 	ushort_t	dcookie_send;		/* drwlock */
1588 	ushort_t	dcookie_recv;		/* drwlock */
1589 	short		dcookie_err;		/* drwlock */
1590 	int		dcookie_errcnt;		/* drwlock */
1591 			/*
1592 			 * Primary target cpu for sending
1593 			 * messages.  Can change to help
1594 			 * distribute interrupts on receiving
1595 			 * side.
1596 			 */
1597 	int		dcpu;			/* drwlock */
1598 			/*
1599 			 * Used to store dcpu from a previous
1600 			 * life.  Only used when requesting
1601 			 * a RELINK with a domain we were just
1602 			 * previously linked with.  Thus, it
1603 			 * does represent a valid cpu in the
1604 			 * remote domain.
1605 			 */
1606 	int		dcpu_save;		/* drwlock */
1607 			/*
1608 			 * Used to store from which cpu the
1609 			 * last message was received.
1610 			 */
1611 	int		dcpu_last;
1612 			/*
1613 			 * Transition phase area.  This field
1614 			 * points to the proper phase structure
1615 			 * depending on what stage the given
1616 			 * domain is in.
1617 			 */
1618 	idn_xphase_t	*dxp;			/* drwlock */
1619 			/*
1620 			 * Actual synchronization object for
1621 			 * the given domain.
1622 			 */
1623 	idn_syncop_t	dsync;	/* drwlock & idn.sync.sz_mutex */
1624 			/*
1625 			 * Slab information for given domain.
1626 			 * If the local domain is a master,
1627 			 * then this field in each domain is used
1628 			 * to store which slabs have been assigned
1629 			 * to given domain.  If the local domain
1630 			 * is a slave, then this information is
1631 			 * NULL for all remote idn_domain[]
1632 			 * entries, but for local domain holds
1633 			 * those slabs assigned to local domain.
1634 			 */
1635 	smr_slab_t	*dslab;			/* dslab_rwlock */
1636 	short		dnslabs;		/* dslab_rwlock */
1637 	short		dslab_state;		/* dslab_rwlock */
1638 	krwlock_t	dslab_rwlock;
1639 			/*
1640 			 * Set of cpus belonging to domain.
1641 			 */
1642 	cpuset_t	dcpuset;		/* drwlock */
1643 
1644 	int		dncpus;			/* drwlock */
1645 			/*
1646 			 * Index into dcpumap to determine
1647 			 * which cpu to target next for
1648 			 * interrupt.  Intended to allow fair
1649 			 * distribution of interrupts on
1650 			 * remote domain.
1651 			 */
1652 	uint_t		dcpuindex;		/* drwlock */
1653 			/*
1654 			 * Quick look-up map of cpus belonging
1655 			 * to domain.  Used to select next target.
1656 			 */
1657 	uchar_t		*dcpumap;		/* drwlock */
1658 			/*
1659 			 * Non-zero indicates outstanding
1660 			 * I/O's to given domain.
1661 			 */
1662 	int		dio;			/* drwlock */
1663 	int		dioerr;			/* drwlock */
1664 			/*
1665 			 * Set when we fail to allocate a buffer
1666 			 * for a domain.  Dictates whether to
1667 			 * reclaim max buffers or not.
1668 			 */
1669 	lock_t		diowanted;
1670 			/*
1671 			 * Set when remote domain does not
1672 			 * seem to be picking up messages sent
1673 			 * to it.  Non-zero indicates we have
1674 			 * an outstanding "ping" to domain.
1675 			 */
1676 	lock_t		diocheck;		/* drwlock */
1677 	short		dslabsize;		/* drwlock */
1678 	uint_t		dmtu;			/* drwlock */
1679 
1680 	uint_t		dbufsize;		/* drwlock */
1681 	short		dnwrsize;		/* drwlock */
1682 	lock_t		dreclaim_inprogress;	/* drwlock */
1683 	uchar_t		dreclaim_index;		/* drwlock */
1684 			/*
1685 			 * The following field is primarily
1686 			 * used during CFG exchange to keep
1687 			 * track of certain per-domain information.
1688 			 */
1689 	union {					/* all - drwlock */
1690 		struct {
1691 			uint_t	_dcfgphase	: 6;
1692 			uint_t	_dcfgsnddone	: 1;
1693 			uint_t	_dcfgrcvdone	: 1;
1694 			uint_t	_dcksum		: 2;
1695 			uint_t	_dmaxnets	: 6;
1696 			uint_t	_dmboxpernet	: 9;
1697 			uint_t	_dncfgitems	: 6;
1698 			uint_t	_drecfg		: 1;
1699 			} _s;
1700 		int	_dtmp;
1701 	} _u;
1702 			/*
1703 			 * Each domain entry maintains a
1704 			 * timer queue holding timers for
1705 			 * messages outstanding to that domain.
1706 			 */
1707 	struct idn_timerq {
1708 		int		tq_cookie;	/* tq_mutex */
1709 		kmutex_t	tq_mutex;
1710 		int		tq_count;	/* tq_mutex */
1711 		idn_timer_t	*tq_queue;	/* tq_mutex */
1712 	} dtimerq;
1713 			/*
1714 			 * dawol is used to keep
1715 			 * track of AWOL details for
1716 			 * given domain when it is
1717 			 * non-responsive.
1718 			 */
1719 	struct {
1720 		int		a_count;	/* drwlock */
1721 		clock_t		a_time;		/* drwlock */
1722 		clock_t		a_last;		/* drwlock */
1723 		clock_t		a_msg;		/* drwlock */
1724 	} dawol;
1725 
1726 	struct hwconfig	{
1727 		short		dh_nboards;	/* drwlock */
1728 		short		dh_nmcadr;	/* drwlock */
1729 		boardset_t	dh_boardset;	/* drwlock */
1730 		uint_t		dh_mcadr[MAX_BOARDS];	/* drwlock */
1731 	} dhw;
1732 			/*
1733 			 * Mailbox information used to
1734 			 * send/recv messages to given domain.
1735 			 */
1736 	struct {
1737 		kmutex_t		m_mutex;
1738 		struct idn_mboxtbl	*m_tbl;		/* m_mutex */
1739 		struct idn_mainmbox	*m_send;	/* m_mutex */
1740 		struct idn_mainmbox	*m_recv;	/* m_mutex */
1741 	} dmbox;
1742 } idn_domain_t;
1743 
1744 typedef struct idn_timerq	idn_timerq_t;
1745 
1746 #define	dcfgphase	_u._s._dcfgphase
1747 #define	dcfgsnddone	_u._s._dcfgsnddone
1748 #define	dcfgrcvdone	_u._s._dcfgrcvdone
1749 #define	dcksum		_u._s._dcksum
1750 #define	dmaxnets	_u._s._dmaxnets
1751 #define	dmboxpernet	_u._s._dmboxpernet
1752 #define	dncfgitems	_u._s._dncfgitems
1753 #define	drecfg		_u._s._drecfg
1754 #define	dbindport	_u._dbindport
1755 #define	dconnected	_u._dconnected
1756 #define	dtmp		_u._dtmp
1757 
1758 #define	IDN_DLOCK_EXCL(dd)	(rw_enter(&idn_domain[dd].drwlock, RW_WRITER))
1759 #define	IDN_DLOCK_SHARED(dd)	(rw_enter(&idn_domain[dd].drwlock, RW_READER))
1760 #define	IDN_DLOCK_TRY_SHARED(dd) \
1761 				(rw_tryenter(&idn_domain[dd].drwlock, \
1762 						RW_READER))
1763 #define	IDN_DLOCK_DOWNGRADE(dd)	(rw_downgrade(&idn_domain[dd].drwlock))
1764 #define	IDN_DUNLOCK(dd)		(rw_exit(&idn_domain[dd].drwlock))
1765 #define	IDN_DLOCK_IS_EXCL(dd)	(RW_WRITE_HELD(&idn_domain[dd].drwlock))
1766 #define	IDN_DLOCK_IS_SHARED(dd)	(RW_READ_HELD(&idn_domain[dd].drwlock))
1767 #define	IDN_DLOCK_IS_HELD(dd)	(RW_LOCK_HELD(&idn_domain[dd].drwlock))
1768 
1769 #define	IDN_MBOX_LOCK(dd)	(mutex_enter(&idn_domain[dd].dmbox.m_mutex))
1770 #define	IDN_MBOX_UNLOCK(dd)	(mutex_exit(&idn_domain[dd].dmbox.m_mutex))
1771 
1772 #define	IDN_RESET_COOKIES(dd) \
1773 	(idn_domain[dd].dcookie_send = idn_domain[dd].dcookie_recv = 0)
1774 
1775 #define	DSLAB_STATE_UNKNOWN	0
1776 #define	DSLAB_STATE_LOCAL	1
1777 #define	DSLAB_STATE_REMOTE	2
1778 
1779 #define	DSLAB_READ_HELD(d)	RW_READ_HELD(&idn_domain[d].dslab_rwlock)
1780 #define	DSLAB_WRITE_HELD(d)	RW_WRITE_HELD(&idn_domain[d].dslab_rwlock)
1781 
1782 #define	DSLAB_LOCK_EXCL(d) \
1783 		rw_enter(&idn_domain[d].dslab_rwlock, RW_WRITER)
1784 #define	DSLAB_LOCK_SHARED(d) \
1785 		rw_enter(&idn_domain[d].dslab_rwlock, RW_READER)
1786 #define	DSLAB_LOCK_TRYUPGRADE(d) \
1787 		rw_tryupgrade(&idn_domain[d].dslab_rwlock)
1788 #define	DSLAB_UNLOCK(d)		rw_exit(&idn_domain[d].dslab_rwlock)
1789 
1790 /*
1791  * ---------------------------------------------------------------------
1792  * Macro to pick another target for the given domain.  This hopefully
1793  * improves performance by better distributing the SSI responsibilities
1794  * at the target domain.
1795  * ---------------------------------------------------------------------
1796  */
1797 #define	BUMP_INDEX(set, index) \
1798 	{ \
1799 		register int	p; \
1800 		for (p = (index)+1; p < NCPU; p++) \
1801 			if (CPU_IN_SET((set), p)) \
1802 				break; \
1803 		if (p >= NCPU) \
1804 			for (p = 0; p <= (index); p++) \
1805 				if (CPU_IN_SET((set), p)) \
1806 					break; \
1807 		if (!CPU_IN_SET((set), p)) { \
1808 			uint_t	_u32, _l32; \
1809 			_u32 = UPPER32_CPUMASK(set); \
1810 			_l32 = LOWER32_CPUMASK(set); \
1811 			cmn_err(CE_PANIC, \
1812 				"IDN: cpu %d not in cpuset 0x%x.%0x\n", \
1813 				p, _u32, _l32); \
1814 		} \
1815 		(index) = p; \
1816 	}
1817 
1818 #define	IDN_ASSIGN_DCPU(dp, cookie) \
1819 		((dp)->dcpu = (int)((dp)->dcpumap[(cookie) & (NCPU-1)]))
1820 
1821 /*
1822  * ---------------------------------------------------------------------
1823  * Atomic increment/decrement, swap, compare-swap functions.
1824  * ---------------------------------------------------------------------
1825  */
1826 #define	ATOMIC_INC(v)		atomic_inc_32((uint_t *)&(v))
1827 #define	ATOMIC_DEC(v)		atomic_dec_32((uint_t *)&(v))
1828 #define	ATOMIC_SUB(v, n)	atomic_add_32((uint_t *)&(v), -(n))
1829 #define	ATOMIC_CAS(a, c, n)	atomic_cas_32((uint32_t *)(a), (uint32_t)(c), \
1830 								(uint32_t)(n))
1831 #define	ATOMIC_SWAPL(a, v)	atomic_swap_32((uint32_t *)(a), (uint32_t)(v))
1832 
1833 /*
1834  * DMV vector interrupt support.
1835  *
1836  * A fixed-size circular buffer is maintained as a queue of
1837  * incoming interrupts.  The low-level idn_dmv_handler() waits
1838  * for an entry to become FREE and will atomically mark it INUSE.
1839  * Once he has filled in the appropriate fields it will be marked
1840  * as READY.  The high-level idn_handler() will be invoked and will
1841  * process all messages in the queue that are READY.  Each message
1842  * is marked PROCESS, a protojob job created and filled in, and
1843  * then the interrupt message is marked FREE for use in the next
1844  * interrupt.  The iv_state field is used to hold the relevant
1845  * state and is updated atomically.
1846  */
1847 #define	IDN_PIL			PIL_8
1848 #define	IDN_DMV_PENDING_MAX	128	/* per cpu */
1849 
1850 #endif /* !_ASM */
1851 
1852 #ifndef _ASM
1853 
1854 /*
1855  * The size of this structure must be a power of 2
1856  * so that we can do a simple shift to calculate
1857  * our offset into based on cpuid.
1858  */
1859 typedef struct idn_dmv_cpu {
1860 	uint32_t	idn_dmv_current;
1861 	int32_t		idn_dmv_lostintr;
1862 	lock_t		idn_dmv_active;
1863 	char		_padding[(2 * sizeof (uint64_t)) - \
1864 				sizeof (uint32_t) - \
1865 				sizeof (lock_t) - \
1866 				sizeof (int32_t)];
1867 } idn_dmv_cpu_t;
1868 
1869 typedef struct idn_dmv_data {
1870 	uint_t		idn_soft_inum;
1871 	uint64_t	idn_dmv_qbase;
1872 	idn_dmv_cpu_t	idn_dmv_cpu[NCPU];
1873 } idn_dmv_data_t;
1874 
1875 /*
1876  * Requirements of the following data structure:
1877  *	- MUST be double-word (8 bytes) aligned.
1878  *	- _iv_head field MUST start on double-word boundary.
1879  *	- iv_xargs0 MUST start on double-word boundary
1880  *	  with iv_xargs1 immediately following.
1881  *	- iv_xargs2 MUST start on double-word boundary
1882  *	  with iv_xargs3 immediately following.
1883  */
1884 typedef struct idn_dmv_msg {
1885 	uint32_t	iv_next;	/* offset */
1886 	uchar_t		iv_inuse;
1887 	uchar_t		iv_ready;
1888 	ushort_t	_padding;
1889 	uint32_t	iv_head	  : 16;
1890 	uint32_t	iv_cookie : 16;
1891 	uint32_t	iv_ver    : 8;
1892 	uint32_t	iv_mtype  : 6;
1893 	uint32_t	iv_atype  : 6;
1894 	uint32_t	iv_domid  : 4;
1895 	uint32_t	iv_cpuid  : 8;
1896 	uint32_t	iv_xargs0;
1897 	uint32_t	iv_xargs1;
1898 	uint32_t	iv_xargs2;
1899 	uint32_t	iv_xargs3;
1900 } idn_dmv_msg_t;
1901 
1902 extern uint_t	idn_dmv_inum;
1903 extern uint_t	idn_soft_inum;
1904 
1905 /*
1906  * An IDN-network address has the following format:
1907  *
1908  *	31......16,15........0
1909  *	| channel |  dnetid  |
1910  *	----------------------
1911  * channel	- network interface.
1912  * netid	- idn_domain[].dnetid
1913  */
1914 #define	IDN_MAXMAX_NETS		32
1915 #define	IDN_BROADCAST_ALLCHAN	((ushort_t)-1)
1916 #define	IDN_BROADCAST_ALLNETID	((ushort_t)-1)
1917 
1918 typedef union {
1919 	struct {
1920 		ushort_t	chan;
1921 		ushort_t	netid;
1922 	} net;
1923 	uint_t	netaddr;
1924 } idn_netaddr_t;
1925 
1926 #define	CHANSET_ALL	(~((idn_chanset_t)0))
1927 #define	CHANSET(c) \
1928 		((idn_chanset_t)1 << ((c) & 31))
1929 #define	CHAN_IN_SET(m, c) \
1930 		(((m) & ((idn_chanset_t)1 << ((c) & 31))) != 0)
1931 #define	CHANSET_ADD(m, c) \
1932 		((m) |= ((idn_chanset_t)1 << ((c) & 31)))
1933 #define	CHANSET_DEL(m, c) \
1934 		((m) &= ~((idn_chanset_t)1 << ((c) & 31)))
1935 #define	CHANSET_ZERO(m)	((m) = 0)
1936 
1937 typedef enum {
1938 /*  0 */	IDNCHAN_OPEN,
1939 /*  1 */	IDNCHAN_SOFT_CLOSE,
1940 /*  2 */	IDNCHAN_HARD_CLOSE,
1941 /*  3 */	IDNCHAN_OFFLINE,
1942 /*  4 */	IDNCHAN_ONLINE
1943 } idn_chanop_t;
1944 
1945 /*
1946  * Retry support.
1947  */
1948 #define	IDN_RETRY_TOKEN(d, x)		((((d) & 0xf) << 16) | \
1949 					(0xffff & (uint_t)(x)))
1950 #define	IDN_RETRY_TOKEN2DOMID(t)	((int)(((t) >> 16) & 0xf))
1951 #define	IDN_RETRY_TOKEN2TYPE(t)		((idn_retry_t)((t) & 0xffff))
1952 #define	IDN_RETRY_TYPEALL		((idn_retry_t)0xffff)
1953 #define	IDN_RETRY_INTERVAL		hz	/* 1 sec */
1954 #define	IDN_RETRY_RECFG_MULTIPLE	10
1955 
1956 #define	IDN_RETRYINTERVAL_NEGO		(2 * hz)
1957 #define	IDN_RETRYINTERVAL_CON		(2 * hz)
1958 #define	IDN_RETRYINTERVAL_FIN		(2 * hz)
1959 
1960 typedef struct idn_retry_job {
1961 	struct idn_retry_job	*rj_prev;
1962 	struct idn_retry_job	*rj_next;
1963 	void			(*rj_func)(uint_t token, void *arg);
1964 	void			*rj_arg;
1965 	uint_t			rj_token;
1966 	short			rj_onq;
1967 	timeout_id_t		rj_id;
1968 } idn_retry_job_t;
1969 
1970 #define	IDNRETRY_ALLOCJOB() \
1971 	((idn_retry_job_t *)kmem_cache_alloc(idn.retryqueue.rq_cache, KM_SLEEP))
1972 #define	IDNRETRY_FREEJOB(j) \
1973 	(kmem_cache_free(idn.retryqueue.rq_cache, (void *)(j)))
1974 
1975 typedef enum {
1976 /*  0 */	IDNRETRY_NIL = 0,
1977 /*  1 */	IDNRETRY_NEGO,
1978 /*  2 */	IDNRETRY_CON,
1979 /*  3 */	IDNRETRY_CONQ,		/* for CON queries */
1980 /*  4 */	IDNRETRY_FIN,
1981 /*  5 */	IDNRETRY_FINQ,		/* for FIN queries */
1982 /*  6 */	IDN_NUM_RETRYTYPES
1983 } idn_retry_t;
1984 
1985 /*
1986  * ---------------------------------------------------------------------
1987  */
1988 typedef struct {
1989 	int		m_domid;
1990 	int		m_cpuid;
1991 	ushort_t	m_msgtype;
1992 	ushort_t	m_acktype;
1993 	ushort_t	m_cookie;
1994 	idn_xdcargs_t	m_xargs;
1995 } idn_protomsg_t;
1996 
1997 typedef struct idn_protojob {
1998 	struct idn_protojob	*j_next;
1999 	int			j_cache;
2000 	idn_protomsg_t		j_msg;
2001 } idn_protojob_t;
2002 
2003 typedef struct idn_protoqueue {
2004 	struct idn_protoqueue	*q_next;
2005 	idn_protojob_t		*q_joblist;
2006 	idn_protojob_t		*q_joblist_tail;
2007 	int			q_die;
2008 	int			q_id;
2009 	ksema_t			*q_morgue;
2010 	kthread_id_t		q_threadp;
2011 	kcondvar_t		q_cv;
2012 	kmutex_t		q_mutex;
2013 } idn_protoqueue_t;
2014 
2015 #define	IDN_PROTOCOL_NSERVERS		4
2016 #define	IDN_PROTOCOL_SERVER_HASH(d)	((d) % idn.nservers)
2017 #define	IDN_PROTOJOB_CHUNKS		(idn.nservers)
2018 
2019 /*
2020  * ---------------------------------------------------------------------
2021  * Data Server definitions.
2022  *
2023  *	idn_datasvr_t 	- Describes data server thread.
2024  *	. ds_id			- Per-domain identifier for data server.
2025  *	. ds_domid		- Domain which data server is handling.
2026  *	. ds_state		- Flag to enable/disable/terminate
2027  *				  data server.
2028  *	. ds_mboxp		- Pointer to data server's (local)
2029  *				  mailbox to be serviced.
2030  *	. ds_waittime		- cv_timedwait sleep time before
2031  *				  checking respective mailbox.
2032  *	. ds_threadp		- Pointer to data server thread.
2033  *	. ds_cv			- Condvar for sleeping.
2034  *	. ds_morguep		- Semaphore for terminating thread.
2035  *
2036  *	idn_mboxhdr_t	- Resides in SMR space (MUST be cache_linesize).
2037  *	. mh_svr_active		- Non-zero indicates data server is
2038  *				  actively reading mailbox for messages.
2039  *	. mh_svr_ready		- Non-zero indicates data server has
2040  *				  allocated and is ready to accept data.
2041  *	. mh_cookie		- Identifier primarily for debug purposes.
2042  *
2043  *	idn_mboxmsg_t	- Entry in the SMR space circular queue use to
2044  *			  represent a data packet.
2045  *	. mm_owner		- Non-zero indicates entry is available
2046  *				  to be processed by receiver's data server.
2047  *	. mm_flag		- Indicates whether entry needs to be
2048  *				  reclaimed by the sender.  Also holds error
2049  *				  indications (e.g. bad offset).
2050  *	. mm_offset		- SMR offset of respective data packet.
2051  *
2052  *	idn_mboxtbl_t	- Encapsulation of a per-domain mailbox (SMR space).
2053  *	. mt_header		- Header information for synchronization.
2054  *	. mt_queue		- Circular queue of idn_mboxmsg_t entries.
2055  *
2056  *	idn_mainmbox_t	- Encapsulation of main SMR recv/send mailboxes.
2057  *	. mm_mutex		- Protects mm_* entries, enqueuing, and
2058  *				  dequeuing of messages.  Also protects
2059  *				  updates to the route table pointed to
2060  *				  by mm_routetbl.
2061  *	. mm_count		- send: Current number of messages
2062  *					enqueued.
2063  *				- recv: Cumulative number of messages
2064  *					processed.
2065  *	. mm_max_count		- send: Maximum number of messages
2066  *					enqueued per iteration.
2067  *				  recv: Maximum number of messages
2068  *					dequeued per iteration.
2069  *	. mm_smr_mboxp		- Pointer to SMR (vaddr) space where
2070  *				  respective mailbox resides.
2071  * ---------------------------------------------------------------------
2072  */
2073 #define	IDN_MBOXHDR_COOKIE_TOP		((uint_t)0xc0c0)
2074 #define	IDN_MAKE_MBOXHDR_COOKIE(pd, sd, ch) \
2075 				((IDN_MBOXHDR_COOKIE_TOP << 16) \
2076 				| (((uint_t)(pd) & 0xf) << 12) \
2077 				| (((uint_t)(sd) & 0xf) << 8) \
2078 				| ((uint_t)(ch) & 0xf))
2079 #define	IDN_GET_MBOXHDR_COOKIE(mhp) \
2080 				((mhp)->mh_cookie & ~0xff00)
2081 #define	VALID_MBOXHDR(mhp, ch, cksum) \
2082 	((IDN_GET_MBOXHDR_COOKIE(mhp) == \
2083 			IDN_MAKE_MBOXHDR_COOKIE(0, 0, (ch))) && \
2084 	((cksum) == (*(mhp)).mh_cksum))
2085 /*
2086  * The number of entries in a mailbox queue must be chosen so
2087  * that (IDN_MMBOX_NUMENTRIES * sizeof (idn_mboxmsg_t)) is a multiple
2088  * of a cacheline size (64).
2089  */
2090 #define	IDN_MMBOX_NUMENTRIES		IDN_MBOX_PER_NET
2091 /*
2092  * We step through the mailboxes in effectively cacheline size
2093  * incremenents so that the source and receiving cpus are not competing
2094  * for the same cacheline when transmitting/receiving messages into/from
2095  * the mailboxes.  The hard requirement is that the step value be even
2096  * since the mailbox size will be chosen odd.  This allows us to wraparound
2097  * the mailbox uniquely touching each entry until we've exhausted them
2098  * all at which point we'll end up where we initially started and repeat
2099  * again.
2100  */
2101 #define	IDN_MMBOXINDEX_STEP	(((64 / sizeof (idn_mboxmsg_t)) + 1) & 0xfffe)
2102 #define	IDN_MMBOXINDEX_INC(i) \
2103 	{ \
2104 		if (((i) += IDN_MMBOXINDEX_STEP) >= IDN_MMBOX_NUMENTRIES) \
2105 			(i) -= IDN_MMBOX_NUMENTRIES; \
2106 	}
2107 
2108 #define	IDN_MMBOXINDEX_DIFF(i, j) \
2109 	(((i) >= (j)) ? (((i) - (j)) / IDN_MMBOXINDEX_STEP) \
2110 		: ((((i) + IDN_MMBOX_NUMENTRIES) - (j)) / IDN_MMBOXINDEX_STEP))
2111 
2112 /*
2113  * Require IDN_MBOXAREA_SIZE <= IDN_SLAB_SIZE so we don't waste
2114  * slab space.
2115  *
2116  * Each domain maintains a MAX_DOMAIN(16) entry mbox_table.  Each
2117  * entry represents a receive mailbox for a possible domain to which
2118  * the given domain may have a connection.  The send mailbox for each
2119  * respective domain is given to the local domain at the time of
2120  * connection establishment.
2121  */
2122 
2123 /*
2124  * ---------------------------------------------------------------------
2125  */
2126 #define	IDN_MBOXTBL_SIZE \
2127 	(IDNROUNDUP(((IDN_MBOX_PER_NET * sizeof (idn_mboxmsg_t)) \
2128 			+ sizeof (idn_mboxhdr_t)), IDN_ALIGNSIZE))
2129 
2130 /*
2131  * ---------------------------------------------------------------------
2132  * Each domain has idn_max_nets worth of possible mailbox tables
2133  * for each domain to which it might possibly be connected.
2134  * ---------------------------------------------------------------------
2135  */
2136 #define	IDN_MBOXAREA_SIZE \
2137 	(IDN_MBOXTBL_SIZE * IDN_MAX_NETS * MAX_DOMAINS * MAX_DOMAINS)
2138 #define	IDN_MBOXAREA_OFFSET(d) \
2139 	((d) * IDN_MBOXTBL_SIZE * IDN_MAX_NETS * MAX_DOMAINS)
2140 
2141 /*
2142  * ---------------------------------------------------------------------
2143  * Return the base of the mailbox area (set of tables) assigned
2144  * to the given domain id.
2145  * ---------------------------------------------------------------------
2146  */
2147 #define	IDN_MBOXAREA_BASE(m, d) \
2148 	((idn_mboxtbl_t *)(((ulong_t)(m)) + IDN_MBOXAREA_OFFSET(d)))
2149 
2150 /*
2151  * ---------------------------------------------------------------------
2152  * Return the pointer to the respective receive mailbox (table set)
2153  * for the given domain id relative to the given base mailbox table.
2154  * ---------------------------------------------------------------------
2155  */
2156 #define	IDN_MBOXTBL_PTR(t, d)	\
2157 	((idn_mboxtbl_t *)(((ulong_t)(t)) + ((d) * IDN_MBOXTBL_SIZE \
2158 				* IDN_MAX_NETS)))
2159 /*
2160  * ---------------------------------------------------------------------
2161  * Return the pointer to the actual target mailbox based on the
2162  * given channel in the given mailbox table.
2163  * ---------------------------------------------------------------------
2164  */
2165 #define	IDN_MBOXTBL_PTR_CHAN(t, c) \
2166 	((idn_mboxtbl_t *)(((ulong_t)(t)) + ((c) * IDN_MBOXTBL_SIZE)))
2167 
2168 #define	IDN_MBOXTBL_PTR_INC(t)	\
2169 	((t) = (idn_mboxtbl_t *)(((ulong_t)(t)) + IDN_MBOXTBL_SIZE))
2170 
2171 #define	IDN_MBOXCHAN_INC(i) \
2172 	{ \
2173 		if (++(i) == IDN_MAX_NETS) \
2174 			(i) = 0; \
2175 	}
2176 
2177 /*
2178  * ---------------------------------------------------------------------
2179  * Return the absolute location within the entire mailbox area
2180  * of the mboxtbl for the given primary and secondary domain and
2181  * channel.  Only relevant when done by the master.
2182  * ---------------------------------------------------------------------
2183  */
2184 #define	IDN_MBOXTBL_ABS_PTR(mt, pd, sd, ch) \
2185 		(IDN_MBOXTBL_PTR_CHAN( \
2186 			IDN_MBOXTBL_PTR( \
2187 				IDN_MBOXAREA_BASE((mt), (pd)), \
2188 				(sd)), \
2189 			(ch)))
2190 
2191 #define	IDN_BFRAME_SHIFT	idn.bframe_shift
2192 #define	IDN_BFRAME2OFFSET(bf)	((bf) << IDN_BFRAME_SHIFT)
2193 #define	IDN_BFRAME2ADDR(bf)	IDN_OFFSET2ADDR(IDN_BFRAME2OFFSET(bf))
2194 #define	IDN_OFFSET2BFRAME(off)	(((off) >> IDN_BFRAME_SHIFT) & 0xffffff)
2195 #define	IDN_ADDR2BFRAME(addr)	IDN_OFFSET2BFRAME(IDN_ADDR2OFFSET(addr))
2196 
2197 typedef struct idn_mboxmsg {
2198 	uint_t		ms_owner  : 1,
2199 			ms_flag   : 7,
2200 			ms_bframe : 24;
2201 } idn_mboxmsg_t;
2202 
2203 typedef idn_mboxmsg_t	idn_mboxq_t[1];
2204 
2205 #define	IDN_CKSUM_MBOX_COUNT	\
2206 			(((int)&((idn_mboxhdr_t *)(0))->mh_svr_ready) / 2)
2207 #define	IDN_CKSUM_MBOX(h)	\
2208 			(IDN_CHECKSUM ? \
2209 			idn_cksum((ushort_t *)(h), IDN_CKSUM_MBOX_COUNT) : 0)
2210 
2211 typedef struct idn_mboxhdr {
2212 	uint_t		mh_cookie;
2213 	uint_t		mh_svr_ready_ptr;
2214 	uint_t		mh_svr_active_ptr;
2215 	ushort_t	mh_svr_ready;
2216 	ushort_t	mh_svr_active;
2217 
2218 	uint_t		_padding[(64 -
2219 				(4*sizeof (uint_t)) -
2220 				(2*sizeof (ushort_t))) / sizeof (uint_t)];
2221 
2222 	uint_t		mh_cksum;
2223 } idn_mboxhdr_t;
2224 
2225 typedef struct idn_mboxtbl {
2226 	idn_mboxhdr_t	mt_header;
2227 	idn_mboxq_t	mt_queue;
2228 } idn_mboxtbl_t;
2229 
2230 #define	IDN_CHAN_DOMAIN_REGISTER(csp, dom) \
2231 	(DOMAINSET_ADD((csp)->ch_reg_domset, (dom)))
2232 
2233 #define	IDN_CHAN_DOMAIN_UNREGISTER(csp, dom) \
2234 	(DOMAINSET_DEL((csp)->ch_reg_domset, (dom)))
2235 
2236 #define	IDN_CHAN_DOMAIN_IS_REGISTERED(csp, dom) \
2237 	(DOMAIN_IN_SET((csp)->ch_reg_domset, (dom)))
2238 
2239 #define	IDN_CHANSVR_SCANSET_ADD_PENDING(csp, dom) \
2240 	{ \
2241 		register int _d; \
2242 		register uint64_t _domset; \
2243 		(dom) &= MAX_DOMAINS - 1;   	/* Assumes power of 2 */ \
2244 		_domset = 0ull; \
2245 		for (_d = 0; _d < (csp)->ch_recv_domcount; _d++) { \
2246 			if ((int)(((csp)->ch_recv_scanset_pending >> \
2247 						(_d * 4)) & 0xf) == (dom)) \
2248 				break; \
2249 			else \
2250 				_domset = (_domset << 4) | 0xfull; \
2251 		} \
2252 		if (_d == (csp)->ch_recv_domcount) { \
2253 			_domset &= (csp)->ch_recv_scanset_pending; \
2254 			_domset |= (uint64_t)(dom) << \
2255 					((csp)->ch_recv_domcount * 4); \
2256 			(csp)->ch_recv_domcount++; \
2257 			(csp)->ch_recv_scanset_pending = 0ull; \
2258 			for (_d = 0; _d < 16; \
2259 					_d += (csp)->ch_recv_domcount) { \
2260 				(csp)->ch_recv_scanset_pending |= _domset; \
2261 				_domset <<= (csp)->ch_recv_domcount * 4; \
2262 			} \
2263 		} \
2264 	}
2265 #define	IDN_CHANSVR_SCANSET_DEL_PENDING(csp, dom) \
2266 	{ \
2267 		register int _d; \
2268 		register uint64_t _domset; \
2269 		(dom) &= MAX_DOMAINS - 1;	/* Assumes power of 2 */ \
2270 		_domset = 0ull; \
2271 		for (_d = 0; _d < (csp)->ch_recv_domcount; _d++) { \
2272 			if ((int)(((csp)->ch_recv_scanset_pending >> \
2273 						(_d * 4)) & 0xf) == (dom)) \
2274 				break; \
2275 			else \
2276 				_domset = (_domset << 4) | 0xfull; \
2277 		} \
2278 		if (_d < (csp)->ch_recv_domcount) { \
2279 			_domset &= (csp)->ch_recv_scanset_pending; \
2280 			(csp)->ch_recv_scanset_pending >>= 4; \
2281 			(csp)->ch_recv_domcount--; \
2282 			for (; _d < (csp)->ch_recv_domcount; _d++) \
2283 				_domset |= (csp)->ch_recv_scanset_pending &\
2284 						(0xfull << (_d * 4)); \
2285 			(csp)->ch_recv_scanset_pending = 0ull; \
2286 			if ((csp)->ch_recv_domcount) { \
2287 				for (_d = 0; _d < 16; \
2288 					_d += (csp)->ch_recv_domcount) { \
2289 					(csp)->ch_recv_scanset_pending |= \
2290 						_domset; \
2291 					_domset <<= \
2292 						(csp)->ch_recv_domcount * 4; \
2293 				} \
2294 			} \
2295 		} \
2296 	}
2297 
2298 #define	IDN_CHAN_TRYLOCK_GLOBAL(csp)	\
2299 		mutex_tryenter(&(csp)->ch_mutex)
2300 #define	IDN_CHAN_LOCK_GLOBAL(csp)	\
2301 		mutex_enter(&(csp)->ch_mutex)
2302 #define	IDN_CHAN_UNLOCK_GLOBAL(csp)	\
2303 		mutex_exit(&(csp)->ch_mutex)
2304 #define	IDN_CHAN_GLOBAL_IS_LOCKED(csp)	\
2305 		(MUTEX_HELD(&(csp)->ch_mutex))
2306 
2307 #define	IDN_CHAN_LOCAL_IS_LOCKED(csp)	\
2308 		(MUTEX_HELD(&(csp)->ch_send.c_mutex) && \
2309 		MUTEX_HELD(&(csp)->ch_recv.c_mutex))
2310 #define	IDN_CHAN_LOCK_LOCAL(csp)	\
2311 		(mutex_enter(&(csp)->ch_recv.c_mutex, \
2312 		mutex_enter(&(csp)->ch_send.c_mutex))
2313 #define	IDN_CHAN_UNLOCK_LOCAL(csp) 	\
2314 		(mutex_exit(&(csp)->ch_send.c_mutex), \
2315 		mutex_exit(&(csp)->ch_recv.c_mutex))
2316 
2317 #define	IDN_CHAN_RECV_IS_LOCKED(csp)	\
2318 		(MUTEX_HELD(&(csp)->ch_recv.c_mutex))
2319 #define	IDN_CHAN_TRYLOCK_RECV(csp) 	\
2320 		(mutex_tryenter(&(csp)->ch_recv.c_mutex))
2321 #define	IDN_CHAN_LOCK_RECV(csp) 	\
2322 		(mutex_enter(&(csp)->ch_recv.c_mutex))
2323 #define	IDN_CHAN_UNLOCK_RECV(csp) 	\
2324 		(mutex_exit(&(csp)->ch_recv.c_mutex))
2325 
2326 #define	IDN_CHAN_SEND_IS_LOCKED(csp)	\
2327 		(MUTEX_HELD(&(csp)->ch_send.c_mutex))
2328 #define	IDN_CHAN_TRYLOCK_SEND(csp) 	\
2329 		(mutex_tryenter(&(csp)->ch_send.c_mutex))
2330 #define	IDN_CHAN_LOCK_SEND(csp) 	\
2331 		(mutex_enter(&(csp)->ch_send.c_mutex))
2332 #define	IDN_CHAN_UNLOCK_SEND(csp) 	\
2333 		(mutex_exit(&(csp)->ch_send.c_mutex))
2334 
2335 /*
2336  * A channel table is an array of pointers to mailboxes
2337  * for the respective domains for the given channel.
2338  * Used a cache for the frequently used items.  Respective
2339  * fields in mainmbox are updated just prior to sleeping.
2340  */
2341 
2342 /*
2343  * Reading c_state requires either c_mutex or ch_mutex.
2344  * Writing c_state requires both c_mutex and ch_mutex in the order:
2345  *	ch_mutex
2346  *	c_mutex
2347  */
2348 typedef struct idn_chaninfo {
2349 	kmutex_t	c_mutex;
2350 	uchar_t		c_state;	/* protected by c_mutex */
2351 	uchar_t		c_checkin;	/* asynchronous flag */
2352 	kcondvar_t	c_cv;
2353 	ushort_t	c_waiters;	/* protected by c_mutex */
2354 	ushort_t	c_inprogress;	/* protected by c_mutex */
2355 } idn_chaninfo_t;
2356 
2357 /*
2358  * Reading/Writing ch_state requires ch_mutex.
2359  * When updating both recv and send c_state's for the locks
2360  * must be grabbed in the following order:
2361  *	ch_mutex
2362  *	ch_recv.c_mutex
2363  *	ch_send.c_mutex
2364  * This order is necessary to prevent deadlocks.
2365  * In general ch_state is intended to represent c_state of
2366  * individual send/recv sides.  During state transitions the
2367  * ch_state and c_state values may be slightly different,
2368  * but eventually should end up identical.
2369  */
2370 typedef struct idn_chansvr {
2371 	uchar_t		ch_id;
2372 	uchar_t		ch_state;	/* protected by ch_mutex */
2373 	lock_t		ch_initlck;
2374 	lock_t		ch_actvlck;
2375 	domainset_t	ch_reg_domset;
2376 	kmutex_t	ch_mutex;
2377 
2378 	idn_chaninfo_t	ch_send;
2379 	int		_padding2[(64 -
2380 				(2*sizeof (uchar_t)) - (2*sizeof (lock_t)) -
2381 				sizeof (uint_t) - sizeof (kmutex_t) -
2382 				sizeof (idn_chaninfo_t)) / sizeof (int)];
2383 
2384 	idn_chaninfo_t	ch_recv;
2385 
2386 	uint64_t	ch_recv_scanset;
2387 	uint64_t	ch_recv_scanset_pending;
2388 
2389 	domainset_t	ch_recv_domset;
2390 	domainset_t	ch_recv_domset_pending;
2391 	short		ch_recv_domcount;
2392 	kcondvar_t	ch_recv_cv;
2393 	int		ch_recv_waittime;
2394 	int		ch_recv_changed;
2395 
2396 	kthread_id_t	ch_recv_threadp;
2397 	ksema_t		*ch_recv_morguep;
2398 	int		ch_bound_cpuid;
2399 	int		ch_bound_cpuid_pending;
2400 } idn_chansvr_t;
2401 
2402 typedef struct idn_mainmbox {
2403 	kmutex_t	mm_mutex;
2404 	short		mm_channel;
2405 	short		mm_domid;
2406 	ushort_t	mm_flags;
2407 	short		mm_type;
2408 
2409 	idn_chansvr_t	*mm_csp;	/* non-NULL indicates reg'd */
2410 	int		mm_count;
2411 	int		mm_dropped;
2412 	idn_mboxtbl_t	*mm_smr_mboxp;		/* SMR vaddr */
2413 
2414 	ushort_t	*mm_smr_activep;	/* SMR pointer */
2415 	ushort_t	*mm_smr_readyp;		/* SMR pointer */
2416 	int		mm_qiget;	/* next msg to get */
2417 	int		mm_qiput;	/* next slot to put msg */
2418 } idn_mainmbox_t;
2419 
2420 /*
2421  * mm_flags
2422  */
2423 #define	IDNMMBOX_FLAG_CORRUPTED		0x01
2424 /*
2425  * mm_type
2426  */
2427 #define	IDNMMBOX_TYPE_RECV		0x1
2428 #define	IDNMMBOX_TYPE_SEND		0x2
2429 
2430 #define	IDNMBOX_IS_RECV(m)	((m) == IDNMMBOX_TYPE_RECV)
2431 #define	IDNMBOX_IS_SEND(m)	((m) == IDNMMBOX_TYPE_SEND)
2432 
2433 /*
2434  * Period between sending wakeup xdc's to remote domain.
2435  */
2436 #define	IDN_CHANNEL_WAKEUP_PERIOD	(hz >> 1)
2437 /*
2438  * ms_flag bit values.
2439  */
2440 #define	IDN_MBOXMSG_FLAG_RECLAIM	0x1	/* needs to be reclaimed */
2441 #define	IDN_MBOXMSG_FLAG_INPROCESS	0x2
2442 #define	IDN_MBOXMSG_FLAG_ERR_BADOFFSET	0x4
2443 #define	IDN_MBOXMSG_FLAG_ERR_NOMBOX	0x8
2444 #define	IDN_MBOXMSG_FLAG_ERRMASK	0xc
2445 /*
2446  * ch_state/c_state bit values.
2447  */
2448 #define	IDN_CHANSVC_STATE_ATTACHED	0x01
2449 #define	IDN_CHANSVC_STATE_ENABLED	0x02
2450 #define	IDN_CHANSVC_STATE_ACTIVE	0x04
2451 #define	IDN_CHANSVC_STATE_FLUSH		0x10
2452 #define	IDN_CHANSVC_STATE_CORRUPTED	0x20
2453 #define	IDN_CHANSVC_STATE_MASK		0x07	/* ATTACHED/ENABLED/ACTIVE */
2454 
2455 #define	IDN_CHANSVC_PENDING_BITS	(IDN_CHANSVC_STATE_ATTACHED | \
2456 					IDN_CHANSVC_STATE_ENABLED)
2457 
2458 /*
2459  * GLOBAL
2460  */
2461 #define	IDN_CHANNEL_IS_ATTACHED(csp)	\
2462 		((csp)->ch_state & IDN_CHANSVC_STATE_ATTACHED)
2463 #define	IDN_CHANNEL_IS_DETACHED(csp)	\
2464 		(!IDN_CHANNEL_IS_ATTACHED(csp))
2465 #define	IDN_CHANNEL_IS_PENDING(csp)	\
2466 		(((csp)->ch_state & IDN_CHANSVC_STATE_MASK) == \
2467 			IDN_CHANSVC_PENDING_BITS)
2468 #define	IDN_CHANNEL_IS_ACTIVE(csp)	\
2469 		((csp)->ch_state & IDN_CHANSVC_STATE_ACTIVE)
2470 #define	IDN_CHANNEL_IS_ENABLED(csp)	\
2471 		((csp)->ch_state & IDN_CHANSVC_STATE_ENABLED)
2472 /*
2473  * SEND
2474  */
2475 #define	IDN_CHANNEL_IS_SEND_ACTIVE(csp)	\
2476 		((csp)->ch_send.c_state & IDN_CHANSVC_STATE_ACTIVE)
2477 /*
2478  * RECV
2479  */
2480 #define	IDN_CHANNEL_IS_RECV_ACTIVE(csp)	\
2481 		((csp)->ch_recv.c_state & IDN_CHANSVC_STATE_ACTIVE)
2482 #define	IDN_CHANNEL_IS_RECV_CORRUPTED(csp) \
2483 		((csp)->ch_recv.c_state & IDN_CHANSVC_STATE_CORRUPTED)
2484 
2485 
2486 #define	IDN_CHAN_SEND_INPROGRESS(csp)	((csp)->ch_send.c_inprogress++)
2487 #define	IDN_CHAN_SEND_DONE(csp) \
2488 	{ \
2489 		ASSERT((csp)->ch_send.c_inprogress > 0); \
2490 		if ((--((csp)->ch_send.c_inprogress) == 0) && \
2491 					((csp)->ch_send.c_waiters != 0)) \
2492 			cv_broadcast(&(csp)->ch_send.c_cv); \
2493 	}
2494 #define	IDN_CHAN_RECV_INPROGRESS(csp)	((csp)->ch_recv.c_inprogress++)
2495 #define	IDN_CHAN_RECV_DONE(csp) \
2496 	{ \
2497 		ASSERT((csp)->ch_recv.c_inprogress > 0); \
2498 		if ((--((csp)->ch_recv.c_inprogress) == 0) && \
2499 					((csp)->ch_recv.c_waiters != 0)) \
2500 			cv_broadcast(&(csp)->ch_recv.c_cv); \
2501 	}
2502 
2503 #define	IDN_CHANSVC_MARK_ATTACHED(csp)	\
2504 		((csp)->ch_state = IDN_CHANSVC_STATE_ATTACHED)
2505 #define	IDN_CHANSVC_MARK_DETACHED(csp)	\
2506 		((csp)->ch_state = 0)
2507 #define	IDN_CHANSVC_MARK_PENDING(csp)	\
2508 		((csp)->ch_state |= IDN_CHANSVC_STATE_ENABLED)
2509 #define	IDN_CHANSVC_MARK_DISABLED(csp)	\
2510 		((csp)->ch_state &= ~IDN_CHANSVC_STATE_ENABLED)
2511 #define	IDN_CHANSVC_MARK_ACTIVE(csp)	\
2512 		((csp)->ch_state |= IDN_CHANSVC_STATE_ACTIVE)
2513 #define	IDN_CHANSVC_MARK_IDLE(csp)	\
2514 		((csp)->ch_state &= ~IDN_CHANSVC_STATE_ACTIVE)
2515 
2516 #define	IDN_CHANSVC_MARK_RECV_ACTIVE(csp)	\
2517 		((csp)->ch_recv.c_state |= IDN_CHANSVC_STATE_ACTIVE)
2518 #define	IDN_CHANSVC_MARK_RECV_CORRUPTED(csp)	\
2519 		((csp)->ch_recv.c_state |= IDN_CHANSVC_STATE_CORRUPTED)
2520 #define	IDN_CHANSVC_MARK_SEND_ACTIVE(csp)	\
2521 		((csp)->ch_send.c_state |= IDN_CHANSVC_STATE_ACTIVE)
2522 
2523 typedef enum {
2524 	IDNCHAN_ACTION_DETACH,		/* DETACH (ATTACHED = 0) */
2525 	IDNCHAN_ACTION_STOP,		/* DISABLE (ENABLED = 0) */
2526 	IDNCHAN_ACTION_SUSPEND,		/* IDLE (ACTIVE = 0) */
2527 	IDNCHAN_ACTION_RESUME,
2528 	IDNCHAN_ACTION_RESTART,
2529 	IDNCHAN_ACTION_ATTACH
2530 } idn_chanaction_t;
2531 
2532 #define	IDN_CHANNEL_SUSPEND(c, w)	\
2533 		(idn_chan_action((c), IDNCHAN_ACTION_SUSPEND, (w)))
2534 #define	IDN_CHANNEL_RESUME(c)		\
2535 		(idn_chan_action((c), IDNCHAN_ACTION_RESUME, 0))
2536 #define	IDN_CHANNEL_STOP(c, w)	\
2537 		(idn_chan_action((c), IDNCHAN_ACTION_STOP, (w)))
2538 #define	IDN_CHANNEL_RESTART(c)		\
2539 		(idn_chan_action((c), IDNCHAN_ACTION_RESTART, 0))
2540 #define	IDN_CHANNEL_DETACH(c, w)	\
2541 		(idn_chan_action((c), IDNCHAN_ACTION_DETACH, (w)))
2542 #define	IDN_CHANNEL_ATTACH(c)		\
2543 		(idn_chan_action((c), IDNCHAN_ACTION_ATTACH, 0))
2544 
2545 /*
2546  * ds_waittime range values.
2547  * When a packet arrives the waittime starts at MIN and gradually
2548  * shifts up to MAX until another packet arrives.  If still no
2549  * packet arrives then we go to a hard sleep
2550  */
2551 #define	IDN_NETSVR_SPIN_COUNT		idn_netsvr_spin_count
2552 #define	IDN_NETSVR_WAIT_MIN		idn_netsvr_wait_min
2553 #define	IDN_NETSVR_WAIT_MAX		idn_netsvr_wait_max
2554 #define	IDN_NETSVR_WAIT_SHIFT		idn_netsvr_wait_shift
2555 
2556 /*
2557  * ---------------------------------------------------------------------
2558  * IDN Global Data
2559  *
2560  * The comment to the right of the respective field represents
2561  * what lock protects that field.  If there is no comment then
2562  * no lock is required to access the field.
2563  * ---------------------------------------------------------------------
2564  */
2565 typedef struct idn_global {				/* protected by... */
2566 	krwlock_t	grwlock;
2567 			/*
2568 			 * Global state of IDN w.r.t.
2569 			 * the local domain.
2570 			 */
2571 	idn_gstate_t	state;			/* grwlock */
2572 			/*
2573 			 * Version of the IDN driver.
2574 			 * Is passed in DMV header so that
2575 			 * other domains can validate they
2576 			 * support protocol used by local
2577 			 * domain.
2578 			 */
2579 	int		version;
2580 			/*
2581 			 * Set to 1 if SMR region properly
2582 			 * allocated and available.
2583 			 */
2584 	int		enabled;
2585 			/*
2586 			 * Local domains "domain id".
2587 			 */
2588 	int		localid;
2589 			/*
2590 			 * Domain id of the Master domain.
2591 			 * Set to IDN_NIL_DOMID if none
2592 			 * currently exists.
2593 			 */
2594 	int		masterid;		/* grwlock */
2595 			/*
2596 			 * Primarily used during Reconfiguration
2597 			 * to track the expected new Master.
2598 			 * Once the current IDN is dismantled
2599 			 * the local domain will attempt to
2600 			 * connect to this new domain.
2601 			 */
2602 	int		new_masterid;		/* grwlock */
2603 			/*
2604 			 * Number of protocol servers configured.
2605 			 */
2606 	int		nservers;
2607 
2608 	dev_info_t	*dip;
2609 
2610 	struct {
2611 		/*
2612 		 * dmv_inum
2613 		 *	Interrupt number assigned by
2614 		 *	DMV subsystem to IDN's DMV
2615 		 *	handler.
2616 		 * soft_inum
2617 		 *	Soft interrupt number assigned
2618 		 *	by OS (add_softintr) for Soft
2619 		 *	interrupt dispatched by DMV
2620 		 *	handler.
2621 		 */
2622 		uint_t	dmv_inum;
2623 		uint_t	soft_inum;
2624 		caddr_t	dmv_data;
2625 		size_t	dmv_data_len;
2626 	} intr;
2627 			/*
2628 			 * first_swlink
2629 			 *	Used as synchronization to
2630 			 *	know whether channels need
2631 			 *	to be activated or not.
2632 			 * first_hwlink
2633 			 *	Used as mechanism to determine
2634 			 *	whether local domain needs
2635 			 *	to publicize its SMR, assuming
2636 			 *	it is the Master.
2637 			 * first_hwmaster
2638 			 *	Domainid of the domain that
2639 			 *	was the master at the time
2640 			 * 	the hardware was programmed.
2641 			 *	We need to keep this so that
2642 			 *	we deprogram with respect to
2643 			 *	the correct domain that the
2644 			 *	hardware was originally
2645 			 *	programmed to.
2646 			 */
2647 	lock_t		first_swlink;
2648 	lock_t		first_hwlink;
2649 	short		first_hwmasterid;
2650 			/*
2651 			 * The xmit* fields are used to set-up a background
2652 			 * thread to monitor when a channel is ready to be
2653 			 * enabled again.  This is necessary since IDN
2654 			 * can't rely on hardware to interrupt it when
2655 			 * things are ready to go.  We need this ability
2656 			 * to wakeup our STREAMS queues.
2657 			 * Criteria for reenabling queues.
2658 			 *	gstate == IDNGS_ONLINE
2659 			 *	channel = !check-in
2660 			 *	buffers are available
2661 			 *
2662 			 * xmit_chanset_wanted
2663 			 *	Indicates which channels wish to have
2664 			 *	their queues reenabled when ready.
2665 			 * xmit_tid
2666 			 *	Timeout-id of monitor.
2667 			 */
2668 	kmutex_t	xmit_lock;
2669 	idn_chanset_t	xmit_chanset_wanted;	/* xmit_lock */
2670 	timeout_id_t	xmit_tid;		/* xmit_lock */
2671 
2672 	struct {
2673 		/*
2674 		 * ready
2675 		 *	Indicates SMR region allocated
2676 		 *	and available from OBP.
2677 		 * vaddr
2678 		 *	Virtual address assigned to SMR.
2679 		 * locpfn
2680 		 *	Page Frame Number associated
2681 		 *	with local domain's SMR.
2682 		 * rempfn
2683 		 *	Page Frame Number associated
2684 		 *	with remote (Master) domain's SMR.
2685 		 * rempfnlim
2686 		 *	PFN past end of remote domain's
2687 		 *	SMR.
2688 		 * prom_paddr/prom_size
2689 		 *	Physical address and size of
2690 		 *	SMR that were assigned by OBP.
2691 		 */
2692 		int		ready;
2693 		caddr_t		vaddr;
2694 		pfn_t		locpfn;
2695 		pfn_t		rempfn;		/* grwlock */
2696 
2697 		pfn_t		rempfnlim;	/* grwlock */
2698 		uint64_t	prom_paddr;
2699 
2700 		uint64_t	prom_size;
2701 	} smr;
2702 
2703 			/*
2704 			 * idnsb_mutex
2705 			 *	Protects access to IDN's
2706 			 *	sigblock area.
2707 			 * idnsb_eventp
2708 			 *	IDN's private area in sigblock
2709 			 *	used for signaling events
2710 			 *	regarding IDN state to SSP.
2711 			 * idnsb
2712 			 *	Area within IDN's private
2713 			 *	sigblock area used for tracking
2714 			 *	certain IDN state which might
2715 			 *	be useful during arbstop
2716 			 *	conditions (if caused by IDN!).
2717 			 */
2718 	kmutex_t	idnsb_mutex;
2719 	idnsb_event_t	*idnsb_eventp;
2720 	idnsb_t		*idnsb;
2721 
2722 	struct sigbintr {
2723 		/*
2724 		 * sb_mutex
2725 		 *	Protects sigbintr elements
2726 		 *	to synchronize execution of
2727 		 *	sigblock (IDN) mailbox handling.
2728 		 * sb_cpuid
2729 		 *	Cpu whose sigblock mailbox
2730 		 *	originally received IDN request
2731 		 *	from SSP.  Necessary to know
2732 		 *	where to put response.
2733 		 * sb_busy
2734 		 *	Flag indicating state of
2735 		 *	sigblock handler thread.
2736 		 *	Synchronize activity between
2737 		 *	SSP and current IDN requests that
2738 		 *	are in progress.
2739 		 * sb_cv
2740 		 *	Condition variable for sigblock
2741 		 *	handler thread to wait on.
2742 		 * sb_inum
2743 		 *	Soft interrupt number assigned
2744 		 *	by OS to handle soft interrupt
2745 		 *	request make by low-level (IDN)
2746 		 *	sigblock handler to dispatch actual
2747 		 *	processing of sigblock (mailbox)
2748 		 *	request.
2749 		 */
2750 		kmutex_t	sb_mutex;
2751 		uchar_t		sb_cpuid;	/* sigbintr.sb_mutex */
2752 		uchar_t		sb_busy;	/* sigbintr.sb_mutex */
2753 		kcondvar_t	sb_cv;		/* sigbintr.sb_mutex */
2754 		uint_t		sb_inum;	/* sigbintr.sb_mutex */
2755 	} sigbintr;
2756 
2757 			/*
2758 			 * struprwlock, strup, sip, siplock
2759 			 *	Standard network streams
2760 			 *	handling structures to manage
2761 			 *	instances of IDN driver.
2762 			 */
2763 	krwlock_t	struprwlock;
2764 	struct idnstr	*strup;			/* struprwlock */
2765 
2766 	struct idn	*sip;			/* siplock */
2767 	kmutex_t	sipwenlock;
2768 	kmutex_t	siplock;
2769 
2770 			/*
2771 			 * Area where IDN maintains its kstats.
2772 			 */
2773 	kstat_t		*ksp;
2774 			/*
2775 			 * Number of domains that local domain
2776 			 * has "open".
2777 			 */
2778 	int		ndomains;		/* grwlock */
2779 			/*
2780 			 * Number of domains that local domain
2781 			 * has registered as non-responsive.
2782 			 */
2783 	int		nawols;			/* grwlock */
2784 			/*
2785 			 * Number of network channels (interfaces)
2786 			 * which are currently active.
2787 			 */
2788 	int		nchannels;		/* grwlock */
2789 			/*
2790 			 * Bitmask representing channels
2791 			 * that are currently active.
2792 			 */
2793 	idn_chanset_t	chanset;		/* grwlock */
2794 			/*
2795 			 * Array of channel (network/data) servers
2796 			 * that have been created.  Not necessarily
2797 			 * all active.
2798 			 */
2799 	idn_chansvr_t	*chan_servers;		/* elmts = ch_mutex */
2800 			/*
2801 			 * Pointer to sigblock handler thread
2802 			 * which ultimately processes SSP
2803 			 * IDN requests.
2804 			 */
2805 	kthread_id_t	sigb_threadp;
2806 			/*
2807 			 * Pointer to area used by Master
2808 			 * to hold mailbox structures.
2809 			 * Actual memory is in SMR.
2810 			 */
2811 	idn_mboxtbl_t	*mboxarea;		/* grwlock */
2812 
2813 	struct {
2814 		/*
2815 		 * IDN_SYNC_LOCK - Provides serialization
2816 		 * mechanism when performing synchronous
2817 		 * operations across domains.
2818 		 */
2819 		kmutex_t	sz_mutex;
2820 		/*
2821 		 * Actual synchronization zones for
2822 		 * CONNECT/DISCONNECT phases.
2823 		 */
2824 		idn_synczone_t	sz_zone[IDN_SYNC_NUMZONE];
2825 	} sync;					/* sz_mutex */
2826 
2827 	struct {
2828 		/*
2829 		 * ds_trans_on
2830 		 *	Set of domains which are trying
2831 		 *	to establish a link w/local.
2832 		 * ds_ready_on
2833 		 *	Set of domains which local knows
2834 		 *	are ready for linking, but has
2835 		 *	not yet confirmed w/peers.
2836 		 * ds_connected
2837 		 *	Set of domains that local has
2838 		 *	confirmed as being ready.
2839 		 * ds_trans_off
2840 		 *	Set of domains which are trying
2841 		 *	to unlink from local.
2842 		 * ds_ready_off
2843 		 *	Set of domains which local knows
2844 		 *	are ready for unlink, but has
2845 		 *	not yet confirmed w/peers.
2846 		 * ds_relink
2847 		 *	Set of domains we're expecting
2848 		 *	to relink with subsequent to
2849 		 *	a RECONFIG (new master selection).
2850 		 * ds_hwlinked
2851 		 *	Set of domains for which local
2852 		 *	has programmed its hardware.
2853 		 * ds_flush
2854 		 *	Set of domains requiring that
2855 		 *	local flush its ecache prior
2856 		 *	to unlinking.
2857 		 * ds_awol
2858 		 *	Set of domains believed to be
2859 		 *	AWOL - haven't responded to
2860 		 *	any queries.
2861 		 * ds_hitlist
2862 		 *	Set of domains which local domain
2863 		 *	is unlinking from and wishes to ignore
2864 		 *	any extraneous indirect link requests
2865 		 *	from other domains, e.g. during a
2866 		 *	Reconfig.
2867 		 */
2868 		domainset_t	ds_trans_on;	/* sz_mutex */
2869 		domainset_t	ds_ready_on;	/* sz_mutex */
2870 
2871 		domainset_t	ds_connected;	/* sz_mutex */
2872 		domainset_t	ds_trans_off;	/* sz_mutex */
2873 
2874 		domainset_t	ds_ready_off;	/* sz_mutex */
2875 		domainset_t	ds_relink;	/* sz_mutex */
2876 
2877 		domainset_t	ds_hwlinked;	/* sz_mutex */
2878 		domainset_t	ds_flush;	/* sz_mutex */
2879 
2880 		domainset_t	ds_awol;	/* sz_mutex */
2881 		domainset_t	ds_hitlist;	/* sz_mutex */
2882 	} domset;
2883 			/*
2884 			 * Bitmask identifying all cpus in
2885 			 * the local IDN.
2886 			 */
2887 	cpuset_t	dc_cpuset;
2888 			/*
2889 			 * Bitmask identifying all boards in
2890 			 * the local IDN.
2891 			 */
2892 	boardset_t	dc_boardset;
2893 
2894 	struct dopers {
2895 		/*
2896 		 * Waiting area for IDN requests,
2897 		 * i.e. link & unlinks.  IDN requests
2898 		 * are performed asynchronously so
2899 		 * we need a place to wait until the
2900 		 * operation has completed.
2901 		 *
2902 		 * dop_domset
2903 		 *	Identifies which domains the
2904 		 *	current waiter is interested in.
2905 		 * dop_waitcount
2906 		 *	Number of waiters in the room.
2907 		 * dop_waitlist
2908 		 *	Actual waiting area.
2909 		 * dop_freelist
2910 		 *	Freelist (small cache) of
2911 		 *	structs for waiting area.
2912 		 */
2913 		kmutex_t	dop_mutex;
2914 		kcondvar_t	dop_cv;		/* dop_mutex */
2915 		domainset_t	dop_domset;	/* dop_mutex */
2916 		int		dop_waitcount;	/* dop_mutex */
2917 		dop_waitlist_t	*dop_waitlist;	/* dop_mutex */
2918 		dop_waitlist_t	*dop_freelist;	/* dop_mutex */
2919 							/* dop_mutex */
2920 		dop_waitlist_t	_dop_wcache[IDNOP_CACHE_SIZE];
2921 	} *dopers;
2922 
2923 	struct {
2924 		/*
2925 		 * Protocol Server:
2926 		 *
2927 		 * p_server
2928 		 *	Linked list of queues
2929 		 *	describing protocol
2930 		 *	servers in use.
2931 		 * p_jobpool
2932 		 *	Kmem cache of structs
2933 		 *	used to enqueue protocol
2934 		 *	jobs for protocol servers.
2935 		 * p_morgue
2936 		 *	Synchronization (check-in)
2937 		 *	area used when terminating
2938 		 *	protocol servers (threads).
2939 		 */
2940 		struct idn_protoqueue	*p_serverq;
2941 		kmem_cache_t		*p_jobpool;
2942 		ksema_t			p_morgue;
2943 	} protocol;
2944 
2945 	struct idn_retry_queue {
2946 		/*
2947 		 * rq_jobs
2948 		 *	Queue of Retry jobs
2949 		 *	that are outstanding.
2950 		 * rq_count
2951 		 *	Number of jobs on retry
2952 		 *	queue.
2953 		 * rq_cache
2954 		 *	Kmem cache for structs
2955 		 *	used to describe retry
2956 		 *	jobs.
2957 		 */
2958 		idn_retry_job_t	*rq_jobs;	/* rq_mutex */
2959 		int		rq_count;	/* rq_mutex */
2960 		kmutex_t	rq_mutex;	/* rq_mutex */
2961 
2962 		kcondvar_t	rq_cv;		/* rq_mutex */
2963 		kmem_cache_t	*rq_cache;
2964 	} retryqueue;
2965 
2966 	struct slabpool {
2967 		/*
2968 		 * Slabpool:
2969 		 *
2970 		 * ntotslabs
2971 		 *	Total number of slabs
2972 		 *	in SMR (free & in-use).
2973 		 * npools
2974 		 *	Number of pools available
2975 		 *	in list.  One smr_slabtbl
2976 		 *	exists for each pool.
2977 		 */
2978 		int		ntotslabs;
2979 		int		npools;
2980 		struct smr_slabtbl {
2981 			/*
2982 			 * sarray
2983 			 *	Array of slab structs
2984 			 *	representing slabs in SMR.
2985 			 * nfree
2986 			 *	Number of slabs actually
2987 			 *	available in sarray.
2988 			 * nslabs
2989 			 *	Number of slabs represented
2990 			 *	in sarray (free & in-use).
2991 			 */
2992 			smr_slab_t	*sarray;
2993 			int		nfree;
2994 			int		nslabs;
2995 		} *pool;
2996 		/*
2997 		 * Holds array of smr_slab_t structs kmem_alloc'd
2998 		 * for slabpool.
2999 		 */
3000 		smr_slab_t	*savep;
3001 	} *slabpool;
3002 
3003 	struct slabwaiter {
3004 		/*
3005 		 * Waiting area for threads
3006 		 * requesting slab allocations.
3007 		 * Used by Slaves for all requests,
3008 		 * but used by Master only for
3009 		 * redundant requests, i.e. multiple
3010 		 * requests on behalf of the same
3011 		 * domain.  One slabwaiter area
3012 		 * exist for each possible domain.
3013 		 *
3014 		 * w_nwaiters
3015 		 *	Number of threads waiting
3016 		 *	in waiting area.
3017 		 * w_done
3018 		 *	Flag to indicate that
3019 		 *	allocation request has
3020 		 *	completed.
3021 		 * w_serrno
3022 		 *	Non-zero indicates an
3023 		 *	errno value to represent
3024 		 *	error that occurred during
3025 		 *	attempt to allocate slab.
3026 		 * w_closed
3027 		 *	Indicates that waiting area is
3028 		 *	closed and won't allow any new
3029 		 *	waiters.  This occurs during
3030 		 *	the small window where we're
3031 		 *	trying to suspend a channel.
3032 		 * w_cv
3033 		 *	Condvar for waiting on.
3034 		 * w_sp
3035 		 *	Holds slab structure of
3036 		 *	successfully allocated slab.
3037 		 */
3038 		kmutex_t	w_mutex;
3039 		short		w_nwaiters;	/* w_mutex */
3040 		short		w_done;		/* w_mutex */
3041 		short		w_serrno;	/* w_mutex */
3042 		short		w_closed;	/* w_mutex */
3043 		kcondvar_t	w_cv;		/* w_mutex */
3044 		smr_slab_t	*w_sp;		/* w_mutex */
3045 	} *slabwaiter;
3046 			/*
3047 			 * Kmem cache used for allocating
3048 			 * timer structures for outstanding
3049 			 * IDN requests.
3050 			 */
3051 	kmem_cache_t	*timer_cache;
3052 			/*
3053 			 * Effectively constant used in
3054 			 * translating buffer frames in
3055 			 * mailbox message frames to
3056 			 * offsets within SMR.
3057 			 */
3058 	int		bframe_shift;
3059 } idn_global_t;
3060 
3061 typedef struct idn_retry_queue	idn_retry_queue_t;
3062 
3063 #define	IDN_GET_MASTERID()	(idn.masterid)
3064 #define	IDN_SET_MASTERID(mid) \
3065 	{ \
3066 		int	_mid = (mid); \
3067 		mutex_enter(&idn.idnsb_mutex); \
3068 		if (idn.idnsb) { \
3069 			idn.idnsb->id_pmaster_board = \
3070 					idn.idnsb->id_master_board; \
3071 			if (_mid == IDN_NIL_DOMID) \
3072 				idn.idnsb->id_master_board = (uchar_t)0xff; \
3073 			else \
3074 				idn.idnsb->id_master_board = \
3075 				(uchar_t)idn_domain[_mid].dvote.v.board; \
3076 		} \
3077 		mutex_exit(&idn.idnsb_mutex); \
3078 		IDN_HISTORY_LOG(IDNH_MASTERID, _mid, idn.masterid, 0); \
3079 		PR_STATE("%d: MASTERID %d -> %d\n", __LINE__, \
3080 			idn.masterid, _mid); \
3081 		idn.masterid = _mid; \
3082 	}
3083 #define	IDN_GET_NEW_MASTERID()	(idn.new_masterid)
3084 #define	IDN_SET_NEW_MASTERID(mid) \
3085 	{ \
3086 		PR_STATE("%d: NEW MASTERID %d -> %d\n", __LINE__, \
3087 			idn.new_masterid, (mid)); \
3088 		idn.new_masterid = (mid); \
3089 	}
3090 
3091 #define	IDN_GLOCK_EXCL()	(rw_enter(&idn.grwlock, RW_WRITER))
3092 #define	IDN_GLOCK_SHARED()	(rw_enter(&idn.grwlock, RW_READER))
3093 #define	IDN_GLOCK_TRY_SHARED()	(rw_tryenter(&idn.grwlock, RW_READER))
3094 #define	IDN_GLOCK_DOWNGRADE()	(rw_downgrade(&idn.grwlock))
3095 #define	IDN_GUNLOCK()		(rw_exit(&idn.grwlock))
3096 #define	IDN_GLOCK_IS_EXCL()	(RW_WRITE_HELD(&idn.grwlock))
3097 #define	IDN_GLOCK_IS_SHARED()	(RW_READ_HELD(&idn.grwlock))
3098 #define	IDN_GLOCK_IS_HELD()	(RW_LOCK_HELD(&idn.grwlock))
3099 
3100 #define	IDN_SYNC_LOCK()		(mutex_enter(&idn.sync.sz_mutex))
3101 #define	IDN_SYNC_TRYLOCK()	(mutex_tryenter(&idn.sync.sz_mutex))
3102 #define	IDN_SYNC_UNLOCK()	(mutex_exit(&idn.sync.sz_mutex))
3103 #define	IDN_SYNC_IS_LOCKED()	(MUTEX_HELD(&idn.sync.sz_mutex))
3104 
3105 /*
3106  * Macro to reset some globals necessary in preparing
3107  * for initialization of HW for IDN.
3108  */
3109 #define	IDN_PREP_HWINIT() \
3110 	{ \
3111 		ASSERT(IDN_GLOCK_IS_EXCL()); \
3112 		lock_clear(&idn.first_swlink); \
3113 		lock_clear(&idn.first_hwlink); \
3114 		idn.first_hwmasterid = (short)IDN_NIL_DOMID; \
3115 	}
3116 
3117 /*
3118  * Return values of idn_send_data.
3119  */
3120 #define	IDNXMIT_OKAY	0	/* xmit successful */
3121 #define	IDNXMIT_LOOP	1	/* loopback */
3122 #define	IDNXMIT_DROP	2	/* drop packet */
3123 #define	IDNXMIT_RETRY	3	/* retry packet (requeue and qenable) */
3124 #define	IDNXMIT_REQUEUE	4	/* requeue packet, but don't qenable */
3125 
3126 /*
3127  * ---------------------------------------------------------------------
3128  * ss_rwlock must be acquired _before_ any idn_domain locks are
3129  * acquired if both structs need to be accessed.
3130  * idn.struprwlock is acquired when traversing IDN's strup list
3131  * and when adding or deleting entries.
3132  *
3133  * ss_nextp	Linked list of streams.
3134  * ss_rq	Respective read queue.
3135  * ss_sip	Attached device.
3136  * ss_state	Current DL state.
3137  * ss_sap	Bound SAP.
3138  * ss_flags	Misc. flags.
3139  * ss_mccount	# enabled multicast addrs.
3140  * ss_mctab	Table of multicast addrs.
3141  * ss_minor	Minor device number.
3142  * ss_rwlock	Protects ss_linkup fields and DLPI state machine.
3143  * ss_linkup	Boolean flag indicating whether particular (domain) link
3144  *		is up.
3145  * ---------------------------------------------------------------------
3146  */
3147 struct idnstr {				/* gets shoved into q_ptr */
3148 	struct idnstr	*ss_nextp;
3149 	queue_t		*ss_rq;
3150 	struct idn	*ss_sip;
3151 	t_uscalar_t	ss_state;
3152 	t_uscalar_t	ss_sap;
3153 	uint_t		ss_flags;
3154 	uint_t		ss_mccount;
3155 	struct ether_addr	*ss_mctab;
3156 	minor_t		ss_minor;
3157 	krwlock_t	ss_rwlock;
3158 };
3159 
3160 /*
3161  * idnstr.ss_flags - Per-stream flags
3162  */
3163 #define	IDNSFAST	0x01		/* "M_DATA fastpath" mode */
3164 #define	IDNSRAW		0x02		/* M_DATA plain raw mode */
3165 #define	IDNSALLPHYS	0x04		/* "promiscuous mode" */
3166 #define	IDNSALLMULTI	0x08		/* enable all multicast addresses */
3167 #define	IDNSALLSAP	0x10		/* enable all ether type values */
3168 
3169 /*
3170  * Maximum number of multicast address per stream.
3171  */
3172 #define	IDNMAXMC	64
3173 #define	IDNMCALLOC	(IDNMAXMC * sizeof (struct ether_addr))
3174 
3175 /*
3176  * Full DLSAP address length (in struct dladdr format).
3177  */
3178 #define	IDNADDRL	(ETHERADDRL + sizeof (ushort_t))
3179 
3180 struct idndladdr {
3181 	struct ether_addr	dl_phys;
3182 	ushort_t		dl_sap;
3183 };
3184 
3185 #define	IDNHEADROOM		64
3186 #define	IDNROUNDUP(a, n)	(((a) + ((n) - 1)) & ~((n) - 1))
3187 
3188 /*
3189  * Respective interpretation of bytes in 6 byte ethernet address.
3190  */
3191 #define	IDNETHER_ZERO		0
3192 #define	IDNETHER_COOKIE1	1
3193 #define	  IDNETHER_COOKIE1_VAL		0xe5
3194 #define	IDNETHER_COOKIE2	2
3195 #define	  IDNETHER_COOKIE2_VAL		0x82
3196 #define	IDNETHER_NETID		3
3197 #define	IDNETHER_CHANNEL	4
3198 #define	IDNETHER_RESERVED	5
3199 #define	  IDNETHER_RESERVED_VAL		0x64
3200 
3201 /*
3202  * IDN driver supports multliple instances, however they
3203  * still all refer to the same "physical" device.  Multiple
3204  * instances are supported primarily to allow increased
3205  * STREAMs bandwidth since each instance has it's own IP queue.
3206  * This structure is primarily defined to be consistent with
3207  * other network drivers and also to hold the kernel stats.
3208  */
3209 struct idn_kstat {
3210 	ulong_t		si_ipackets;	/* # packets received */
3211 	ulong_t		si_ierrors;	/* # total input errors */
3212 	ulong_t		si_opackets;	/* # packets sent */
3213 	ulong_t		si_oerrors;	/* # total output errors */
3214 
3215 	ulong_t		si_txcoll;	/* # xmit collisions */
3216 	ulong_t		si_rxcoll;	/* # recv collisions */
3217 	ulong_t		si_crc;		/* # recv crc errors */
3218 	ulong_t		si_buff;	/* # recv pkt sz > buf sz */
3219 
3220 	ulong_t		si_nolink;	/* # loss of connection */
3221 	ulong_t		si_linkdown;	/* # link is down */
3222 	ulong_t		si_inits;	/* # driver inits */
3223 	ulong_t		si_nocanput;	/* # canput() failures */
3224 
3225 	ulong_t		si_allocbfail;	/* # allocb() failures */
3226 	ulong_t		si_notbufs;	/* # out of xmit buffers */
3227 	ulong_t		si_reclaim;	/* # reclaim failures */
3228 	ulong_t		si_smraddr;	/* # bad SMR addrs */
3229 
3230 	ulong_t		si_txmax;	/* # xmit over limit */
3231 	ulong_t		si_txfull;	/* # xmit mbox full */
3232 	ulong_t		si_xdcall;	/* # xdcalls sent */
3233 	ulong_t		si_sigsvr;	/* # data server wakeups */
3234 
3235 	ulong_t		si_mboxcrc;	/* # send mbox crc errors */
3236 	/*
3237 	 * MIB II kstat variables
3238 	 */
3239 	ulong_t		si_rcvbytes;	/* # bytes received */
3240 	ulong_t		si_xmtbytes;	/* # bytes transmitted */
3241 	ulong_t		si_multircv;	/* # multicast packets received */
3242 
3243 	ulong_t		si_multixmt;	/* # multicast packets for xmit */
3244 	ulong_t		si_brdcstrcv;	/* # broadcast packets received */
3245 	ulong_t		si_brdcstxmt;	/* # broadcast packets for xmit */
3246 	ulong_t		si_norcvbuf;	/* # rcv packets discarded */
3247 
3248 	ulong_t		si_noxmtbuf;	/* # xmit packets discarded */
3249 	/*
3250 	 * PSARC 1997/198 : 64 bit kstats
3251 	 */
3252 	uint64_t	si_ipackets64;	/* # packets received */
3253 	uint64_t	si_opackets64;	/* # packets transmitted */
3254 	uint64_t	si_rbytes64;	/* # bytes received */
3255 	uint64_t	si_obytes64;	/* # bytes transmitted */
3256 	/*
3257 	 * PSARC 1997/247 : RFC 1643	dot3Stats...
3258 	 */
3259 	ulong_t	si_fcs_errors;		/* FCSErrors */
3260 	ulong_t	si_macxmt_errors;	/* InternalMacTransmitErrors */
3261 	ulong_t	si_toolong_errors;	/* FrameTooLongs */
3262 	ulong_t	si_macrcv_errors;	/* InternalMacReceiveErrors */
3263 };
3264 
3265 /*
3266  * Per logical interface private data structure.
3267  */
3268 struct idn {
3269 	struct idn		*si_nextp;	/* linked instances */
3270 	dev_info_t		*si_dip;	/* assoc. dev_info */
3271 	struct ether_addr	si_ouraddr;	/* enet address */
3272 
3273 	uint_t			si_flags;	/* misc. flags */
3274 	uint_t			si_wantw;	/* xmit: out of res. */
3275 	queue_t			*si_ip4q;	/* ip (v4) read queue */
3276 	queue_t			*si_ip6q;	/* ip (v6) read queue */
3277 
3278 	kstat_t			*si_ksp;	/* kstat pointer */
3279 	struct idn_kstat	si_kstat;	/* per-inst kstat */
3280 };
3281 
3282 struct idn_gkstat {
3283 	ulong_t		gk_reconfigs;		/* # reconfigs */
3284 	ulong_t		gk_reconfig_last;	/* timestamep */
3285 	ulong_t		gk_reaps;		/* # of reap request */
3286 	ulong_t		gk_reap_last;		/* timestamep */
3287 
3288 	ulong_t		gk_links;		/* # of IDN links */
3289 	ulong_t		gk_link_last;		/* timestamep */
3290 	ulong_t		gk_unlinks;		/* # of IDN unlinks */
3291 	ulong_t		gk_unlink_last;		/* timestamep */
3292 
3293 	ulong_t		gk_buffail;		/* # bad bufalloc */
3294 	ulong_t		gk_buffail_last;	/* timestamp */
3295 	ulong_t		gk_slabfail;		/* # bad slaballoc */
3296 	ulong_t		gk_slabfail_last;	/* timestamp */
3297 
3298 	ulong_t		gk_reap_count;		/* # of slabs reaped */
3299 	ulong_t		gk_dropped_intrs;	/* dropped intrs */
3300 };
3301 
3302 extern struct idn_gkstat	sg_kstat;
3303 
3304 #ifdef IDN_NO_KSTAT
3305 
3306 #define	IDN_KSTAT_INC(s, i)
3307 #define	IDN_KSTAT_ADD(s, i, n)
3308 #define	IDN_GKSTAT_INC(i)
3309 #define	IDN_GKSTAT_ADD(vvv, iii)
3310 #define	IDN_GKSTAT_GLOBAL_EVENT(vvv, nnn)
3311 
3312 #else /* IDN_NO_KSTAT */
3313 
3314 #define	IDN_KSTAT_INC(sss, vvv) \
3315 		((((struct idn *)(sss))->si_kstat.vvv)++)
3316 #define	IDN_KSTAT_ADD(sss, vvv, nnn) \
3317 		((((struct idn *)(sss))->si_kstat.vvv) += (nnn))
3318 #define	IDN_GKSTAT_INC(vvv)		((sg_kstat.vvv)++)
3319 #define	IDN_GKSTAT_ADD(vvv, iii)	((sg_kstat.vvv) += (iii))
3320 #define	IDN_GKSTAT_GLOBAL_EVENT(vvv, ttt) \
3321 		((sg_kstat.vvv)++, ((sg_kstat.ttt) = lbolt))
3322 
3323 #endif /* IDN_NO_KSTAT */
3324 
3325 /*
3326  * idn.si_flags
3327  */
3328 #define	IDNRUNNING		0x01		/* IDNnet is UP */
3329 #define	IDNPROMISC		0x02		/* promiscuous mode enabled */
3330 #define	IDNSUSPENDED		0x04		/* suspended (DR) */
3331 
3332 typedef struct kstat_named	kstate_named_t;
3333 
3334 struct idn_kstat_named {
3335 	kstat_named_t	sk_ipackets;	/* # packets received */
3336 	kstat_named_t	sk_ierrors;	/* # total input errors */
3337 	kstat_named_t	sk_opackets;	/* # packets sent */
3338 	kstat_named_t	sk_oerrors;	/* # total output errors */
3339 
3340 	kstat_named_t	sk_txcoll;	/* # xmit collisions */
3341 	kstat_named_t	sk_rxcoll;	/* # recv collisions */
3342 	kstat_named_t	sk_crc;		/* # recv crc errors */
3343 	kstat_named_t	sk_buff;	/* # recv pkt sz > buf sz */
3344 
3345 	kstat_named_t	sk_nolink;	/* # loss of connection */
3346 	kstat_named_t	sk_linkdown;	/* # link is down */
3347 	kstat_named_t	sk_inits;	/* # driver inits */
3348 	kstat_named_t	sk_nocanput;	/* # canput() failures */
3349 
3350 	kstat_named_t	sk_allocbfail;	/* # allocb() failures */
3351 	kstat_named_t	sk_notbufs;	/* # out of xmit buffers */
3352 	kstat_named_t	sk_reclaim;	/* # reclaim failures */
3353 	kstat_named_t	sk_smraddr;	/* # bad SMR addrs */
3354 
3355 	kstat_named_t	sk_txmax;	/* # xmit over limit */
3356 	kstat_named_t	sk_txfull;	/* # xmit mbox full */
3357 	kstat_named_t	sk_xdcall;	/* # xdcalls sent */
3358 	kstat_named_t	sk_sigsvr;	/* # data server wakeups */
3359 
3360 	kstat_named_t	sk_mboxcrc;	/* # send mbox crc errors */
3361 	/*
3362 	 * MIB II kstat variables
3363 	 */
3364 	kstat_named_t	sk_rcvbytes;	/* # bytes received */
3365 	kstat_named_t	sk_xmtbytes;	/* # bytes transmitted */
3366 	kstat_named_t	sk_multircv;	/* # multicast packets received */
3367 
3368 	kstat_named_t	sk_multixmt;	/* # multicast packets for xmit */
3369 	kstat_named_t	sk_brdcstrcv;	/* # broadcast packets received */
3370 	kstat_named_t	sk_brdcstxmt;	/* # broadcast packets for xmit */
3371 	kstat_named_t	sk_norcvbuf;	/* # rcv packets discarded */
3372 
3373 	kstat_named_t	sk_noxmtbuf;	/* # xmit packets discarded */
3374 	/*
3375 	 * PSARC 1997/198 : 64bit kstats
3376 	 */
3377 	kstat_named_t	sk_ipackets64;	/* # packets received */
3378 	kstat_named_t	sk_opackets64;	/* # packets transmitted */
3379 	kstat_named_t	sk_rbytes64;	/* # bytes received */
3380 	kstat_named_t	sk_obytes64;	/* # bytes transmitted */
3381 	/*
3382 	 * PSARC 1997/247 : RFC 1643	dot3Stats...
3383 	 */
3384 	kstat_named_t	sk_fcs_errors;		/* FCSErr */
3385 	kstat_named_t	sk_macxmt_errors;	/* InternalMacXmtErr */
3386 	kstat_named_t	sk_toolong_errors;	/* FrameTooLongs */
3387 	kstat_named_t	sk_macrcv_errors;	/* InternalMacRcvErr */
3388 };
3389 
3390 /*
3391  * Stats for global events of interest (non-counters).
3392  */
3393 struct idn_gkstat_named {
3394 	kstat_named_t	sk_curtime;		/* current time */
3395 	kstat_named_t	sk_reconfigs;		/* # master recfgs */
3396 	kstat_named_t	sk_reconfig_last;	/* timestamp */
3397 	kstat_named_t	sk_reaps;		/* # of reap req */
3398 	kstat_named_t	sk_reap_last;		/* timestamp */
3399 	kstat_named_t	sk_links;		/* # of links */
3400 	kstat_named_t	sk_link_last;		/* timestamp */
3401 	kstat_named_t	sk_unlinks;		/* # of unlinks */
3402 	kstat_named_t	sk_unlink_last;		/* timestamp */
3403 	kstat_named_t	sk_buffail;		/* # bad buf alloc */
3404 	kstat_named_t	sk_buffail_last;	/* timestamp */
3405 	kstat_named_t	sk_slabfail;		/* # bad buf alloc */
3406 	kstat_named_t	sk_slabfail_last;	/* timestamp */
3407 	kstat_named_t	sk_reap_count;		/* # slabs reaped */
3408 	kstat_named_t	sk_dropped_intrs;	/* intrs dropped */
3409 };
3410 
3411 /*
3412  * ---------------------------------------------------------------------
3413  */
3414 #ifdef DEBUG
3415 #define	IDNXDC(d, mt, a1, a2, a3, a4) \
3416 	(debug_idnxdc("idnxdc", (int)(d), (mt), \
3417 		(uint_t)(a1), (uint_t)(a2), (uint_t)(a3), (uint_t)(a4)))
3418 #else /* DEBUG */
3419 #define	IDNXDC(d, mt, a1, a2, a3, a4) \
3420 	(idnxdc((int)(d), (mt), \
3421 		(uint_t)(a1), (uint_t)(a2), (uint_t)(a3), (uint_t)(a4)))
3422 #endif /* DEBUG */
3423 #define	IDNXDC_BROADCAST(ds, mt, a1, a2, a3, a4) \
3424 	(idnxdc_broadcast((domainset_t)(ds), (mt), \
3425 		(uint_t)(a1), (uint_t)(a2), (uint_t)(a3), (uint_t)(a4)))
3426 
3427 /*
3428  * ---------------------------------------------------------------------
3429  */
3430 #define	SET_XARGS(x, a0, a1, a2, a3) \
3431 	((x)[0] = (uint_t)(a0), (x)[1] = (uint_t)(a1), \
3432 	(x)[2] = (uint_t)(a2), (x)[3] = (uint_t)(a3))
3433 
3434 #define	GET_XARGS(x, a0, a1, a2, a3) \
3435 	(((a0) ? *(uint_t *)(a0) = (x)[0] : 1), \
3436 	((a1) ? *(uint_t *)(a1) = (x)[1] : 1), \
3437 	((a2) ? *(uint_t *)(a2) = (x)[2] : 1), \
3438 	((a3) ? *(uint_t *)(a3) = (x)[3] : 1))
3439 
3440 #define	CLR_XARGS(x) \
3441 		((x)[0] = (x)[1] = (x)[2] = (x)[3] = 0)
3442 
3443 #define	GET_XARGS_NEGO_TICKET(x)	((uint_t)(x)[0])
3444 #define	GET_XARGS_NEGO_DSET(x, d) \
3445 		((d)[0] = (x)[1], (d)[1] = (x)[2], (d)[2] = (x)[3])
3446 #define	SET_XARGS_NEGO_TICKET(x, t)	((x)[0] = (uint_t)(t))
3447 #define	SET_XARGS_NEGO_DSET(x, d) \
3448 		((x)[1] = (uint_t)(d)[0], \
3449 		(x)[2] = (uint_t)(d)[1], \
3450 		(x)[3] = (uint_t)(d)[2])
3451 
3452 #define	GET_XARGS_CON_TYPE(x)		((idn_con_t)(x)[0])
3453 #define	GET_XARGS_CON_DOMSET(x)		((domainset_t)(x)[1])
3454 #define	SET_XARGS_CON_TYPE(x, t)	((x)[0] = (uint_t)(t))
3455 #define	SET_XARGS_CON_DOMSET(x, s)	((x)[1] = (uint_t)(s))
3456 
3457 #define	GET_XARGS_FIN_TYPE(x)		GET_FIN_TYPE((x)[0])
3458 #define	GET_XARGS_FIN_ARG(x)		GET_FIN_ARG((x)[0])
3459 #define	GET_XARGS_FIN_DOMSET(x)		((domainset_t)(x)[1])
3460 #define	GET_XARGS_FIN_OPT(x)		((idn_finopt_t)(x)[2])
3461 #define	GET_XARGS_FIN_MASTER(x)		((uint_t)(x)[3])
3462 #define	SET_XARGS_FIN_TYPE(x, t)	SET_FIN_TYPE((x)[0], (t))
3463 #define	SET_XARGS_FIN_ARG(x, a)		SET_FIN_ARG((x)[0], (a))
3464 #define	SET_XARGS_FIN_DOMSET(x, s)	((x)[1] = (uint_t)(s))
3465 #define	SET_XARGS_FIN_OPT(x, o)		((x)[2] = (uint_t)(o))
3466 #define	SET_XARGS_FIN_MASTER(x, m)	((x)[3] = (uint_t)(m))
3467 
3468 #define	GET_XARGS_NACK_TYPE(x)		((idn_nack_t)(x)[0])
3469 #define	GET_XARGS_NACK_ARG1(x)		((x)[1])
3470 #define	GET_XARGS_NACK_ARG2(x)		((x)[2])
3471 #define	SET_XARGS_NACK_TYPE(x, t)	((x)[0] = (uint_t)(t))
3472 #define	SET_XARGS_NACK_ARG1(x, a1)	((x)[1] = (uint_t)(a1))
3473 #define	SET_XARGS_NACK_ARG2(x, a2)	((x)[2] = (uint_t)(a2))
3474 
3475 #define	GET_XARGS_CFG_PHASE(x)		((int)(x)[0])
3476 #define	SET_XARGS_CFG_PHASE(x, p)	((x)[0] = (uint_t)(p))
3477 
3478 /*
3479  * ---------------------------------------------------------------------
3480  */
3481 /*
3482  * Device instance to SIP (IDN instance pointer).
3483  */
3484 #ifdef DEBUG
3485 #define	IDN_INST2SIP(i) \
3486 		(ASSERT(((i) >= 0) && ((i) < (IDN_MAXMAX_NETS << 1))), \
3487 			idn_i2s_table[i])
3488 #else /* DEBUG */
3489 #define	IDN_INST2SIP(i)		(idn_i2s_table[i])
3490 #endif /* DEBUG */
3491 
3492 #define	IDN_SET_INST2SIP(i, s) \
3493 	{ \
3494 		ASSERT(((i) >= 0) && ((i) < (IDN_MAXMAX_NETS << 1))); \
3495 		idn_i2s_table[i] = (s); \
3496 	}
3497 
3498 #define	IDN_NETID2DOMID(n)	(VALID_UDOMAINID(n) ? \
3499 					((int)(n)) : IDN_NIL_DOMID)
3500 #define	IDN_DOMID2NETID(d)	((ushort_t)(d))
3501 
3502 #ifdef DEBUG
3503 #define	IDNDL_ETHER2DOMAIN(eap) \
3504 		(_idndl_ether2domain(eap))
3505 #define	IDNDL_ETHER2SIP(eap) \
3506 		(_idndl_ether2sip(eap))
3507 #else
3508 /*
3509  * The following values can be returned from IDNDL_ETHER2DOMAIN:
3510  *	IDN_NIL_DOMID
3511  *		Ether address is broadcast (0xff) or domain doesn't exist.
3512  *	domid	Domain id with drwlock(reader) held.
3513  */
3514 #define	IDNDL_ETHER2DOMAIN(eap) \
3515 	(IDN_NETID2DOMID((eap)->ether_addr_octet[IDNETHER_NETID]))
3516 #define	IDNDL_ETHER2SIP(eap) \
3517 		(((eap)->ether_addr_octet[IDNETHER_CHANNEL] == 0xff) ? NULL : \
3518 		IDN_INST2SIP((int)(eap)->ether_addr_octet[IDNETHER_CHANNEL]))
3519 #endif /* DEBUG */
3520 
3521 #define	UPPER32_CPUMASK(s)	_upper32cpumask(s)
3522 #define	LOWER32_CPUMASK(s)	_lower32cpumask(s)
3523 #define	MAKE64_CPUMASK(s, u, l)	_make64cpumask(&(s), (u), (l))
3524 
3525 #ifdef DEBUG
3526 extern caddr_t	_idn_getstruct(char *structname, int size);
3527 extern void	_idn_freestruct(caddr_t ptr, char *structname, int size);
3528 
3529 #define	GETSTRUCT(structure, num) \
3530 	((structure *)_idn_getstruct("structure", sizeof (structure)*(num)))
3531 #define	FREESTRUCT(ptr, structure, num) \
3532 	(_idn_freestruct((caddr_t)ptr, "structure", sizeof (structure)*(num)))
3533 #else /* DEBUG */
3534 #define	GETSTRUCT(structure, num) \
3535 	((structure *)kmem_zalloc((uint_t)(sizeof (structure) * (num)), \
3536 				    KM_SLEEP))
3537 #define	FREESTRUCT(ptr, structure, num) \
3538 	(kmem_free((caddr_t)(ptr), sizeof (structure) * (num)))
3539 #endif /* DEBUG */
3540 
3541 extern int		idn_debug;
3542 extern idn_global_t	idn;
3543 extern idn_domain_t	idn_domain[];
3544 extern struct idn	*idn_i2s_table[];
3545 extern int		idn_history;
3546 extern struct idn_history	idnhlog;
3547 
3548 extern int		idn_smr_size;
3549 extern int		idn_nwr_size;
3550 extern int		idn_protocol_nservers;
3551 extern int		idn_awolmsg_interval;
3552 extern int		idn_smr_bufsize;
3553 extern int		idn_slab_bufcount;
3554 extern int		idn_slab_prealloc;
3555 extern int		idn_slab_mintotal;
3556 extern int		idn_window_max;
3557 extern int		idn_window_incr;
3558 extern int		idn_reclaim_min;
3559 extern int		idn_reclaim_max;
3560 extern int		idn_mbox_per_net;
3561 extern int		idn_max_nets;
3562 
3563 extern int		idn_netsvr_spin_count;
3564 extern int		idn_netsvr_wait_min;
3565 extern int		idn_netsvr_wait_max;
3566 extern int		idn_netsvr_wait_shift;
3567 
3568 extern int		idn_checksum;
3569 
3570 extern int		idn_msgwait_nego;
3571 extern int		idn_msgwait_cfg;
3572 extern int		idn_msgwait_con;
3573 extern int		idn_msgwait_fin;
3574 extern int		idn_msgwait_cmd;
3575 extern int		idn_msgwait_data;
3576 
3577 extern int		idn_retryfreq_nego;
3578 extern int		idn_retryfreq_con;
3579 extern int		idn_retryfreq_fin;
3580 
3581 extern int		idn_window_emax;	/* calculated */
3582 extern int		idn_slab_maxperdomain;	/* calculated */
3583 
3584 /*
3585  * ---------------------------------------------------------------------
3586  * io/idn.c
3587  * ---------------------------------------------------------------------
3588  */
3589 extern int	board_to_ready_cpu(int board, cpuset_t cpuset);
3590 extern int	idn_open_domain(int domid, int cpuid, uint_t ticket);
3591 extern void 	idn_close_domain(int domid);
3592 extern void	inum2str(uint_t inum, char str[]);
3593 extern idn_timer_t	*idn_timer_alloc();
3594 extern void	idn_timer_free(idn_timer_t *tp);
3595 extern void	idn_timerq_init(idn_timerq_t *tq);
3596 extern void	idn_timerq_deinit(idn_timerq_t *tq);
3597 extern void	idn_timerq_free(idn_timerq_t *tq);
3598 extern ushort_t	idn_timer_start(idn_timerq_t *tq, idn_timer_t *tp,
3599 				clock_t tval);
3600 extern int	idn_timer_stopall(idn_timer_t *tp);
3601 extern void	idn_timer_dequeue(idn_timerq_t *tq, idn_timer_t *tp);
3602 extern void	idn_timer_stop(idn_timerq_t *tq, int subtype, ushort_t tcookie);
3603 extern idn_timer_t	*idn_timer_get(idn_timerq_t *tq, int subtype,
3604 				ushort_t tcookie);
3605 extern void	idn_domain_resetentry(idn_domain_t *dp);
3606 extern void	idn_strlinks_enable(uint_t netaddr, int domid);
3607 extern void	idn_strlinks_disable(uint_t domset, uint_t netaddr,
3608 				int disconnect);
3609 extern void	idn_dopcache_init();
3610 extern void	idn_dopcache_deinit();
3611 extern void 	*idn_init_op(idn_opflag_t opflag, boardset_t boardset,
3612 				idnsb_error_t *sep);
3613 extern void	idn_add_op(idn_opflag_t opflag, domainset_t domset);
3614 extern void	idn_update_op(idn_opflag_t opflag, domainset_t domset,
3615 				idnsb_error_t *sep);
3616 extern void	idn_deinit_op(void *cookie);
3617 extern int	idn_wait_op(void *cookie, boardset_t *domsetp,
3618 				int wait_timeout);
3619 extern int	idn_wakeup_op(boardset_t boardset, uint_t domset,
3620 				idn_opflag_t opflag, int error);
3621 extern void	idn_error_op(uint_t domset, boardset_t boardset, int error);
3622 extern void	cpuset2str(cpuset_t cset, char buffer[]);
3623 extern void	domainset2str(domainset_t dset, char buffer[]);
3624 extern void	boardset2str(boardset_t bset, char buffer[]);
3625 extern void	mask2str(uint_t mask, char buffer[], int maxnum);
3626 extern int	idnxdc(int domid, idn_msgtype_t *mtp,
3627 				uint_t arg1, uint_t arg2,
3628 				uint_t arg3, uint_t arg4);
3629 extern void	idnxdc_broadcast(domainset_t domset, idn_msgtype_t *mtp,
3630 				uint_t arg1, uint_t arg2,
3631 				uint_t arg3, uint_t arg4);
3632 extern void	idn_awol_event_set(boardset_t boardset);
3633 extern void	idn_awol_event_clear(boardset_t boardset);
3634 #ifdef DEBUG
3635 extern int	debug_idnxdc(char *f, int domid, idn_msgtype_t *mtp,
3636 				uint_t arg1, uint_t arg2,
3637 				uint_t arg3, uint_t arg4);
3638 #endif /* DEBUG */
3639 extern boardset_t	cpuset2boardset(cpuset_t portset);
3640 extern uint_t	_upper32cpumask(cpuset_t cset);
3641 extern uint_t	_lower32cpumask(cpuset_t cset);
3642 extern void	_make64cpumask(cpuset_t *csetp, uint_t upper, uint_t lower);
3643 
3644 /*
3645  * ---------------------------------------------------------------------
3646  * io/idn_proto.c
3647  * ---------------------------------------------------------------------
3648  */
3649 extern void	idn_assign_cookie(int domid);
3650 extern int	idn_rput_data(queue_t *q, mblk_t *mp, int isput);
3651 extern int	idn_wput_data(queue_t *q, mblk_t *mp, int isput);
3652 extern int	idn_send_data(int dst_domid, idn_netaddr_t dst_netaddr,
3653 				queue_t *wq, mblk_t *mp);
3654 extern void 	idn_recv_signal(mblk_t *mp);
3655 extern int 	idn_link(int domid, int cpuid, int pri, int waittime,
3656 				idnsb_error_t *sep);
3657 extern int 	idn_unlink(int domid, boardset_t idnset, idn_fin_t fintype,
3658 				idn_finopt_t finopt, int waittime,
3659 				idnsb_error_t *sep);
3660 extern int	idnh_recv_dataack(int domid, int src_proc,
3661 				uint_t acknack, idn_xdcargs_t xargs);
3662 extern int 	idnh_recv_other(int sourceid, int src_proc, int dst_proc,
3663 				uint_t inum, uint_t acknack,
3664 				idn_xdcargs_t xargs);
3665 extern void 	idn_send_cmd(int domid, idn_cmd_t cmdtype,
3666 				uint_t arg1, uint_t arg2, uint_t arg3);
3667 extern void	idn_send_cmdresp(int domid, idn_msgtype_t *mtp,
3668 				idn_cmd_t cmdtype, uint_t arg1,
3669 				uint_t arg2, uint_t cerrno);
3670 extern void 	idn_broadcast_cmd(idn_cmd_t cmdtype,
3671 				uint_t arg1, uint_t arg2, uint_t arg3);
3672 extern int	idn_reclaim_mboxdata(int domid, int channel, int nbufs);
3673 extern void	idn_clear_awol(int domid);
3674 extern int	idn_protocol_init(int nservers);
3675 extern void	idn_protocol_deinit();
3676 extern void	idn_timer_expired(void *arg);
3677 extern int	idn_open_channel(int channel);
3678 extern void	idn_close_channel(int channel, idn_chanop_t chanop);
3679 extern idn_mainmbox_t	*idn_mainmbox_init(int domid, int mbx);
3680 extern void	idn_mainmbox_deinit(int domid, idn_mainmbox_t *mmp);
3681 extern void	idn_signal_data_server(int domid, ushort_t channel);
3682 extern int	idn_chanservers_init();
3683 extern void	idn_chanservers_deinit();
3684 extern void	idn_chanserver_bind(int net, int cpuid);
3685 extern int	idn_retry_terminate(uint_t token);
3686 extern idn_protojob_t	*idn_protojob_alloc(int kmflag);
3687 extern void	idn_protojob_submit(int cookie, idn_protojob_t *jp);
3688 extern int	idn_domain_is_registered(int domid, int channel,
3689 				idn_chanset_t *chansetp);
3690 extern void	idn_xmit_monitor_kickoff(int chan_wanted);
3691 extern void	idn_sync_exit(int domid, idn_synccmd_t cmd);
3692 /*
3693  * ---------------------------------------------------------------------
3694  * io/idn_xf.c
3695  * ---------------------------------------------------------------------
3696  */
3697 extern void	idnxf_flushall_ecache();
3698 extern int	idnxf_shmem_add(int is_master, boardset_t boardset,
3699 				pfn_t pfnbase, pfn_t pfnlimit,
3700 				uint_t *mcadr);
3701 extern int	idnxf_shmem_sub(int is_master, boardset_t boardset);
3702 extern int	idn_cpu_per_board(void *p2o, cpuset_t cset,
3703 				struct hwconfig *hwp);
3704 /*
3705  * ---------------------------------------------------------------------
3706  * io/idn_dlpi.c
3707  * ---------------------------------------------------------------------
3708  */
3709 extern int	idndl_init(struct idn *sip);
3710 extern void	idndl_uninit(struct idn *sip);
3711 extern void	idndl_statinit(struct idn *sip);
3712 extern void	idndl_dodetach(struct idnstr *);
3713 extern int	idnioc_dlpi(queue_t *wq, mblk_t *mp, int *argsize);
3714 extern void	idndl_localetheraddr(struct idn *sip, struct ether_addr *eap);
3715 extern int	idndl_domain_etheraddr(int domid, int instance,
3716 				struct ether_addr *eap);
3717 extern void	idndl_dlpi_init();
3718 extern int	idndl_start(queue_t *wq, mblk_t *mp, struct idn *sip);
3719 extern void	idndl_read(struct idn *sip, mblk_t *mp);
3720 extern void	idndl_proto(queue_t *wq, mblk_t *mp);
3721 extern void	idndl_sendup(struct idn *, mblk_t *, struct idnstr *(*)());
3722 extern struct idnstr *idndl_accept(struct idnstr *, struct idn *, int,
3723 				struct ether_addr *);
3724 extern struct idnstr *idndl_paccept(struct idnstr *, struct idn *, int,
3725 				struct ether_addr *);
3726 extern void	idndl_wenable(struct idn *);
3727 /*
3728  * ---------------------------------------------------------------------
3729  * io/idn_smr.c
3730  * ---------------------------------------------------------------------
3731  */
3732 extern void	smr_slabwaiter_open(domainset_t domset);
3733 extern void	smr_slabwaiter_close(domainset_t domset);
3734 /*
3735  * ---------------------------------------------------------------------
3736  */
3737 extern void	idn_smrsize_init();
3738 extern void	idn_init_autolink();
3739 extern void	idn_deinit_autolink();
3740 
3741 extern void	idn_dmv_handler(void *arg);
3742 extern void	idnxf_init_mondo(uint64_t dmv_word0,
3743 				uint64_t dmv_word1, uint64_t dmv_word2);
3744 extern int	idnxf_send_mondo(int upaid);
3745 
3746 extern clock_t	idn_msg_waittime[];
3747 extern clock_t	idn_msg_retrytime[];
3748 
3749 #endif /* !_ASM */
3750 #endif /* _KERNEL */
3751 
3752 #ifndef _ASM
3753 /*
3754  * ---------------------------------------------------------------------
3755  */
3756 #define	IDN_NIL_DOMID		-1
3757 #define	IDN_NIL_DCPU		-1
3758 
3759 /*
3760  * ---------------------------------------------------------------------
3761  */
3762 
3763 /*
3764  * IOCTL Interface
3765  *
3766  * Commands must stay in the range (1 - 4096) since only 12 bits
3767  * are allotted.
3768  */
3769 #define	_IDN(n)			(('I' << 20) | ('D' << 12) | (n))
3770 #define	IDNIOC_LINK		_IDN(1)		/* domain_link */
3771 #define	IDNIOC_UNLINK		_IDN(2)		/* domain_unlink */
3772 #define	IDNIOC_unused0		_IDN(3)
3773 #define	IDNIOC_unused1		_IDN(4)
3774 #define	IDNIOC_unused2		_IDN(5)
3775 #define	IDNIOC_unused3		_IDN(6)
3776 #define	IDNIOC_unused4		_IDN(7)
3777 #define	IDNIOC_DLPI_ON		_IDN(8)		/* Turn ON DLPI on str */
3778 #define	IDNIOC_DLPI_OFF		_IDN(9)		/* Turn OFF DLPI on str */
3779 #define	IDNIOC_PING		_IDN(10)	/* For latency testing */
3780 #define	IDNIOC_PING_INIT	_IDN(11)
3781 #define	IDNIOC_PING_DEINIT	_IDN(12)
3782 #define	IDNIOC_MEM_RW		_IDN(13)	/* Random R/W of SMR */
3783 
3784 
3785 #define	VALID_NDOP(op)		(((op) == ND_SET) || ((op) == ND_GET))
3786 
3787 #define	VALID_DLPIOP(op)	(((op) == DLIOCRAW) || \
3788 				((op) == DL_IOC_HDR_INFO))
3789 
3790 #define	VALID_IDNOP(op)		(((op) >= _IDN(1)) && ((op) <= _IDN(13)))
3791 
3792 #define	VALID_IDNIOCTL(op)	(VALID_IDNOP(op) || \
3793 				VALID_NDOP(op) || \
3794 				VALID_DLPIOP(op))
3795 
3796 typedef union idnop {
3797 	struct {
3798 		int		domid;		/* input */
3799 		int		cpuid;		/* input */
3800 		int		master;		/* input */
3801 		int		wait;		/* input */
3802 	} link;
3803 	struct {
3804 		int		domid;		/* input */
3805 		int		cpuid;		/* input */
3806 		int		force;		/* input */
3807 		int		wait;		/* input */
3808 	} unlink;
3809 	struct {
3810 		int		domid;		/* input */
3811 		int		cpuid;		/* input */
3812 	} ping;
3813 	struct {
3814 		uint_t		lo_off;		/* input */
3815 		uint_t		hi_off;		/* input */
3816 		int		blksize;	/* input */
3817 		int		num;		/* input */
3818 		int		rw;		/* input */
3819 		int		goawol;		/* input */
3820 	} rwmem;
3821 } idnop_t;
3822 
3823 #ifdef _KERNEL
3824 /*
3825  * ndd support for IDN tunables.
3826  */
3827 typedef struct idnparam {
3828 	ulong_t	sp_min;
3829 	ulong_t	sp_max;
3830 	ulong_t	sp_val;
3831 	char	*sp_name;
3832 } idnparam_t;
3833 
3834 extern idnparam_t	idn_param_arr[];
3835 
3836 #define	idn_modunloadable		idn_param_arr[0].sp_val
3837 #ifdef IDN_PERF
3838 #define	_LP	0
3839 #define	_xxx_tbd			idn_param_arr[_LP+1].sp_val
3840 #endif /* IDN_PERF */
3841 
3842 /*
3843  * =====================================================================
3844  */
3845 
3846 /*
3847  * Some junk to pretty print board lists and cpu lists in
3848  * log/console messages.  Length is big enough to display 64 double
3849  * digit cpus separated by a command and single space.  (Board list
3850  * is similar, but only 16 entries possible.
3851  */
3852 #define	_DSTRLEN		400
3853 #define	ALLOC_DISPSTRING()	((char *)kmem_alloc(_DSTRLEN, KM_NOSLEEP))
3854 #define	FREE_DISPSTRING(b)	(kmem_free((void *)(b), _DSTRLEN))
3855 
3856 /*
3857  * These are declared in idn.c.
3858  */
3859 extern const char	*idnds_str[];
3860 extern const char	*idnxs_str[];
3861 extern const char	*idngs_str[];
3862 extern const char	*idncmd_str[];
3863 extern const char	*idncon_str[];
3864 extern const char	*idnfin_str[];
3865 extern const char	*idnfinarg_str[];
3866 extern const char	*idnfinopt_str[];
3867 extern const char	*idnreg_str[];
3868 extern const char	*idnnack_str[];
3869 extern const char	*idnop_str[];
3870 extern const char	*idnsync_str[];
3871 extern const char	*chanop_str[];
3872 extern const char	*chanaction_str[];
3873 extern const char	*inum_str[];
3874 extern const int	inum_bump;
3875 extern const int	inum_max;
3876 extern const int	acknack_shift;
3877 
3878 extern const char	*timer_str[];
3879 extern const char	*res_str[];
3880 
3881 #endif /* _KERNEL */
3882 #endif /* !_ASM */
3883 
3884 #ifdef	__cplusplus
3885 }
3886 #endif
3887 
3888 #endif /* _SYS_IDN_H */
3889