xref: /titanic_50/usr/src/uts/sun4u/starfire/io/idn_xf.c (revision c77a61a72b5ecdc507d6cf104142edd371a16c84)
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 (c) 1996 by Sun Microsystems, Inc.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include <sys/types.h>
29 #include <sys/sysmacros.h>
30 #include <sys/open.h>
31 #include <sys/param.h>
32 #include <sys/vm_machparam.h>
33 #include <sys/machparam.h>
34 #include <sys/systm.h>
35 #include <sys/signal.h>
36 #include <sys/cred.h>
37 #include <sys/user.h>
38 #include <sys/proc.h>
39 #include <sys/vnode.h>
40 #include <sys/uio.h>
41 #include <sys/buf.h>
42 #include <sys/file.h>
43 #include <sys/kmem.h>
44 #include <sys/stat.h>
45 #include <sys/stream.h>
46 #include <sys/stropts.h>
47 #include <sys/strsubr.h>
48 #include <sys/poll.h>
49 #include <sys/debug.h>
50 #include <sys/conf.h>
51 #include <sys/ddi.h>
52 #include <sys/sunddi.h>
53 #include <sys/errno.h>
54 #include <sys/modctl.h>
55 #include <sys/x_call.h>
56 #include <sys/cpuvar.h>
57 #include <sys/machcpuvar.h>
58 #include <sys/machsystm.h>
59 
60 #include <sys/pda.h>
61 #include <sys/starfire.h>
62 #include <sys/idn.h>
63 #include <sys/idn_xf.h>
64 
65 kmutex_t	idn_xf_mutex;		/* to serialize hardware access */
66 /*
67  * This data structure is referenced during the cross-call
68  * update of the CICs.  The semaphore is used for synchronization
69  * when waiting for completion of the respective operation.
70  * We want IDNCIC_TIMEOUT ticks for all the cpus to check-in
71  * before we bail out and fail the operation.
72  */
73 #define	IDNCIC_TIMEOUT		(30*hz)
74 #define	IDNCIC_TIMECHK		(hz/3)
75 #define	IDNCIC_UNKNOWN		0
76 #define	IDNCIC_OK		1	/* values for xf_errcic */
77 #define	IDNCIC_ERR		2
78 #define	IDNCIC_BUSY		3
79 
80 #ifdef DEBUG
81 #define	NCICREGS		3	/* smmask, smbar, smlar */
82 #define	CICREG_SMMASK		0
83 #define	CICREG_SMBAR		1
84 #define	CICREG_SMLAR		2
85 
86 #define	RESET_CIC_HISTORY() \
87 		(xf_cicboards = xf_cicbuses = 0, \
88 		bzero(xf_cicregs, sizeof (xf_cicregs)))
89 
90 #define	UPDATE_CIC_HISTORY(reg, brd, bus, val) \
91 		(BOARDSET_ADD(xf_cicboards, (brd)), \
92 		BOARDSET_ADD(xf_cicbuses, (bus)), \
93 		xf_cicregs[brd][bus][reg] = (val))
94 
95 #define	DUMP_CIC_HISTORY() \
96 { \
97 	if (idn_debug & IDNDBG_XF) { \
98 		int	_bd, _bs; \
99 		procname_t	_proc = "dump_cic_history"; \
100 		for (_bd = 0; _bd < MAX_BOARDS; _bd++) { \
101 			if (!BOARD_IN_SET(xf_cicboards, _bd)) \
102 				continue; \
103 			for (_bs = 0; _bs < MAX_ABUSES; _bs++) { \
104 				if (!BOARD_IN_SET(xf_cicbuses, _bs)) \
105 					continue; \
106 				printf("%s: (bd.bs = %d.%d) m/b/l = " \
107 					"%x/%x/%x\n", _proc, _bd, _bs, \
108 					xf_cicregs[_bd][_bs][CICREG_SMMASK], \
109 					xf_cicregs[_bd][_bs][CICREG_SMBAR], \
110 					xf_cicregs[_bd][_bs][CICREG_SMLAR]); \
111 			} \
112 		} \
113 		DEBUG_DELAY(); \
114 	} \
115 }
116 
117 /*
118  * Globally updated during CIC reg updates.  Everybody has
119  * a unique location, so no concern about updates stepping
120  * on each other.
121  */
122 static ushort_t	xf_cicboards, xf_cicbuses;
123 static uint_t	xf_cicregs[MAX_BOARDS][MAX_ABUSES][NCICREGS];
124 #else /* DEBUG */
125 #define	RESET_CIC_HISTORY()
126 #define	UPDATE_CIC_HISTORY(reg, brd, bus, val)
127 #define	DUMP_CIC_HISTORY()
128 #endif /* DEBUG */
129 
130 struct idnxf_cic_info {			/* protected by idn_xf_mutex */
131 /*  0 */	short		xf_abus_mask;
132 /*  2 */	boardset_t	xf_boardset;
133 /*  4 */	uint_t		xf_smbase;
134 /*  8 */	uint_t		xf_smlimit;
135 /*  c */	int		xf_doadd;
136 
137 /* 10 */	int		xf_count;	/* atomically updated */
138 /* 14 */	time_t		xf_start_time;
139 /* 18 */	kcondvar_t	xf_cv;
140 /* 1a */	short		xf_errtimer;
141 /* 1c */	int		xf_errcnt;	/* atomically updated */
142 
143 /* 20 */	uchar_t		xf_errcic[MAX_BOARDS][MAX_ABUSES];
144 
145 /* 60 */	kmutex_t	xf_mutex;
146 };	/* sizeof = 0x68 = 104 (26X) */
147 
148 static struct idnxf_cic_info	idnxf_cic_info;
149 #ifdef DEBUG
150 static uint_t			o_idn_debug;
151 #endif /* DEBUG */
152 
153 int	idn_check_cpu_per_board = 1;
154 
155 static int	pc_prep_cic_buffer(int cpuid, uint_t cicdata);
156 static int	cic_write_sm_mask(int board, int bus, boardset_t sm_mask);
157 static int	cic_write_sm_bar(int board, int bus, uint_t sm_bar);
158 static int	cic_write_sm_lar(int board, int bus, uint_t sm_lar);
159 static int	cic_get_smmask_bit(void);
160 static int	pc_write_madr(pda_handle_t ph,
161 				int lboard, int rboard, uint_t madr);
162 static boardset_t	get_boardset(pda_handle_t ph, int *nboards);
163 static int	verify_smregs(int brd, int bus, boardset_t smmask,
164 				uint_t smbase, uint_t smlimit);
165 static void	idnxf_shmem_wakeup(void *arg);
166 static void	idnxf_shmem_update_one(uint64_t arg1, uint64_t arg2);
167 static int	idnxf_shmem_update_all(pda_handle_t ph,
168 				boardset_t boardset, uint_t smbase,
169 				uint_t smlimit, int doadd);
170 
171 #define	PHYSIO_ST(paddr, val)		(stphysio((paddr), (val)))
172 #define	PHYSIO_LD(paddr)		(ldphysio(paddr))
173 #define	PHYSIO_STH(paddr, val)		(sthphysio((paddr), (val)))
174 #define	PHYSIO_LDH(paddr)		(ldhphysio(paddr))
175 
176 #ifdef DEBUG
177 #define	DEBUG_DELAY() 	(drv_usecwait(5000))	/* 5 ms */
178 #else /* DEBUG */
179 #define	DEBUG_DELAY()
180 #endif /* DEBUG */
181 
182 
183 /*
184  * ---------------------------------------------------------------------
185  */
186 boardset_t
187 cic_read_domain_mask(int board, int bus)
188 {
189 	u_longlong_t	csr_addr;
190 	boardset_t	domain_mask;
191 	procname_t	proc = "cic_read_domain_mask";
192 
193 	ASSERT(CPUID_TO_BOARDID(CPU->cpu_id) == board);
194 
195 	csr_addr = MAKE_CIC_CSR_PA(board,
196 				    CSR_TYPE_CIC,
197 				    CIC_DOMAIN_MASK_ADDR,
198 				    bus);
199 	PR_XF("%s: (bd=%d, bs=%d) csr_addr = 0x%llx\n",
200 			proc, board, bus, csr_addr);
201 
202 	domain_mask = (boardset_t)PHYSIO_LDH(csr_addr);
203 
204 	return (domain_mask);
205 }
206 
207 boardset_t
208 cic_read_sm_mask(int board, int bus)
209 {
210 	u_longlong_t	csr_addr;
211 	boardset_t	sm_mask;
212 	procname_t	proc = "cic_read_sm_mask";
213 
214 	ASSERT(CPUID_TO_BOARDID(CPU->cpu_id) == board);
215 
216 	csr_addr = MAKE_CIC_CSR_PA(board,
217 				    CSR_TYPE_CIC,
218 				    CIC_SM_MASK_ADDR,
219 				    bus);
220 	PR_XF("%s: (bd=%d, bs=%d) csr_addr = 0x%llx\n",
221 			proc, board, bus, csr_addr);
222 
223 	sm_mask = (boardset_t)PHYSIO_LDH(csr_addr);
224 
225 	return (sm_mask);
226 }
227 
228 static int
229 cic_write_sm_mask(int board, int bus, boardset_t sm_mask)
230 {
231 	u_longlong_t	csr_addr;
232 	int		cnt;
233 	procname_t	proc = "cic_write_sm_mask";
234 
235 	ASSERT(CPUID_TO_BOARDID(CPU->cpu_id) == board);
236 
237 	sm_mask &= 0xffff;
238 	/*
239 	 * Before we can write to the CIC, we need to set
240 	 * up the CIC write data buffer in the PC.
241 	 */
242 	if (pc_prep_cic_buffer(CPU->cpu_id, (uint_t)sm_mask) < 0)
243 		return (-1);
244 
245 	/*
246 	 * Now we can write to the CIC.
247 	 */
248 	csr_addr = MAKE_CIC_CSR_PA(board,
249 				    CSR_TYPE_CIC,
250 				    CIC_SM_MASK_ADDR,
251 				    bus);
252 	PR_XF("%s: (bd=%d, bs=%d) csr_addr = 0x%llx\n",
253 		proc, board, bus, csr_addr);
254 	PR_XF("%s: writing sm_mask = 0x%x\n",
255 		proc, (ushort_t)sm_mask);
256 
257 	UPDATE_CIC_HISTORY(CICREG_SMMASK, board, bus, sm_mask);
258 
259 	PHYSIO_STH(csr_addr, (ushort_t)sm_mask);
260 	/*
261 	 * Read back for verification.
262 	 */
263 	for (cnt = 0; (PHYSIO_LDH(csr_addr) != sm_mask) && (cnt < 10); cnt++)
264 		;
265 
266 	return ((cnt == 10) ? -1 : 0);
267 }
268 
269 uint_t
270 cic_read_sm_bar(int board, int bus)
271 {
272 	u_longlong_t	csr_addr;
273 	uint_t		sm_bar;
274 	procname_t	proc = "cic_read_sm_bar";
275 
276 	ASSERT(CPUID_TO_BOARDID(CPU->cpu_id) == board);
277 
278 	csr_addr = MAKE_CIC_CSR_PA(board,
279 				    CSR_TYPE_CIC,
280 				    CIC_SM_BAR_MSB_ADDR,
281 				    bus);
282 	PR_XF("%s:MSB: (bd=%d, bs=%d) csr_addr = 0x%llx\n",
283 		proc, board, bus, csr_addr);
284 
285 	sm_bar = (uint_t)PHYSIO_LDH(csr_addr);
286 	sm_bar <<= 16;
287 
288 	csr_addr = MAKE_CIC_CSR_PA(board,
289 				    CSR_TYPE_CIC,
290 				    CIC_SM_BAR_LSB_ADDR,
291 				    bus);
292 	PR_XF("%s:LSB: (bd=%d, bs=%d) csr_addr = 0x%llx\n",
293 		proc, board, bus, csr_addr);
294 
295 	sm_bar |= (uint_t)PHYSIO_LDH(csr_addr);
296 
297 	return (sm_bar);
298 }
299 
300 static int
301 cic_write_sm_bar(int board, int bus, uint_t sm_bar)
302 {
303 	int		cnt;
304 	u_longlong_t	csr_addr;
305 	uint_t		sm_bar_lsb, sm_bar_msb;
306 	procname_t	proc = "cic_write_sm_bar";
307 
308 	ASSERT(CPUID_TO_BOARDID(CPU->cpu_id) == board);
309 
310 	sm_bar_lsb = sm_bar & 0xffff;
311 	sm_bar_msb = (sm_bar >> 16) & 0xffff;
312 
313 	/*
314 	 * Before we can write to the CIC, we need to set
315 	 * up the CIC write data buffer in the PC.
316 	 */
317 	if (pc_prep_cic_buffer(CPU->cpu_id, sm_bar_msb) < 0)
318 		return (-1);
319 
320 	csr_addr = MAKE_CIC_CSR_PA(board,
321 				    CSR_TYPE_CIC,
322 				    CIC_SM_BAR_MSB_ADDR,
323 				    bus);
324 	PR_XF("%s:MSB: (bd=%d, bs=%d) csr_addr = 0x%llx\n",
325 		proc, board, bus, csr_addr);
326 	PR_XF("%s:MSB: sm_bar[31:16] = 0x%x\n",
327 		proc, (ushort_t)sm_bar_msb);
328 
329 	UPDATE_CIC_HISTORY(CICREG_SMBAR, board, bus, sm_bar);
330 
331 	PHYSIO_STH(csr_addr, (ushort_t)sm_bar_msb);
332 	for (cnt = 0;
333 	    ((uint_t)PHYSIO_LDH(csr_addr) != sm_bar_msb) && (cnt < 10);
334 	    cnt++)
335 		;
336 	if (cnt == 10) {
337 		cmn_err(CE_WARN,
338 			"IDN: 500: failed to write sm_bar (msb) (0x%x)",
339 			(uint_t)sm_bar_msb);
340 		return (-1);
341 	}
342 
343 	/*
344 	 * Now to LSB portion.
345 	 */
346 	if (pc_prep_cic_buffer(CPU->cpu_id, sm_bar_lsb) < 0)
347 		return (-1);
348 
349 	csr_addr = MAKE_CIC_CSR_PA(board,
350 				    CSR_TYPE_CIC,
351 				    CIC_SM_BAR_LSB_ADDR,
352 				    bus);
353 	PR_XF("%s:LSB: (bd=%d, bs=%d) csr_addr = 0x%llx\n",
354 		proc, board, bus, csr_addr);
355 	PR_XF("%s:LSB: sm_bar[15:0] = 0x%x\n",
356 		proc, (ushort_t)sm_bar_lsb);
357 
358 	PHYSIO_STH(csr_addr, (ushort_t)sm_bar_lsb);
359 	for (cnt = 0;
360 	    ((uint_t)PHYSIO_LDH(csr_addr) != sm_bar_lsb) && (cnt < 10);
361 	    cnt++)
362 		;
363 	if (cnt == 10) {
364 		cmn_err(CE_WARN,
365 			"IDN: 500: failed to write sm_bar (lsb) (0x%x)",
366 			(uint_t)sm_bar_lsb);
367 		return (-1);
368 	}
369 
370 	return (0);
371 }
372 
373 uint_t
374 cic_read_sm_lar(int board, int bus)
375 {
376 	u_longlong_t	csr_addr;
377 	uint_t		sm_lar;
378 	procname_t	proc = "cic_read_sm_lar";
379 
380 	ASSERT(CPUID_TO_BOARDID(CPU->cpu_id) == board);
381 
382 	csr_addr = MAKE_CIC_CSR_PA(board,
383 				    CSR_TYPE_CIC,
384 				    CIC_SM_LAR_MSB_ADDR,
385 				    bus);
386 	PR_XF("%s:MSB: (bd=%d, bs=%d) csr_addr = 0x%llx\n",
387 		proc, board, bus, csr_addr);
388 
389 	sm_lar = (uint_t)PHYSIO_LDH(csr_addr);
390 	sm_lar <<= 16;
391 
392 	csr_addr = MAKE_CIC_CSR_PA(board,
393 				    CSR_TYPE_CIC,
394 				    CIC_SM_LAR_LSB_ADDR,
395 				    bus);
396 	PR_XF("%s:LSB: (bd=%d, bs=%d) csr_addr = 0x%llx\n",
397 		proc, board, bus, csr_addr);
398 
399 	sm_lar |= (uint_t)PHYSIO_LDH(csr_addr);
400 
401 	return (sm_lar);
402 }
403 
404 static int
405 cic_write_sm_lar(int board, int bus, uint_t sm_lar)
406 {
407 	int		cnt;
408 	u_longlong_t	csr_addr;
409 	uint_t		sm_lar_lsb, sm_lar_msb;
410 	procname_t	proc = "cic_write_sm_lar";
411 
412 	ASSERT(CPUID_TO_BOARDID(CPU->cpu_id) == board);
413 
414 	sm_lar_lsb = sm_lar & 0xffff;
415 	sm_lar_msb = (sm_lar >> 16) & 0xffff;
416 
417 	/*
418 	 * Before we can write to the CIC, we need to set
419 	 * up the CIC write data buffer in the PC.
420 	 */
421 	if (pc_prep_cic_buffer(CPU->cpu_id, sm_lar_msb) < 0)
422 		return (-1);
423 
424 	csr_addr = MAKE_CIC_CSR_PA(board,
425 				    CSR_TYPE_CIC,
426 				    CIC_SM_LAR_MSB_ADDR,
427 				    bus);
428 	PR_XF("%s:MSB: (bd=%d, bs=%d) csr_addr = 0x%llx\n",
429 		proc, board, bus, csr_addr);
430 	PR_XF("%s:MSB: sm_lar[31:16] = 0x%x\n",
431 		proc, (ushort_t)sm_lar_msb);
432 
433 	UPDATE_CIC_HISTORY(CICREG_SMLAR, board, bus, sm_lar);
434 
435 	PHYSIO_STH(csr_addr, (ushort_t)sm_lar_msb);
436 	for (cnt = 0;
437 	    ((uint_t)PHYSIO_LDH(csr_addr) != sm_lar_msb) && (cnt < 10);
438 	    cnt++)
439 		;
440 	if (cnt == 10) {
441 		cmn_err(CE_WARN,
442 			"IDN: 501: failed to write sm_lar (msb) (0x%x)",
443 			(uint_t)sm_lar_msb);
444 		return (-1);
445 	}
446 
447 	/*
448 	 * Now to LSB portion.
449 	 */
450 	if (pc_prep_cic_buffer(CPU->cpu_id, sm_lar_lsb) < 0)
451 		return (-1);
452 
453 	csr_addr = MAKE_CIC_CSR_PA(board,
454 				    CSR_TYPE_CIC,
455 				    CIC_SM_LAR_LSB_ADDR,
456 				    bus);
457 	PR_XF("%s:LSB: (bd=%d, bs=%d) csr_addr = 0x%llx\n",
458 		proc, board, bus, csr_addr);
459 	PR_XF("%s:LSB: sm_lar[15:0] = 0x%x\n",
460 		proc, (ushort_t)sm_lar_lsb);
461 
462 	PHYSIO_STH(csr_addr, (ushort_t)sm_lar_lsb);
463 	for (cnt = 0;
464 	    ((uint_t)PHYSIO_LDH(csr_addr) != sm_lar_lsb) && (cnt < 10);
465 	    cnt++)
466 		;
467 	if (cnt == 10) {
468 		cmn_err(CE_WARN,
469 			"IDN: 501: failed to write sm_lar (lsb) (0x%x)",
470 			(uint_t)sm_lar_lsb);
471 		return (-1);
472 	}
473 
474 	return (0);
475 }
476 
477 static int
478 cic_get_smmask_bit(void)
479 {
480 	u_longlong_t	csr_addr;
481 	int		board;
482 	uint_t		config1;
483 	procname_t	proc = "cic_get_smmask_bit";
484 
485 	affinity_set(CPU_CURRENT);
486 
487 	board = CPUID_TO_BOARDID(CPU->cpu_id);
488 	/*
489 	 * Now that I'm stuck on this cpu I can go look at this
490 	 * board's CIC registers.
491 	 */
492 	csr_addr = MAKE_CIC_CSR_PA(board,
493 				    CSR_TYPE_CIC,
494 				    CIC_CONFIG1_ADDR,
495 				    0);
496 	PR_XF("%s: (bd=%d) csr_addr = 0x%llx (via cpu %d)\n",
497 		proc, board, csr_addr, (int)CPU->cpu_id);
498 
499 	config1 = (uint_t)PHYSIO_LDH(csr_addr);
500 
501 	config1 = CIC_CONFIG1_SMMASK_BIT(config1);
502 
503 	affinity_clear();
504 
505 	return (config1);
506 }
507 
508 static int
509 pc_prep_cic_buffer(int cpuid, uint_t cicdata)
510 {
511 	int		rv;
512 	int		brd, port;
513 	u_longlong_t	csr_addr;
514 	register int	cnt;
515 	procname_t	proc = "pc_prep_cic_buffer";
516 
517 
518 	ASSERT(CPU->cpu_id == cpuid);
519 
520 	port = cpuid % plat_max_cpu_units_per_board();
521 	brd = CPUID_TO_BOARDID(cpuid);
522 
523 	csr_addr = STARFIRE_PC_CICBUF_ADDR(brd, port);
524 
525 	/*
526 	 * csr_addr now points to CIC write buffer which resides
527 	 * in PC register space.
528 	 */
529 	PR_XF("%s: (cpu=%d) csr_addr = 0x%llx\n", proc, cpuid, csr_addr);
530 
531 	PHYSIO_ST(csr_addr, cicdata);
532 
533 	/*
534 	 * Now we need to read back the data to guarantee
535 	 * it got there.  Part of the PC protocol.
536 	 */
537 	for (cnt = 0; (PHYSIO_LD(csr_addr) != cicdata) && (cnt < 10);
538 	    cnt++)
539 		;
540 
541 	rv = 0;
542 	if (cnt == 10) {
543 		cmn_err(CE_WARN,
544 			"IDN: 502: unable to store data (0x%x) to "
545 			"CIC buffer (0x%llx)",
546 			cicdata, csr_addr);
547 		rv = -1;
548 	} else if (cnt >= 1) {
549 		PR_XF("%s: MULTIPLE READS (cpu=%d) cnt = %d\n",
550 			proc, cpuid, cnt);
551 	}
552 
553 	return (rv);
554 }
555 
556 /*
557  * --------------------------------------------------
558  * Write the given MC address decoding register contents (madr) of
559  * the respective remote board (rboard) into all the PCs located on
560  * the local board (lboard).
561  * --------------------------------------------------
562  */
563 static int
564 pc_write_madr(pda_handle_t ph, int lboard, int rboard, uint_t madr)
565 {
566 	u_longlong_t	pc_madr_addr;
567 	register int	p, ioc;
568 	register ushort_t	procset, iocset;
569 	int		rv = 0;
570 	uint_t		rd_madr;
571 	board_desc_t	*lbp;
572 	procname_t	proc = "pc_write_madr";
573 
574 	lbp = pda_get_board_info(ph, lboard);
575 
576 	ASSERT(lbp);
577 	ASSERT((lbp->bda_board & BDAN_MASK) == BDAN_GOOD);
578 
579 	procset = lbp->bda_proc;
580 	iocset  = lbp->bda_ioc;
581 
582 	/*
583 	 * Update the PCs for the cpus.
584 	 */
585 	for (p = 0; p < MAX_PROCMODS; procset >>= 4, p++) {
586 		int	i;
587 
588 		if (!((procset & BDAN_MASK) == BDAN_GOOD))
589 			continue;
590 
591 		pc_madr_addr = (u_longlong_t)STARFIRE_PC_MADR_ADDR(lboard,
592 							rboard, p);
593 
594 		/*
595 		 * On this first iteration of updating the PC
596 		 * we need to turn off the MADR VALID bit so that
597 		 * there's no accidental usage of the entry before
598 		 * all four bytes have been updated in the PC.
599 		 */
600 		if (madr != 0) {
601 			/*
602 			 * Need to clear valid bit on first
603 			 * go around.
604 			 */
605 			madr &= ~STARFIRE_PC_MADR_VALIDBIT;
606 		}
607 		PR_XF("%s: write madr(0x%x) to pc_addr(0x%llx) "
608 			"[lb=%d, rb=%d, cpu=%d]\n",
609 			proc, madr, pc_madr_addr, lboard, rboard, p);
610 		DEBUG_DELAY();
611 
612 		for (i = 0; i < 20; i++) {
613 			PHYSIO_ST(pc_madr_addr, madr);
614 			/*
615 			 * Read back for sanity check.
616 			 */
617 			rd_madr = PHYSIO_LD(pc_madr_addr);
618 			if (madr == rd_madr)
619 				break;
620 		}
621 		if (i > 0) {
622 			PR_XF("%s: WARNING: (1) lb=%d, rb=%d, "
623 				"madr=0x%x (i=%d)\n",
624 				proc, lboard, rboard, madr, i);
625 		}
626 		if (rd_madr != madr) {
627 			cmn_err(CE_WARN,
628 				"IDN: 503: (invalidate) failed to update "
629 				"PC madr (expected 0x%x, actual 0x%x)",
630 				madr, rd_madr);
631 			rv++;
632 			continue;
633 		}
634 		if (madr == 0) {
635 			continue;
636 		} else {
637 			/*
638 			 * Turn the valid bit back on.
639 			 */
640 			madr |= STARFIRE_PC_MADR_VALIDBIT;
641 		}
642 		PR_XF("%s: write madr(0x%x) to pc_addr(0x%llx) "
643 			"[lb=%d, rb=%d, cpu=%d]\n",
644 			proc, madr, pc_madr_addr, lboard, rboard, p);
645 		DEBUG_DELAY();
646 
647 		for (i = 0; i < 20; i++) {
648 			PHYSIO_ST(pc_madr_addr, madr);
649 			/*
650 			 * Read back for sanity check.
651 			 */
652 			rd_madr = PHYSIO_LD(pc_madr_addr);
653 			if (madr == rd_madr)
654 				break;
655 		}
656 		if (i > 0) {
657 			PR_XF("%s: WARNING: (2) lb=%d, rb=%d, "
658 				"madr=0x%x (i=%d)\n",
659 				proc, lboard, rboard, madr, i);
660 		}
661 		if (rd_madr != madr) {
662 			cmn_err(CE_WARN,
663 				"IDN: 503: (validate) failed to update "
664 				"PC madr (expected 0x%x, actual 0x%x)",
665 				madr, rd_madr);
666 			rv++;
667 		}
668 	}
669 	/*
670 	 * Update the PCs for the iocs.
671 	 */
672 	for (ioc = 0; ioc < MAX_IOCS; iocset >>= 4, ioc++) {
673 		int	i;
674 
675 		if (!((iocset & BDAN_MASK) == BDAN_GOOD))
676 			continue;
677 
678 		pc_madr_addr = (u_longlong_t)STARFIRE_PC_MADR_ADDR(lboard,
679 							rboard, ioc + 4);
680 
681 		if (madr != 0) {
682 			/*
683 			 * Need to clear valid bit on first
684 			 * go around.
685 			 */
686 			madr &= ~STARFIRE_PC_MADR_VALIDBIT;
687 		}
688 		PR_XF("%s: write madr(0x%x) to iopc_madr_addr(0x%llx) "
689 			"[lb=%d, rb=%d, ioc=%d]\n",
690 			proc, madr, pc_madr_addr, lboard, rboard, ioc);
691 		DEBUG_DELAY();
692 
693 		for (i = 0; i < 20; i++) {
694 			PHYSIO_ST(pc_madr_addr, madr);
695 			/*
696 			 * Read back for sanity check.
697 			 */
698 			rd_madr = PHYSIO_LD(pc_madr_addr);
699 			if (madr == rd_madr)
700 				break;
701 		}
702 		if (i > 0) {
703 			PR_XF("%s: WARNING: (3) lb=%d, rb=%d, "
704 				"madr=0x%x (i=%d)\n",
705 				proc, lboard, rboard, madr, i);
706 		}
707 		if (rd_madr != madr) {
708 			cmn_err(CE_WARN,
709 				"IDN: 504: (invalidate) failed to update "
710 				"IOPC madr (expected 0x%x, actual 0x%x)",
711 				madr, rd_madr);
712 			rv++;
713 			continue;
714 		}
715 
716 		if (madr == 0) {
717 			continue;
718 		} else {
719 			/*
720 			 * Turn the valid bit back on.
721 			 */
722 			madr |= STARFIRE_PC_MADR_VALIDBIT;
723 		}
724 
725 		PR_XF("%s: write madr(0x%x) to iopc_madr_addr(0x%llx) "
726 			"[lb=%d, rb=%d, ioc=%d]\n",
727 			proc, madr, pc_madr_addr, lboard, rboard, ioc);
728 		DEBUG_DELAY();
729 
730 		for (i = 0; i < 20; i++) {
731 			PHYSIO_ST(pc_madr_addr, madr);
732 			/*
733 			 * Read back for sanity check.
734 			 */
735 			rd_madr = PHYSIO_LD(pc_madr_addr);
736 			if (madr == rd_madr)
737 				break;
738 		}
739 		if (i > 0) {
740 			PR_XF("%s: WARNING: (4) lb=%d, rb=%d, "
741 				"madr=0x%x (i=%d)\n",
742 				proc, lboard, rboard, madr, i);
743 		}
744 		if (rd_madr != madr) {
745 			cmn_err(CE_WARN,
746 				"IDN: 504: (validate) failed to update "
747 				"IOPC madr (expected 0x%x, actual 0x%x)",
748 				madr, rd_madr);
749 			rv++;
750 		}
751 	}
752 
753 	return (rv ? -1 : 0);
754 }
755 
756 /*
757  * --------------------------------------------------
758  * Read the array of MC address decoding registers from one of the
759  * PCs on the local board (lboard) into the given in array (mc_adr).
760  * --------------------------------------------------
761  */
762 void
763 pc_read_madr(pda_handle_t ph, int lboard, uint_t mc_adr[], int local_only)
764 {
765 	u_longlong_t	pc_madr_addr;
766 	register int	p, ioc;
767 	register ushort_t	procset, iocset;
768 	int		brd;
769 	board_desc_t	*lbp;
770 
771 	lbp = pda_get_board_info(ph, lboard);
772 
773 	ASSERT(lbp);
774 	ASSERT((lbp->bda_board & BDAN_MASK) == BDAN_GOOD);
775 
776 	procset = lbp->bda_proc;
777 	iocset = lbp->bda_ioc;
778 
779 	for (p = 0; p < MAX_PROCMODS; procset >>= 4, p++)
780 		if ((procset & BDAN_MASK) == BDAN_GOOD)
781 			break;
782 
783 	if (p == MAX_PROCMODS) {
784 		/*
785 		 * Couldn't find a PC off a cpu, let's check the
786 		 * IOCs.
787 		 */
788 		for (ioc = 0; ioc < MAX_IOCS; iocset >>= 4, ioc++)
789 			if ((iocset & BDAN_MASK) == BDAN_GOOD)
790 				break;
791 		if (ioc == MAX_IOCS) {
792 			cmn_err(CE_WARN,
793 				"IDN: 505: board %d missing any valid PCs",
794 				lboard);
795 			return;
796 		}
797 		p = ioc + 4;
798 	}
799 
800 	pc_madr_addr = (u_longlong_t)STARFIRE_PC_MADR_ADDR(lboard, 0, p);
801 	/*
802 	 * pc_madr_addr = Starts at entry for board 0.
803 	 */
804 	for (brd = 0; brd < MAX_BOARDS; brd++) {
805 		/*
806 		 * It's possible our local PC may have old entries to
807 		 * AWOL domains.  Only want to pay attention to PC
808 		 * entries corresponding to our boards.
809 		 */
810 		lbp = pda_get_board_info(ph, brd);
811 		if (!local_only ||
812 				((lbp->bda_board & BDAN_MASK) == BDAN_GOOD))
813 			mc_adr[brd] = PHYSIO_LD(pc_madr_addr);
814 		else
815 			mc_adr[brd] = 0;
816 
817 		pc_madr_addr += ((u_longlong_t)1 <<
818 					STARFIRE_PC_MADR_BOARD_SHIFT);
819 	}
820 }
821 
822 /*
823  * --------------------------------------------------
824  * Read the MC address decoding register contents for all
825  * possible boards and store the results in their respective
826  * slot in mc_adr.  Keep a count of non-zero MC ADRs and
827  * return that.
828  * --------------------------------------------------
829  */
830 void
831 mc_get_adr_all(pda_handle_t ph, uint_t mc_adr[], int *nmcadr)
832 {
833 	int	brd;
834 	uint_t	madr[MAX_BOARDS];
835 
836 	/*
837 	 * Note that each PC has a complete copy of all MC contents
838 	 * and so all we have to do is read one PC rather than
839 	 * each of the MCs in the system.
840 	 */
841 	brd = CPUID_TO_BOARDID(CPU->cpu_id);
842 	pc_read_madr(ph, brd, madr, 1);
843 
844 	*nmcadr = 0;
845 	for (brd = 0; brd < MAX_BOARDS; brd++)
846 		if ((mc_adr[brd] = madr[brd]) != 0)
847 			(*nmcadr)++;
848 }
849 
850 static boardset_t
851 get_boardset(pda_handle_t ph, int *nboards)
852 {
853 	int		brd;
854 	int		nbrds = 0;
855 	boardset_t	bmask;
856 
857 	if (nboards != NULL)
858 		*nboards = 0;
859 
860 	bmask = 0;
861 	for (brd = 0; brd < MAX_BOARDS; brd++) {
862 		if (pda_board_present(ph, brd)) {
863 			bmask |= 1 << brd;
864 			nbrds++;
865 		}
866 	}
867 	if (nboards != NULL)
868 		*nboards = (short)nbrds;
869 
870 	return (bmask);
871 }
872 
873 int
874 update_local_hw_config(idn_domain_t *ldp, struct hwconfig *loc_hw)
875 {
876 	procname_t	proc = "update_local_hw_config";
877 
878 	ASSERT(IDN_DLOCK_IS_EXCL(ldp->domid));
879 	ASSERT(IDN_GLOCK_IS_EXCL());
880 	ASSERT(ldp == &idn_domain[idn.localid]);
881 
882 	if (ldp->dhw.dh_boardset != loc_hw->dh_boardset) {
883 		int	c;
884 
885 		PR_PROTO("%s: NEW HW CONFIG (old_bset = 0x%x, "
886 			"new_bset = 0x%x)\n",
887 			proc, ldp->dhw.dh_boardset, loc_hw->dh_boardset);
888 
889 		PR_PROTO("%s: clearing boardset 0x%x\n", proc,
890 			ldp->dhw.dh_boardset & ~loc_hw->dh_boardset);
891 		PR_PROTO("%s: setting boardset  0x%x\n", proc,
892 			loc_hw->dh_boardset & ~ldp->dhw.dh_boardset);
893 
894 		idn.dc_boardset &= ~ldp->dhw.dh_boardset;
895 		idn.dc_boardset |= loc_hw->dh_boardset;
896 		for (c = 0; c < NCPU; c++) {
897 			if (CPU_IN_SET(ldp->dcpuset, c)) {
898 				CPUSET_DEL(idn.dc_cpuset, c);
899 			}
900 		}
901 		CPUSET_OR(idn.dc_cpuset, cpu_ready_set);
902 
903 		bcopy(loc_hw, &ldp->dhw, sizeof (ldp->dhw));
904 		ldp->dcpuset = cpu_ready_set;
905 		ldp->dcpu    = cpu0.cpu_id;
906 		ldp->dncpus  = (int)ncpus;
907 		ldp->dvote.v.nmembrds = ldp->dhw.dh_nmcadr - 1;
908 		ldp->dvote.v.ncpus    = (int)ldp->dncpus - 1;
909 		ldp->dvote.v.board    = CPUID_TO_BOARDID(CPU->cpu_id);
910 
911 		return (1);
912 	} else {
913 		PR_PROTO("%s: NO change detected\n", proc);
914 		return (0);
915 	}
916 }
917 
918 int
919 get_hw_config(struct hwconfig *loc_hw)
920 {
921 	pda_handle_t	ph;
922 	boardset_t	domainset;
923 	int		bd;
924 	int		nmcadr;
925 	int		nboards;
926 	procname_t	proc = "get_hw_config";
927 
928 	ASSERT(loc_hw != NULL);
929 
930 	bzero(loc_hw, sizeof (*loc_hw));
931 	/*
932 	 * See if sm_mask is writable.
933 	 * XXX - Should be the same for all CIC's.  Do we
934 	 *	 we need to verify?
935 	 */
936 	if (cic_get_smmask_bit() == 0) {
937 		/*
938 		 * If smmask is not writable, we can not allow
939 		 * IDN operations.
940 		 */
941 		cmn_err(CE_WARN,
942 			"IDN: 506: cic sm_mask is not writeable");
943 		return (-1);
944 	}
945 	/*
946 	 * Map in the post2obp structure so we can find
947 	 * valid boards and hardware asics.
948 	 */
949 	ph = pda_open();
950 	if (ph == (pda_handle_t)NULL) {
951 		cmn_err(CE_WARN,
952 			"IDN: 507: failed to map-in post2obp structure");
953 		return (-1);
954 	} else if (!pda_is_valid(ph)) {
955 		cmn_err(CE_WARN, "IDN: 508: post2obp checksum invalid");
956 		pda_close(ph);
957 		return (-1);
958 	}
959 	/*
960 	 * Need to read the MC address decoding registers
961 	 * so that they can be given to other domains.
962 	 */
963 	loc_hw->dh_boardset = get_boardset(ph, &nboards);
964 	loc_hw->dh_nboards = (short)nboards;
965 	ASSERT(loc_hw->dh_boardset & (1 << CPUID_TO_BOARDID(CPU->cpu_id)));
966 
967 	mc_get_adr_all(ph, loc_hw->dh_mcadr, &nmcadr);
968 	loc_hw->dh_nmcadr = (short)nmcadr;
969 
970 	affinity_set(CPU_CURRENT);
971 	/*
972 	 * There will always be a bus 0 (logical).
973 	 */
974 	bd = CPUID_TO_BOARDID(CPU->cpu_id);
975 	domainset = (boardset_t)cic_read_domain_mask(bd, 0);
976 	affinity_clear();
977 
978 	if (!idn_cpu_per_board(ph, cpu_ready_set, loc_hw)) {
979 		pda_close(ph);
980 		return (-1);
981 	}
982 
983 	pda_close(ph);
984 
985 
986 #ifdef DEBUG
987 	{
988 		int	brd;
989 
990 		for (brd = 0; brd < MAX_BOARDS; brd++)
991 			if (loc_hw->dh_mcadr[brd] != 0) {
992 				PR_XF("%s: brd %d, mc = 0x%x\n",
993 					proc, brd, loc_hw->dh_mcadr[brd]);
994 			}
995 	}
996 #endif /* DEBUG */
997 
998 	if ((loc_hw->dh_boardset != domainset) || (loc_hw->dh_nmcadr < 1))
999 		return (-1);
1000 	else
1001 		return (0);
1002 }
1003 
1004 /*
1005  * Function called via timeout() to wakeup a possibly stuck
1006  * idnxf_shmem_update_all() should not all cpus check-in after a
1007  * x-call to update their respective CICs.
1008  */
1009 /*ARGSUSED0*/
1010 static void
1011 idnxf_shmem_wakeup(void *arg)
1012 {
1013 	struct idnxf_cic_info	*idnxfp = (struct idnxf_cic_info *)arg;
1014 	int		count;
1015 	int		expired;
1016 	procname_t	proc = "idnxf_shmem_wakeup";
1017 
1018 	expired = ((lbolt - idnxfp->xf_start_time) >= IDNCIC_TIMEOUT) ? 1 : 0;
1019 
1020 	if ((count = idnxfp->xf_count) == 0) {
1021 		/*
1022 		 * Everybody has finished.  Wakeup the requester.
1023 		 */
1024 		mutex_enter(&idnxfp->xf_mutex);
1025 		cv_signal(&idnxfp->xf_cv);
1026 		mutex_exit(&idnxfp->xf_mutex);
1027 
1028 	} else if ((count > 0) && expired) {
1029 		/*
1030 		 * There are still active cic updaters and time
1031 		 * has expired.  Bail on them.
1032 		 */
1033 		idnxfp->xf_errtimer = 1;
1034 #ifdef DEBUG
1035 		/*
1036 		 * Special debug case since idn_debug
1037 		 * may have been temporarily cleared
1038 		 * during xc_some.
1039 		 */
1040 		if ((idn_debug | o_idn_debug) & IDNDBG_REGS)
1041 			printf("%s: TIMEOUT...bailing on %d lost CIC "
1042 				"updates...\n", proc, count);
1043 #endif /* DEBUG */
1044 
1045 		ATOMIC_SUB(idnxfp->xf_count, count);
1046 
1047 		mutex_enter(&idnxfp->xf_mutex);
1048 		cv_signal(&idnxfp->xf_cv);
1049 		mutex_exit(&idnxfp->xf_mutex);
1050 
1051 	} else {
1052 		(void) timeout(idnxf_shmem_wakeup, (caddr_t)idnxfp,
1053 						(clock_t)IDNCIC_TIMECHK);
1054 	}
1055 }
1056 
1057 /*
1058  * Called indirectly from idnxf_shmem_update_all() via a xcall
1059  * for the recepient cpu to update the CICs on its respective
1060  * board.
1061  * IMPORTANT: NO console output from this routine!!
1062  */
1063 static void
1064 idnxf_shmem_update_one(uint64_t arg1, uint64_t arg2)
1065 {
1066 	struct idnxf_cic_info	*idnxfp = (struct idnxf_cic_info *)arg1;
1067 	time_t		start_time = (time_t)arg2;
1068 	int		rv, cpuid, brd, bus;
1069 	boardset_t	smmask;
1070 
1071 
1072 	cpuid = CPU->cpu_id;
1073 	brd   = CPUID_TO_BOARDID(cpuid);
1074 
1075 	if (idnxfp->xf_start_time != start_time) {
1076 		/*
1077 		 * Ooops!  Not my place to intrude.
1078 		 */
1079 		idnxf_cic_info.xf_errcic[brd][0] = IDNCIC_BUSY;
1080 		ATOMIC_INC(idnxf_cic_info.xf_errcnt);
1081 
1082 		goto done;
1083 	}
1084 
1085 	/*
1086 	 * We're executing out of the context of a cross-call
1087 	 * so we're effectively bound! :)
1088 	 */
1089 	for (bus = 0; bus < MAX_ABUSES; bus++) {
1090 		/*
1091 		 * XXX - need to worry about shuffle??
1092 		 */
1093 		if (!(idnxfp->xf_abus_mask & (1 << bus)))
1094 			continue;
1095 		smmask = cic_read_sm_mask(brd, bus);
1096 
1097 		if (idnxfp->xf_doadd) {
1098 			smmask |= idnxfp->xf_boardset;
1099 			(void) cic_write_sm_mask(brd, bus, smmask);
1100 
1101 			if (idnxfp->xf_smbase != (uint_t)-1) {
1102 				(void) cic_write_sm_bar(brd, bus,
1103 							idnxfp->xf_smbase);
1104 				(void) cic_write_sm_lar(brd, bus,
1105 							idnxfp->xf_smlimit);
1106 			}
1107 			/*
1108 			 * Verify data got there!
1109 			 */
1110 			rv = verify_smregs(brd, bus, smmask, idnxfp->xf_smbase,
1111 							idnxfp->xf_smlimit);
1112 		} else {
1113 			smmask &= ~idnxfp->xf_boardset;
1114 			(void) cic_write_sm_mask(brd, bus, smmask);
1115 
1116 			if (!smmask) {
1117 				/*
1118 				 * Update the LAR first so that we effectively
1119 				 * disable the register without possibly
1120 				 * opening the window to transaction we
1121 				 * don't care about.  Updating the LAR first
1122 				 * will guarantee we effectively turn it
1123 				 * off immediately.
1124 				 */
1125 				(void) cic_write_sm_lar(brd, bus, 0);
1126 				(void) cic_write_sm_bar(brd, bus, 1);
1127 
1128 				rv = verify_smregs(brd, bus, smmask, 1, 0);
1129 			} else {
1130 				rv = verify_smregs(brd, bus, smmask,
1131 							(uint_t)-1, (uint_t)-1);
1132 			}
1133 		}
1134 		if (rv) {
1135 			idnxf_cic_info.xf_errcic[brd][bus] = IDNCIC_ERR;
1136 			ATOMIC_INC(idnxf_cic_info.xf_errcnt);
1137 		} else {
1138 			idnxf_cic_info.xf_errcic[brd][bus] = IDNCIC_OK;
1139 		}
1140 	}
1141 
1142 done:
1143 	ATOMIC_DEC(idnxf_cic_info.xf_count);
1144 }
1145 
1146 static int
1147 idnxf_shmem_update_all(pda_handle_t ph, boardset_t boardset,
1148 			uint_t smbase, uint_t smlimit, int doadd)
1149 {
1150 	cpuset_t	target_cpuset;
1151 	int		target_count;
1152 	int		rv = 0;
1153 	int		c, brd, bus;
1154 	short		abus_mask;
1155 	time_t		start_time;
1156 	procname_t	proc = "idnxf_shmem_update_all";
1157 
1158 
1159 	ASSERT(MUTEX_HELD(&idn_xf_mutex));
1160 
1161 	pda_get_busmask(ph, &abus_mask, NULL);
1162 
1163 	CPUSET_ZERO(target_cpuset);
1164 	target_count = 0;
1165 	/*
1166 	 * Build a cpuset of target cpus (one per board) to
1167 	 * be used to send the CIC update xcall.
1168 	 */
1169 	for (brd = 0; brd < MAX_BOARDS; brd++) {
1170 		/*
1171 		 * Need to target an available cpu on the target board
1172 		 * so that we can look at the CICs on that board.
1173 		 */
1174 		c = board_to_ready_cpu(brd, cpu_ready_set);
1175 
1176 		if (c == -1) {
1177 			/*
1178 			 * If there's no cpu on this board, no
1179 			 * need to update the CICs.
1180 			 */
1181 			continue;
1182 		}
1183 		CPUSET_ADD(target_cpuset, c);
1184 		target_count++;
1185 	}
1186 
1187 	if (CPUSET_ISNULL(target_cpuset)) {
1188 		PR_REGS("%s: NO target cpus to update!!\n", proc);
1189 		return (0);
1190 	}
1191 
1192 	RESET_CIC_HISTORY();
1193 
1194 	/*
1195 	 * Broadcast out the CIC update request and then
1196 	 * sit back and wait for dinner to arrive!
1197 	 * Let's set up the global structure all the xcall
1198 	 * recepients will read.
1199 	 */
1200 	start_time = lbolt;
1201 	/*
1202 	 * Set the start time.  Make sure it's different
1203 	 * then the previous run.
1204 	 */
1205 	if (start_time <= idnxf_cic_info.xf_start_time)
1206 		start_time++;
1207 	idnxf_cic_info.xf_start_time = start_time;
1208 
1209 	idnxf_cic_info.xf_abus_mask = abus_mask;
1210 	idnxf_cic_info.xf_boardset = boardset;
1211 	idnxf_cic_info.xf_smbase = smbase;
1212 	idnxf_cic_info.xf_smlimit = smlimit;
1213 	idnxf_cic_info.xf_doadd = doadd;
1214 	idnxf_cic_info.xf_count = target_count;
1215 	idnxf_cic_info.xf_errcnt = 0;
1216 	idnxf_cic_info.xf_errtimer = 0;
1217 	bzero(&idnxf_cic_info.xf_errcic, sizeof (idnxf_cic_info.xf_errcic));
1218 
1219 	/*
1220 	 * Broadcast out the xcall to do the task.
1221 	 */
1222 #ifdef DEBUG
1223 	{
1224 		uint_t	tu32, tl32;
1225 
1226 		tu32 = UPPER32_CPUMASK(target_cpuset);
1227 		tl32 = LOWER32_CPUMASK(target_cpuset);
1228 		PR_REGS("%s: (start %ld) broadcasting CIC - "
1229 			"%s to cpus 0x%x.%0x\n",
1230 			proc, start_time, doadd ? "LINK" : "UNLINK",
1231 			tu32, tl32);
1232 	}
1233 
1234 	/*
1235 	 * Can't dump debug during cross-calls.
1236 	 */
1237 	o_idn_debug = idn_debug;
1238 	idn_debug = 0;
1239 #endif /* DEBUG */
1240 
1241 	xc_attention(target_cpuset);
1242 
1243 	xc_some(target_cpuset, idnxf_shmem_update_one,
1244 			(uint64_t)&idnxf_cic_info, (uint64_t)start_time);
1245 
1246 	xc_dismissed(target_cpuset);
1247 
1248 	ASSERT(idnxf_cic_info.xf_count == 0);
1249 
1250 #ifdef DEBUG
1251 	idn_debug = o_idn_debug;
1252 	o_idn_debug = 0;
1253 #endif /* DEBUG */
1254 
1255 	PR_REGS("%s: waiting for completion of %d CIC - %s...\n",
1256 		proc, idnxf_cic_info.xf_count, doadd ? "LINKS" : "UNLINKS");
1257 	PR_REGS("%s: CIC - %s have checked IN.\n",
1258 		proc, doadd ? "LINKS" : "UNLINKS");
1259 
1260 	/*
1261 	 * Modifying xf_start_time effectively disables any
1262 	 * possible outstanding xcall's since they don't touch
1263 	 * idnxf_cic_info unless their given start_time matches
1264 	 * that in the idnxf_cic_info structure.
1265 	 */
1266 	idnxf_cic_info.xf_start_time++;
1267 
1268 	PR_REGS("%s: xf_errcnt = %d, xf_errtimer = %d\n",
1269 		proc, idnxf_cic_info.xf_errcnt, idnxf_cic_info.xf_errtimer);
1270 	DUMP_CIC_HISTORY();
1271 	/*
1272 	 * Should errors be fatal? (panic).
1273 	 */
1274 	rv = 0;
1275 	for (c = 0; c < NCPU; c++) {
1276 		if (!CPU_IN_SET(target_cpuset, c))
1277 			continue;
1278 		brd = CPUID_TO_BOARDID(c);
1279 
1280 		for (bus = 0; bus < MAX_ABUSES; bus++) {
1281 
1282 			if (!(abus_mask & (1 << bus)))
1283 				continue;
1284 
1285 			switch (idnxf_cic_info.xf_errcic[brd][bus]) {
1286 			case IDNCIC_UNKNOWN:
1287 				/*
1288 				 * Unknown is only an error if the
1289 				 * timer expired.
1290 				 */
1291 				if (!idnxf_cic_info.xf_errtimer)
1292 					break;
1293 				cmn_err(CE_WARN,
1294 					"IDN: 509: CPU %d never responded "
1295 					"to CIC update", c);
1296 				/*FALLTHROUGH*/
1297 
1298 			case IDNCIC_ERR:
1299 				cmn_err(CE_WARN,
1300 					"IDN: 510: failed write-smregs "
1301 					"(bd=%d, bs=%d, sm(bar=0x%x, "
1302 					"lar=0x%x))",
1303 					brd, bus, smbase, smlimit);
1304 				rv++;
1305 				break;
1306 
1307 			case IDNCIC_BUSY:
1308 				cmn_err(CE_WARN, "IDN: 511: update-one "
1309 					"(cpu=%d, bd=%d) time conflict",
1310 					c, brd);
1311 				/*
1312 				 * Should never occur.  Not fatal,
1313 				 * just continue.
1314 				 */
1315 				break;
1316 
1317 			default:
1318 				PR_REGS("%s: board %d, bus %d "
1319 					"(bar=0x%x,lar=0x%x) - update OK\n",
1320 					proc, brd, bus, smbase, smlimit);
1321 				break;
1322 			}
1323 		}
1324 	}
1325 
1326 	return (rv ? -1 : 0);
1327 }
1328 
1329 /*
1330  * Add the respective boardset/base/limit/mcadr's to the local
1331  * domain's hardware configuration with respect to the SMR.
1332  *
1333  * is_master	Indicates remote domain is a master.
1334  */
1335 int
1336 idnxf_shmem_add(int is_master, boardset_t boardset,
1337 		pfn_t pfnbase, pfn_t pfnlimit,
1338 		uint_t *mcadr)
1339 {
1340 	int		rv = 0;
1341 	register int	brd, rbrd;
1342 	register boardset_t	localboardset;
1343 	uint_t		madr;
1344 	uint_t		smbase, smlimit;
1345 	pda_handle_t	ph;
1346 	procname_t	proc = "idnxf_shmem_add";
1347 
1348 
1349 	localboardset = idn_domain[idn.localid].dhw.dh_boardset;
1350 
1351 	ASSERT(localboardset && boardset && ((localboardset & boardset) == 0));
1352 	ASSERT(is_master ? (pfnbase && pfnlimit && mcadr) : 1);
1353 
1354 	if (pfnbase != PFN_INVALID) {
1355 		smbase  = (uint_t)PFN_TO_SMADDR(pfnbase);
1356 		smlimit = (uint_t)PFN_TO_SMADDR(pfnlimit);
1357 	} else {
1358 		smbase = smlimit = (uint_t)-1;
1359 	}
1360 	PR_REGS("%s: is_master=%d, boardset=0x%x, smbase=0x%x, smlimit=%x\n",
1361 		proc, is_master, boardset, smbase, smlimit);
1362 
1363 	/*
1364 	 * Need to serialize hardware access so we don't have multiple
1365 	 * threads attempting to access hardware regs simulataneously.
1366 	 * This should not be a significant performance penalty since
1367 	 * the hardware is only touched when domains are linking or
1368 	 * unlinking.
1369 	 */
1370 	mutex_enter(&idn_xf_mutex);
1371 
1372 	/*
1373 	 * Map in the post2obp structure so we can find
1374 	 * bus config information.
1375 	 */
1376 	ph = pda_open();
1377 	if (ph == (pda_handle_t)NULL) {
1378 		cmn_err(CE_WARN,
1379 			"IDN: 507: failed to map-in post2obp structure");
1380 		rv = -1;
1381 		goto done;
1382 
1383 	} else if (!pda_is_valid(ph)) {
1384 		cmn_err(CE_WARN, "IDN: 508: post2obp checksum invalid");
1385 		rv = -1;
1386 		goto done;
1387 	}
1388 	/*
1389 	 * Take a checkpoint in bbsram for diagnostic purposes.
1390 	 */
1391 	CHECKPOINT_OPENED(IDNSB_CHKPT_SMR, boardset, 1);
1392 
1393 	rv = idnxf_shmem_update_all(ph, boardset, smbase, smlimit, 1);
1394 
1395 	if (rv || (is_master == 0))
1396 		goto done;
1397 
1398 	/*
1399 	 * If this is a slave (i.e. remote domain is_master),
1400 	 * then we need to deprogram our PCs.
1401 	 */
1402 	PR_REGS("%s: updating PC regs (lboardset=0x%x, rboardset=0x%x)\n",
1403 		proc, localboardset, boardset);
1404 
1405 	for (brd = 0; brd < MAX_BOARDS; brd++) {
1406 
1407 		if (!BOARD_IN_SET(localboardset, brd))
1408 			continue;
1409 		/*
1410 		 * If this is a slave (i.e. remote domain is_master),
1411 		 * then we need to program our PCs.
1412 		 */
1413 		for (rbrd = 0; rbrd < MAX_BOARDS; rbrd++) {
1414 
1415 			if ((madr = mcadr[rbrd]) == 0)
1416 				continue;
1417 
1418 			ASSERT(BOARD_IN_SET(boardset, rbrd));
1419 			/*
1420 			 * Write the MC adr for the respective
1421 			 * remote board (rbrd) into the PCs of
1422 			 * the given local board (brd).
1423 			 */
1424 			if (pc_write_madr(ph, brd, rbrd, madr) < 0) {
1425 				cmn_err(CE_WARN,
1426 					"IDN: 512: failed [add] write-madr "
1427 					"(bd=%d, rbd=%d, madr=0x%x)",
1428 					brd, rbrd, madr);
1429 				rv = -1;
1430 				goto done;
1431 			}
1432 		}
1433 	}
1434 
1435 done:
1436 	if (ph)
1437 		pda_close(ph);
1438 
1439 	mutex_exit(&idn_xf_mutex);
1440 	/*
1441 	 * XXX
1442 	 *
1443 	 * Failure here is fatal.  Disable IDN?
1444 	 * NOn-zero return value will at least prevent
1445 	 * linkage with domain - probably sufficient.
1446 	 */
1447 	return (rv);
1448 }
1449 
1450 /*
1451  * Remove the respective boardset from the local domain's
1452  * hardware configuration with respect to the SMR.
1453  *
1454  * is_master	Indicates remote domain is a master.
1455  */
1456 int
1457 idnxf_shmem_sub(int is_master, boardset_t boardset)
1458 {
1459 	int		rv = 0;
1460 	register int	brd, rbrd;
1461 	register boardset_t	localboardset;
1462 	pda_handle_t	ph;
1463 	procname_t	proc = "idnxf_shmem_sub";
1464 
1465 	localboardset = idn_domain[idn.localid].dhw.dh_boardset;
1466 
1467 	ASSERT(localboardset && boardset && ((localboardset & boardset) == 0));
1468 
1469 	PR_REGS("%s: is_master=%d, boardset=0x%x\n",
1470 		proc, is_master, boardset);
1471 
1472 	/*
1473 	 * Need to serialize hardware access so we don't have multiple
1474 	 * threads attempting to access hardware regs simulataneously.
1475 	 * This should not be a significant performance penalty since
1476 	 * the hardware is only touched when domains are linking or
1477 	 * unlinking.
1478 	 */
1479 	mutex_enter(&idn_xf_mutex);
1480 
1481 	/*
1482 	 * Map in the post2obp structure so we can find
1483 	 * bus config information.
1484 	 */
1485 	ph = pda_open();
1486 	if (ph == (pda_handle_t)NULL) {
1487 		cmn_err(CE_WARN,
1488 			"IDN: 507: failed to map-in post2obp structure");
1489 		rv = -1;
1490 		goto done;
1491 
1492 	} else if (!pda_is_valid(ph)) {
1493 		cmn_err(CE_WARN, "IDN: 508: post2obp checksum invalid");
1494 		rv = -1;
1495 		goto done;
1496 	}
1497 	/*
1498 	 * Take a checkpoint in bbsram for diagnostic purposes.
1499 	 */
1500 	CHECKPOINT_CLOSED(IDNSB_CHKPT_SMR, boardset, 2);
1501 
1502 	rv = idnxf_shmem_update_all(ph, boardset, (uint_t)-1, (uint_t)-1, 0);
1503 
1504 	if (rv || (is_master == 0))
1505 		goto done;
1506 
1507 	/*
1508 	 * If this is a slave (i.e. remote domain is_master),
1509 	 * then we need to deprogram our PCs.
1510 	 */
1511 	PR_REGS("%s: reseting PC regs (lboardset=0x%x, rboardset=0x%x)\n",
1512 		proc, localboardset, boardset);
1513 
1514 	for (brd = 0; brd < MAX_BOARDS; brd++) {
1515 
1516 		if (!BOARD_IN_SET(localboardset, brd))
1517 			continue;
1518 
1519 		for (rbrd = 0; rbrd < MAX_BOARDS; rbrd++) {
1520 
1521 			if (!BOARD_IN_SET(boardset, rbrd))
1522 				continue;
1523 			/*
1524 			 * Clear the MC adr for the respective
1525 			 * remote board (rbrd) into the PCs of
1526 			 * the given local board (brd).
1527 			 */
1528 			if (pc_write_madr(ph, brd, rbrd, 0) < 0) {
1529 				cmn_err(CE_WARN,
1530 					"IDN: 512: failed [del] write-madr "
1531 					"(bd=%d, rbd=%d, madr=0x%x)",
1532 					brd, rbrd, 0);
1533 				rv = -1;
1534 				goto done;
1535 			}
1536 		}
1537 	}
1538 
1539 done:
1540 	if (ph)
1541 		pda_close(ph);
1542 	mutex_exit(&idn_xf_mutex);
1543 
1544 	return (rv);
1545 }
1546 
1547 /*
1548  * We cannot cross-trap cpu_flush_ecache since it references
1549  * %g7 via CPU.  It's possible that %g7 may not be set up
1550  * when the trap comes in, and could thus cause a crash.
1551  * Well...at least that's what has been happening when I
1552  * tried x-calls within an xc_attention (KMISS) panic.
1553  * Instead we use cross-calls.  However, since we can't
1554  * xc_attention around a cross-call, we have not guaranteed
1555  * way of knowing the operation succeeded.  To synchronize
1556  * this flush operation across cpus, we use a semaphore
1557  * which is V'd by the receiving cpus and P'd by the caller
1558  * initiating the all-cpus flush.
1559  */
1560 /*ARGSUSED0*/
1561 void
1562 idn_flush_ecache(uint64_t arg1, uint64_t arg2)
1563 {
1564 	extern void	cpu_flush_ecache(void);
1565 
1566 	cpu_flush_ecache();
1567 	/*
1568 	 * Paranoia...Give things a chance to drain.
1569 	 */
1570 	drv_usecwait(500000);	/* 500 msec */
1571 }
1572 /*
1573  * Flush the ecache's of all the cpus within this domain of
1574  * any possible SMR references.
1575  * This logic is borrowed from ecc.c:cpu_flush_ecache().
1576  */
1577 void
1578 idnxf_flushall_ecache()
1579 {
1580 	cpuset_t	local_cpuset;
1581 	procname_t	proc = "idnxf_flushall_ecache";
1582 
1583 
1584 	PR_XF("%s: flushing ecache (cpu_ready_set = 0x%x.%x)\n",
1585 		proc, UPPER32_CPUMASK(cpu_ready_set),
1586 		LOWER32_CPUMASK(cpu_ready_set));
1587 
1588 	CHECKPOINT_CACHE_CLEAR_DEBUG(1);
1589 	CHECKPOINT_CACHE_STEP_DEBUG(0x1, 2);
1590 
1591 	local_cpuset = cpu_ready_set;
1592 
1593 	xc_attention(local_cpuset);
1594 
1595 	/*
1596 	 * We tell each cpu to do a flush and then we hit
1597 	 * a semaphore to synchronize with all of them
1598 	 * to guarantee they have completed the flush before
1599 	 * we continue on.  We have to do this type of
1600 	 * sychronization since we can't xc_attention around
1601 	 * a cross-call.
1602 	 */
1603 	CHECKPOINT_CACHE_STEP_DEBUG(0x2, 3);
1604 
1605 	xc_all(idn_flush_ecache, 0, 0);
1606 
1607 	CHECKPOINT_CACHE_STEP_DEBUG(0x4, 4);
1608 
1609 	xc_dismissed(local_cpuset);
1610 
1611 	CHECKPOINT_CACHE_STEP_DEBUG(0x8, 5);
1612 }
1613 
1614 /*
1615  * --------------------------------------------------
1616  */
1617 static int
1618 verify_smregs(int brd, int bus, boardset_t smmask,
1619 		uint_t smbase, uint_t smlimit)
1620 {
1621 	int		rv = 0;
1622 	uint_t		smreg;
1623 
1624 	if (smmask != (boardset_t)-1) {
1625 		smreg = (uint_t)cic_read_sm_mask(brd, bus);
1626 		if (smreg != (uint_t)smmask) {
1627 			cmn_err(CE_WARN,
1628 				"IDN: 513: sm-mask error "
1629 				"(expected = 0x%x, actual = 0x%x)",
1630 				(uint_t)smmask, smreg);
1631 			rv++;
1632 		}
1633 	}
1634 
1635 	if (smbase != (uint_t)-1) {
1636 		smreg = cic_read_sm_bar(brd, bus);
1637 		if (smreg != smbase) {
1638 			cmn_err(CE_WARN,
1639 				"IDN: 514: sm-base error "
1640 				"(expected = 0x%x, actual = 0x%x)",
1641 				smbase, smreg);
1642 			rv++;
1643 		}
1644 	}
1645 
1646 	if (smlimit != (uint_t)-1) {
1647 		smreg = cic_read_sm_lar(brd, bus);
1648 		if (smreg != smlimit) {
1649 			cmn_err(CE_WARN,
1650 				"IDN: 515: sm-limit error "
1651 				"(expected = 0x%x, actual = 0x%x)",
1652 				smlimit, smreg);
1653 			rv++;
1654 		}
1655 	}
1656 
1657 	return (rv ? -1 : 0);
1658 }
1659 
1660 /*
1661  * -------------------------------------------------------------
1662  */
1663 int
1664 idn_cpu_per_board(pda_handle_t ph, cpuset_t cset, struct hwconfig *hwp)
1665 {
1666 	int		b, err = 0;
1667 	boardset_t	bset, cpu_bset;
1668 	board_desc_t	*lbp;
1669 
1670 	if (!idn_check_cpu_per_board)
1671 		return (1);
1672 
1673 	bset = hwp->dh_boardset;
1674 	CPUSET_TO_BOARDSET(cset, cpu_bset);
1675 
1676 	/*
1677 	 * Every board has at least one cpu, we're happy.
1678 	 */
1679 	if (cpu_bset == bset)
1680 		return (1);
1681 
1682 	/*
1683 	 * Well, not all boards had cpus.  That's okay so
1684 	 * long as they don't have memory also.
1685 	 * Get rid of the boards that have a cpu.
1686 	 */
1687 	bset &= ~cpu_bset;
1688 	/*
1689 	 * None of the remaining boards in the set shold have mem.
1690 	 */
1691 	err = 0;
1692 
1693 	/*
1694 	 * A NULL post2obp pointer indicates we're checking
1695 	 * the config of a remote domain.  Since we can't
1696 	 * look at the post2obp of the remote domain, we'll
1697 	 * have to trust what he passed us in his config.
1698 	 */
1699 	if (ph && !pda_is_valid(ph)) {
1700 		cmn_err(CE_WARN, "IDN: 508: post2obp checksum invalid");
1701 		return (0);
1702 	}
1703 
1704 	for (b = 0; b < MAX_BOARDS; b++) {
1705 		if (!BOARD_IN_SET(bset, b))
1706 			continue;
1707 
1708 		lbp = ph ? pda_get_board_info(ph, b) : NULL;
1709 
1710 		if ((lbp &&
1711 			(BDA_NBL(lbp->bda_board, BDA_MC_NBL) == BDAN_GOOD)) ||
1712 			(!lbp && hwp->dh_mcadr[b])) {
1713 			err++;
1714 			cmn_err(CE_WARN,
1715 				"IDN: 516: (%s) board %d has memory, "
1716 				"but no CPUs - CPU per memory board REQUIRED",
1717 				ph ? "local" : "remote", b);
1718 		}
1719 	}
1720 
1721 	return (err ? 0 : 1);
1722 }
1723