1*03831d35Sstevel /*
2*03831d35Sstevel  * CDDL HEADER START
3*03831d35Sstevel  *
4*03831d35Sstevel  * The contents of this file are subject to the terms of the
5*03831d35Sstevel  * Common Development and Distribution License (the "License").
6*03831d35Sstevel  * You may not use this file except in compliance with the License.
7*03831d35Sstevel  *
8*03831d35Sstevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*03831d35Sstevel  * or http://www.opensolaris.org/os/licensing.
10*03831d35Sstevel  * See the License for the specific language governing permissions
11*03831d35Sstevel  * and limitations under the License.
12*03831d35Sstevel  *
13*03831d35Sstevel  * When distributing Covered Code, include this CDDL HEADER in each
14*03831d35Sstevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*03831d35Sstevel  * If applicable, add the following below this CDDL HEADER, with the
16*03831d35Sstevel  * fields enclosed by brackets "[]" replaced with your own identifying
17*03831d35Sstevel  * information: Portions Copyright [yyyy] [name of copyright owner]
18*03831d35Sstevel  *
19*03831d35Sstevel  * CDDL HEADER END
20*03831d35Sstevel  */
21*03831d35Sstevel 
22*03831d35Sstevel /*
23*03831d35Sstevel  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*03831d35Sstevel  * Use is subject to license terms.
25*03831d35Sstevel  */
26*03831d35Sstevel 
27*03831d35Sstevel #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*03831d35Sstevel 
29*03831d35Sstevel #include <sys/cpuvar.h>
30*03831d35Sstevel #include <sys/cpu_module.h>
31*03831d35Sstevel #include <sys/kmem.h>
32*03831d35Sstevel #include <sys/sunddi.h>
33*03831d35Sstevel #include <sys/param.h>
34*03831d35Sstevel #include <sys/obpdefs.h>
35*03831d35Sstevel #include <sys/prom_plat.h>
36*03831d35Sstevel #include <sys/sgsbbc_mailbox.h>
37*03831d35Sstevel #include <sys/sbd_ioctl.h>
38*03831d35Sstevel #include <sys/sbdp_priv.h>
39*03831d35Sstevel #include <sys/sbdp_mbox.h>
40*03831d35Sstevel #include <sys/promif.h>
41*03831d35Sstevel #include <sys/plat_ecc_dimm.h>
42*03831d35Sstevel 
43*03831d35Sstevel #define	UNKNOWN "unknown"
44*03831d35Sstevel #define	INITL_STATUS	0xdead
45*03831d35Sstevel 
46*03831d35Sstevel int sbdp_mbox_wait = 86400;	/* in seconds */
47*03831d35Sstevel int sbdp_shw_bd_wait = 5;	/* in seconds */
48*03831d35Sstevel 
49*03831d35Sstevel int sbdp_sc_err_translation(int);
50*03831d35Sstevel int sbdp_poweroff_wkaround = 1;
51*03831d35Sstevel 
52*03831d35Sstevel /*
53*03831d35Sstevel  * By default, DR of non-Panther procs is not allowed into a Panther
54*03831d35Sstevel  * domain with large page sizes enabled.  Setting this to 0 will remove
55*03831d35Sstevel  * the restriction.
56*03831d35Sstevel  */
57*03831d35Sstevel static int sbdp_large_page_restriction = 1;
58*03831d35Sstevel 
59*03831d35Sstevel /*
60*03831d35Sstevel  * Initialize the data structs for the common part of the pkts
61*03831d35Sstevel  */
62*03831d35Sstevel void
sbdp_init_msg_pkt(sbbc_msg_t * msg,uint16_t sub_type,int len,caddr_t buf)63*03831d35Sstevel sbdp_init_msg_pkt(sbbc_msg_t *msg, uint16_t sub_type, int len, caddr_t buf)
64*03831d35Sstevel {
65*03831d35Sstevel 	msg->msg_type.type = DR_MBOX;
66*03831d35Sstevel 	msg->msg_type.sub_type = sub_type;
67*03831d35Sstevel 	msg->msg_status = INITL_STATUS;
68*03831d35Sstevel 	msg->msg_len = len;
69*03831d35Sstevel 	msg->msg_buf = buf;
70*03831d35Sstevel 	msg->msg_data[0] = 0;
71*03831d35Sstevel 	msg->msg_data[1] = 0;
72*03831d35Sstevel 
73*03831d35Sstevel }
74*03831d35Sstevel 
75*03831d35Sstevel /*
76*03831d35Sstevel  * Convert a showboard data structure to the board structure shared
77*03831d35Sstevel  * between sbd and sbdp
78*03831d35Sstevel  */
79*03831d35Sstevel void
sbdp_showbd_2_sbd_stat(show_board_t * shbp,sbd_stat_t * stp,int board)80*03831d35Sstevel sbdp_showbd_2_sbd_stat(show_board_t *shbp, sbd_stat_t *stp, int board)
81*03831d35Sstevel {
82*03831d35Sstevel 	static fn_t	f = "sbdp_showbd_2_sbd_stat";
83*03831d35Sstevel 
84*03831d35Sstevel 	SBDP_DBG_FUNC("%s\n", f);
85*03831d35Sstevel 
86*03831d35Sstevel 	stp->s_board = board;
87*03831d35Sstevel 	(void) strcpy(stp->s_info, shbp->s_info);
88*03831d35Sstevel 	stp->s_power = shbp->s_power;
89*03831d35Sstevel 
90*03831d35Sstevel 	(void) strcpy(stp->s_type, shbp->s_type);
91*03831d35Sstevel 
92*03831d35Sstevel 	if (shbp->s_present == 0) {
93*03831d35Sstevel 		/*
94*03831d35Sstevel 		 * This should go away since the SC should put the unknown
95*03831d35Sstevel 		 * We leave this here so Symon and other scripts don't have
96*03831d35Sstevel 		 * a problem
97*03831d35Sstevel 		 */
98*03831d35Sstevel 		(void) strcpy(stp->s_type, UNKNOWN);
99*03831d35Sstevel 		stp->s_rstate = SBD_STAT_EMPTY;
100*03831d35Sstevel 	} else if (shbp->s_claimed == 0)
101*03831d35Sstevel 		stp->s_rstate = SBD_STAT_DISCONNECTED;
102*03831d35Sstevel 	else
103*03831d35Sstevel 		stp->s_rstate = SBD_STAT_CONNECTED;
104*03831d35Sstevel 
105*03831d35Sstevel 
106*03831d35Sstevel 	stp->s_assigned = shbp->s_assigned;
107*03831d35Sstevel 	stp->s_cond = shbp->s_cond;
108*03831d35Sstevel }
109*03831d35Sstevel 
110*03831d35Sstevel /*
111*03831d35Sstevel  * Entry point from sbd.  Get the status from the SC and then convert
112*03831d35Sstevel  * the info returned into something that sbd understands
113*03831d35Sstevel  * If the request times out or fails other than an illegal transaction
114*03831d35Sstevel  * copy the info from our inventory
115*03831d35Sstevel  */
116*03831d35Sstevel int
sbdp_get_board_status(sbdp_handle_t * hp,sbd_stat_t * stp)117*03831d35Sstevel sbdp_get_board_status(sbdp_handle_t *hp, sbd_stat_t *stp)
118*03831d35Sstevel {
119*03831d35Sstevel 	int		board = hp->h_board;
120*03831d35Sstevel 	int		node = hp->h_wnode;
121*03831d35Sstevel 	sbbc_msg_t	request, *reqp = &request;
122*03831d35Sstevel 	sbbc_msg_t	response, *resp = &response;
123*03831d35Sstevel 	info_t		inform, *informp = &inform;
124*03831d35Sstevel 	show_board_t	show_bd, *shbp = &show_bd;
125*03831d35Sstevel 	int		rv = 0;
126*03831d35Sstevel 	sbd_error_t	*sep = hp->h_err;
127*03831d35Sstevel 	int		len;
128*03831d35Sstevel 	sbdp_bd_t	*bdp;
129*03831d35Sstevel 	static fn_t	f = "sbdp_get_board_status";
130*03831d35Sstevel 
131*03831d35Sstevel 	SBDP_DBG_FUNC("%s\n", f);
132*03831d35Sstevel 
133*03831d35Sstevel 	/*
134*03831d35Sstevel 	 * Check for options.  If there are any, fail the operation
135*03831d35Sstevel 	 */
136*03831d35Sstevel 	if (hp->h_opts != NULL && hp->h_opts->copts != NULL) {
137*03831d35Sstevel 		sbdp_set_err(sep, ESBD_INVAL_OPT, hp->h_opts->copts);
138*03831d35Sstevel 		return (-1);
139*03831d35Sstevel 	}
140*03831d35Sstevel 
141*03831d35Sstevel 	bdp = sbdp_get_bd_info(node, board);
142*03831d35Sstevel 
143*03831d35Sstevel 	informp->board = board;
144*03831d35Sstevel 	informp->node = node;
145*03831d35Sstevel 	informp->revision = 0xdead;
146*03831d35Sstevel 	len = sizeof (info_t);
147*03831d35Sstevel 
148*03831d35Sstevel 	sbdp_init_msg_pkt(reqp, DR_MBOX_SHOW_BOARD, len, (caddr_t)informp);
149*03831d35Sstevel 
150*03831d35Sstevel 	bzero(shbp, sizeof (show_board_t));
151*03831d35Sstevel 	shbp->s_cond = -1;
152*03831d35Sstevel 	shbp->s_power = -1;
153*03831d35Sstevel 	shbp->s_assigned = -1;
154*03831d35Sstevel 	shbp->s_claimed = -1;
155*03831d35Sstevel 	shbp->s_present = -1;
156*03831d35Sstevel 	len = sizeof (show_board_t);
157*03831d35Sstevel 
158*03831d35Sstevel 	sbdp_init_msg_pkt(resp, DR_MBOX_SHOW_BOARD, len, (caddr_t)shbp);
159*03831d35Sstevel 
160*03831d35Sstevel 	rv = sbbc_mbox_request_response(reqp, resp, sbdp_shw_bd_wait);
161*03831d35Sstevel 
162*03831d35Sstevel 	SBDP_DBG_MISC("show board completed: rv = %d\n", rv);
163*03831d35Sstevel 
164*03831d35Sstevel 	/*
165*03831d35Sstevel 	 * This domain has no access to this board. Return failure
166*03831d35Sstevel 	 */
167*03831d35Sstevel 	if ((resp->msg_status == SG_MBOX_STATUS_BOARD_ACCESS_DENIED) ||
168*03831d35Sstevel 		(resp->msg_status == SG_MBOX_STATUS_ILLEGAL_SLOT) ||
169*03831d35Sstevel 		(resp->msg_status == SG_MBOX_STATUS_ILLEGAL_NODE)) {
170*03831d35Sstevel 
171*03831d35Sstevel 		/*
172*03831d35Sstevel 		 * invalidate cached copy.
173*03831d35Sstevel 		 */
174*03831d35Sstevel 		bdp->valid_cp = -1;
175*03831d35Sstevel 
176*03831d35Sstevel 		sbdp_set_err(sep, ESGT_GET_BOARD_STAT, NULL);
177*03831d35Sstevel 		return (EIO);
178*03831d35Sstevel 	}
179*03831d35Sstevel 
180*03831d35Sstevel 	/*
181*03831d35Sstevel 	 * If we get any error see if we can return a cached copy of the
182*03831d35Sstevel 	 * board info.  If one exists turn the busy flag on
183*03831d35Sstevel 	 */
184*03831d35Sstevel 	if (rv != 0) {
185*03831d35Sstevel 		mutex_enter(&bdp->bd_mutex);
186*03831d35Sstevel 		if (bdp->valid_cp == -1) {
187*03831d35Sstevel 			sbdp_set_err(sep, ESGT_GET_BOARD_STAT,
188*03831d35Sstevel 			    NULL);
189*03831d35Sstevel 			mutex_exit(&bdp->bd_mutex);
190*03831d35Sstevel 			return (EIO);
191*03831d35Sstevel 		}
192*03831d35Sstevel 
193*03831d35Sstevel 		/*
194*03831d35Sstevel 		 * we have a valid copy.  Return it and set the
195*03831d35Sstevel 		 * busy flag on so the user know this is not the most
196*03831d35Sstevel 		 * recent copy
197*03831d35Sstevel 		 */
198*03831d35Sstevel 		bcopy(bdp->bd_sc, shbp, sizeof (show_board_t));
199*03831d35Sstevel 		mutex_exit(&bdp->bd_mutex);
200*03831d35Sstevel 		stp->s_busy = 1;
201*03831d35Sstevel 		/*
202*03831d35Sstevel 		 * The sbbc returns the error in both parts (i.e rv and status)
203*03831d35Sstevel 		 * so since we just took care of it reset rv
204*03831d35Sstevel 		 */
205*03831d35Sstevel 		rv = 0;
206*03831d35Sstevel 	} else {
207*03831d35Sstevel 		/*
208*03831d35Sstevel 		 * revalidate our copy of the returned data
209*03831d35Sstevel 		 */
210*03831d35Sstevel 		if (bdp == NULL) {
211*03831d35Sstevel 			SBDP_DBG_MBOX("HUGE ERROR\n");
212*03831d35Sstevel 		} else {
213*03831d35Sstevel 			mutex_enter(&bdp->bd_mutex);
214*03831d35Sstevel 			bcopy(shbp, bdp->bd_sc, sizeof (show_board_t));
215*03831d35Sstevel 			bdp->valid_cp = 1;
216*03831d35Sstevel 			mutex_exit(&bdp->bd_mutex);
217*03831d35Sstevel 		}
218*03831d35Sstevel 	}
219*03831d35Sstevel 
220*03831d35Sstevel 
221*03831d35Sstevel 	SBDP_DBG_MBOX("Showboard: board\t%d\n\trevision\t%d\n\ts_cond\t%d\n\t"
222*03831d35Sstevel 		"s_power\t%d\n\ts_assigned\t%d\n\ts_claimed\t%d\n\t"
223*03831d35Sstevel 		"s_present\t%d\n\ts_ledstatus\t%d\n\ts_type\t%s\n\t"
224*03831d35Sstevel 		"s_info\t%s\n",
225*03831d35Sstevel 			board, shbp->revision, shbp->s_cond, shbp->s_power,
226*03831d35Sstevel 			shbp->s_assigned, shbp->s_claimed, shbp->s_present,
227*03831d35Sstevel 			shbp->s_ledstatus, shbp->s_type, shbp->s_info);
228*03831d35Sstevel 
229*03831d35Sstevel 	/*
230*03831d35Sstevel 	 * Now that we got the info run through the sbd-sbdp translator
231*03831d35Sstevel 	 */
232*03831d35Sstevel 	sbdp_showbd_2_sbd_stat(shbp, stp, board);
233*03831d35Sstevel 
234*03831d35Sstevel 	/*
235*03831d35Sstevel 	 * Last add the platform options
236*03831d35Sstevel 	 */
237*03831d35Sstevel 	SBDP_PLATFORM_OPTS(stp->s_platopts);
238*03831d35Sstevel 
239*03831d35Sstevel 	return (rv);
240*03831d35Sstevel }
241*03831d35Sstevel 
242*03831d35Sstevel /*
243*03831d35Sstevel  * Entry point from sbd.  Call down to the SC to assign the board
244*03831d35Sstevel  * We simply return the status the SC told us
245*03831d35Sstevel  */
246*03831d35Sstevel int
sbdp_assign_board(sbdp_handle_t * hp)247*03831d35Sstevel sbdp_assign_board(sbdp_handle_t *hp)
248*03831d35Sstevel {
249*03831d35Sstevel 	int		board = hp->h_board;
250*03831d35Sstevel 	int		node = hp->h_wnode;
251*03831d35Sstevel 	sbbc_msg_t	request, *reqp = &request;
252*03831d35Sstevel 	sbbc_msg_t	response, *resp = &response;
253*03831d35Sstevel 	int		cmd_rev = -1;
254*03831d35Sstevel 	info2_t		inform, *informp = &inform;
255*03831d35Sstevel 	int		rv = 0;
256*03831d35Sstevel 	sbd_error_t	*sep;
257*03831d35Sstevel 	int		len;
258*03831d35Sstevel 	static fn_t	f = "sbdp_assign_board";
259*03831d35Sstevel 
260*03831d35Sstevel 	SBDP_DBG_FUNC("%s\n", f);
261*03831d35Sstevel 
262*03831d35Sstevel 	sep = hp->h_err;
263*03831d35Sstevel 	/*
264*03831d35Sstevel 	 * Check for options.  If there are any, fail the operation
265*03831d35Sstevel 	 */
266*03831d35Sstevel 	if (hp->h_opts != NULL && hp->h_opts->copts != NULL) {
267*03831d35Sstevel 		sbdp_set_err(sep, ESBD_INVAL_OPT, hp->h_opts->copts);
268*03831d35Sstevel 		return (-1);
269*03831d35Sstevel 	}
270*03831d35Sstevel 
271*03831d35Sstevel 	informp->board = board;
272*03831d35Sstevel 	informp->node = node;
273*03831d35Sstevel 	informp->extra = SBDP_ASSIGN;
274*03831d35Sstevel 	len =	sizeof (info2_t);
275*03831d35Sstevel 
276*03831d35Sstevel 	sbdp_init_msg_pkt(reqp, DR_MBOX_ASSIGN, len, (caddr_t)informp);
277*03831d35Sstevel 
278*03831d35Sstevel 	len =  sizeof (cmd_rev);
279*03831d35Sstevel 
280*03831d35Sstevel 	sbdp_init_msg_pkt(resp, DR_MBOX_ASSIGN, len, (caddr_t)&cmd_rev);
281*03831d35Sstevel 
282*03831d35Sstevel 	rv = sbbc_mbox_request_response(reqp, resp, sbdp_mbox_wait);
283*03831d35Sstevel 
284*03831d35Sstevel 	if (rv != 0 || (rv = resp->msg_status != SG_MBOX_STATUS_SUCCESS)) {
285*03831d35Sstevel 		SBDP_DBG_MISC("failed to assign board: rv = %d\n", rv);
286*03831d35Sstevel 		sbdp_set_err(sep, sbdp_sc_err_translation(resp->msg_status),
287*03831d35Sstevel 		    NULL);
288*03831d35Sstevel 	}
289*03831d35Sstevel 
290*03831d35Sstevel 	return (rv);
291*03831d35Sstevel }
292*03831d35Sstevel 
293*03831d35Sstevel /*
294*03831d35Sstevel  * Entry point from sbd.  Call down to the SC to unassign the board
295*03831d35Sstevel  * We simply return the status the SC told us
296*03831d35Sstevel  */
297*03831d35Sstevel int
sbdp_unassign_board(sbdp_handle_t * hp)298*03831d35Sstevel sbdp_unassign_board(sbdp_handle_t *hp)
299*03831d35Sstevel {
300*03831d35Sstevel 	int		board = hp->h_board;
301*03831d35Sstevel 	int		node = hp->h_wnode;
302*03831d35Sstevel 	sbbc_msg_t	request, *reqp = &request;
303*03831d35Sstevel 	sbbc_msg_t	response, *resp = &response;
304*03831d35Sstevel 	int		cmd_rev = -1;
305*03831d35Sstevel 	info2_t		inform, *informp = &inform;
306*03831d35Sstevel 	int		rv = 0;
307*03831d35Sstevel 	sbd_error_t	*sep;
308*03831d35Sstevel 	int		len;
309*03831d35Sstevel 	static fn_t	f = "sbdp_unassign_board";
310*03831d35Sstevel 
311*03831d35Sstevel 	SBDP_DBG_FUNC("%s\n", f);
312*03831d35Sstevel 
313*03831d35Sstevel 	sep = hp->h_err;
314*03831d35Sstevel 	/*
315*03831d35Sstevel 	 * Check for options.  If there are any, fail the operation
316*03831d35Sstevel 	 */
317*03831d35Sstevel 	if (hp->h_opts != NULL && hp->h_opts->copts != NULL) {
318*03831d35Sstevel 		sbdp_set_err(sep, ESBD_INVAL_OPT, hp->h_opts->copts);
319*03831d35Sstevel 		return (-1);
320*03831d35Sstevel 	}
321*03831d35Sstevel 
322*03831d35Sstevel 	informp->board = board;
323*03831d35Sstevel 	informp->node = node;
324*03831d35Sstevel 	informp->extra = SBDP_UNASSIGN;
325*03831d35Sstevel 	len =	sizeof (info2_t);
326*03831d35Sstevel 
327*03831d35Sstevel 	sbdp_init_msg_pkt(reqp, DR_MBOX_ASSIGN, len, (caddr_t)informp);
328*03831d35Sstevel 
329*03831d35Sstevel 	len =  sizeof (cmd_rev);
330*03831d35Sstevel 
331*03831d35Sstevel 	sbdp_init_msg_pkt(resp, DR_MBOX_ASSIGN, len, (caddr_t)&cmd_rev);
332*03831d35Sstevel 
333*03831d35Sstevel 	rv = sbbc_mbox_request_response(reqp, resp, sbdp_mbox_wait);
334*03831d35Sstevel 
335*03831d35Sstevel 	if (rv != 0 || (rv = resp->msg_status != SG_MBOX_STATUS_SUCCESS)) {
336*03831d35Sstevel 		SBDP_DBG_MISC("failed to unassign board: rv = %d\n", rv);
337*03831d35Sstevel 		sbdp_set_err(sep, sbdp_sc_err_translation(resp->msg_status),
338*03831d35Sstevel 		    NULL);
339*03831d35Sstevel 	}
340*03831d35Sstevel 
341*03831d35Sstevel 	return (rv);
342*03831d35Sstevel }
343*03831d35Sstevel 
344*03831d35Sstevel static int
sg_attach_board(void * arg)345*03831d35Sstevel sg_attach_board(void *arg)
346*03831d35Sstevel {
347*03831d35Sstevel 	sbdp_handle_t	*hp;
348*03831d35Sstevel 	cpuset_t	cset;
349*03831d35Sstevel 	int		rv;
350*03831d35Sstevel 	static fn_t	f = "sg_attach_board";
351*03831d35Sstevel 
352*03831d35Sstevel 	SBDP_DBG_FUNC("%s\n", f);
353*03831d35Sstevel 
354*03831d35Sstevel 	hp = (sbdp_handle_t *)arg;
355*03831d35Sstevel 
356*03831d35Sstevel 	cset = cpu_ready_set;
357*03831d35Sstevel 	promsafe_xc_attention(cset);
358*03831d35Sstevel 	rv = prom_serengeti_attach_board(hp->h_wnode, hp->h_board);
359*03831d35Sstevel 	xc_dismissed(cset);
360*03831d35Sstevel 
361*03831d35Sstevel 	return (rv);
362*03831d35Sstevel }
363*03831d35Sstevel 
364*03831d35Sstevel static int
sg_detach_board(void * arg)365*03831d35Sstevel sg_detach_board(void *arg)
366*03831d35Sstevel {
367*03831d35Sstevel 	sbdp_handle_t	*hp;
368*03831d35Sstevel 	cpuset_t	cset;
369*03831d35Sstevel 	int		rv;
370*03831d35Sstevel 	static fn_t	f = "sg_detach_board";
371*03831d35Sstevel 
372*03831d35Sstevel 	SBDP_DBG_FUNC("%s\n", f);
373*03831d35Sstevel 
374*03831d35Sstevel 	hp = (sbdp_handle_t *)arg;
375*03831d35Sstevel 
376*03831d35Sstevel 	cset = cpu_ready_set;
377*03831d35Sstevel 	promsafe_xc_attention(cset);
378*03831d35Sstevel 	rv = prom_serengeti_detach_board(hp->h_wnode, hp->h_board);
379*03831d35Sstevel 	xc_dismissed(cset);
380*03831d35Sstevel 
381*03831d35Sstevel 	return (rv);
382*03831d35Sstevel }
383*03831d35Sstevel 
384*03831d35Sstevel /*
385*03831d35Sstevel  * Entry point from sbd.  First we call down to the SC to "attach/claim" this
386*03831d35Sstevel  * board.  As a side effect the SC updates the pda info so obp can create the
387*03831d35Sstevel  * device tree.  If we are successful, we ask OBP to probe the board.  OBP
388*03831d35Sstevel  * creates new nodes on its own obp tree
389*03831d35Sstevel  * As an added bonus, since we don't use the inkernel prober, we need to create
390*03831d35Sstevel  * the dev_info nodes but just to a point where they are created but
391*03831d35Sstevel  * Solaris can't use them (i.e BIND)
392*03831d35Sstevel  */
393*03831d35Sstevel int
sbdp_connect_board(sbdp_handle_t * hp)394*03831d35Sstevel sbdp_connect_board(sbdp_handle_t *hp)
395*03831d35Sstevel {
396*03831d35Sstevel 	sbbc_msg_t	request, *reqp = &request;
397*03831d35Sstevel 	sbbc_msg_t	response, *resp = &response;
398*03831d35Sstevel 	int		rv = 0;
399*03831d35Sstevel 	int		board, node;
400*03831d35Sstevel 	sbd_error_t	*sep;
401*03831d35Sstevel 	static fn_t	f = "sbdp_connect_board";
402*03831d35Sstevel 	int		panther_pages_enabled;
403*03831d35Sstevel 
404*03831d35Sstevel 	SBDP_DBG_FUNC("%s\n", f);
405*03831d35Sstevel 
406*03831d35Sstevel 	board = hp->h_board;
407*03831d35Sstevel 	node = hp->h_wnode;
408*03831d35Sstevel 	sep = hp->h_err;
409*03831d35Sstevel 
410*03831d35Sstevel 	/*
411*03831d35Sstevel 	 * Check for options.  If there are any, fail the operation
412*03831d35Sstevel 	 */
413*03831d35Sstevel 	if (hp->h_opts != NULL && hp->h_opts->copts != NULL) {
414*03831d35Sstevel 		sbdp_set_err(sep, ESBD_INVAL_OPT, hp->h_opts->copts);
415*03831d35Sstevel 		return (-1);
416*03831d35Sstevel 	}
417*03831d35Sstevel 
418*03831d35Sstevel 	/*
419*03831d35Sstevel 	 * Currently, we pass the info in the extra data fields.
420*03831d35Sstevel 	 * This may change in the SC.  We need to change it then
421*03831d35Sstevel 	 */
422*03831d35Sstevel 	sbdp_init_msg_pkt(reqp, DR_MBOX_CLAIM, 0, (caddr_t)NULL);
423*03831d35Sstevel 	reqp->msg_data[0] = node;
424*03831d35Sstevel 	reqp->msg_data[1] = board;
425*03831d35Sstevel 
426*03831d35Sstevel 	sbdp_init_msg_pkt(resp, DR_MBOX_CLAIM, 0, (caddr_t)NULL);
427*03831d35Sstevel 
428*03831d35Sstevel 	rv = sbbc_mbox_request_response(reqp, resp, sbdp_mbox_wait);
429*03831d35Sstevel 
430*03831d35Sstevel 	if (rv != 0 || (rv = resp->msg_status != SG_MBOX_STATUS_SUCCESS)) {
431*03831d35Sstevel 		SBDP_DBG_MISC("failed to claim board: rv = %d\n", rv);
432*03831d35Sstevel 		sbdp_set_err(sep, sbdp_sc_err_translation(resp->msg_status),
433*03831d35Sstevel 		    NULL);
434*03831d35Sstevel 		return (rv);
435*03831d35Sstevel 	}
436*03831d35Sstevel 
437*03831d35Sstevel 	rv = prom_tree_update(sg_attach_board, hp);
438*03831d35Sstevel 	if (rv != 0) {
439*03831d35Sstevel 		SBDP_DBG_MISC("failed to prom attach board: rv = %d\n", rv);
440*03831d35Sstevel 		sbdp_set_err(sep, ESGT_PROM_ATTACH, NULL);
441*03831d35Sstevel 		/*
442*03831d35Sstevel 		 * Clean up
443*03831d35Sstevel 		 */
444*03831d35Sstevel 		sbdp_init_msg_pkt(reqp, DR_MBOX_UNCLAIM, 0, (caddr_t)NULL);
445*03831d35Sstevel 		reqp->msg_data[0] = node;
446*03831d35Sstevel 		reqp->msg_data[1] = board;
447*03831d35Sstevel 
448*03831d35Sstevel 		sbdp_init_msg_pkt(resp, DR_MBOX_UNCLAIM, 0, (caddr_t)NULL);
449*03831d35Sstevel 
450*03831d35Sstevel 		(void) sbbc_mbox_request_response(reqp, resp, sbdp_mbox_wait);
451*03831d35Sstevel 
452*03831d35Sstevel 		return (rv);
453*03831d35Sstevel 	}
454*03831d35Sstevel 
455*03831d35Sstevel 	SBDP_DBG_MISC("prom attach worked\n");
456*03831d35Sstevel 	sbdp_attach_bd(node, board);
457*03831d35Sstevel 
458*03831d35Sstevel 	/*
459*03831d35Sstevel 	 * XXX Until the Solaris large pages support heterogeneous cpu
460*03831d35Sstevel 	 * domains, DR needs to prevent the addition of non-Panther cpus
461*03831d35Sstevel 	 * to an all-Panther domain with large pages enabled.
462*03831d35Sstevel 	 */
463*03831d35Sstevel 	panther_pages_enabled = (page_num_pagesizes() > DEFAULT_MMU_PAGE_SIZES);
464*03831d35Sstevel 	if (sbdp_board_non_panther_cpus(node, board) > 0 &&
465*03831d35Sstevel 	    panther_pages_enabled && sbdp_large_page_restriction) {
466*03831d35Sstevel 		cmn_err(CE_WARN, "Domain shutdown is required to add a non-"
467*03831d35Sstevel 		    "UltraSPARC-IV+ board into an all UltraSPARC-IV+ domain");
468*03831d35Sstevel 		(void) sbdp_disconnect_board(hp);
469*03831d35Sstevel 		sbdp_set_err(sep, ESGT_NOT_SUPP, NULL);
470*03831d35Sstevel 		return (-1);
471*03831d35Sstevel 	}
472*03831d35Sstevel 
473*03831d35Sstevel 	/*
474*03831d35Sstevel 	 * Now that the board has been successfully attached, obtain
475*03831d35Sstevel 	 * platform-specific DIMM serial id information for the board.
476*03831d35Sstevel 	 */
477*03831d35Sstevel 	if (SG_BOARD_IS_CPU_TYPE(board) &&
478*03831d35Sstevel 	    plat_ecc_capability_sc_get(PLAT_ECC_DIMM_SID_MESSAGE)) {
479*03831d35Sstevel 		(void) plat_request_mem_sids(board);
480*03831d35Sstevel 	}
481*03831d35Sstevel 
482*03831d35Sstevel 	return (rv);
483*03831d35Sstevel }
484*03831d35Sstevel 
485*03831d35Sstevel /*
486*03831d35Sstevel  * Entry point from sbd.  Undo the connect call. We first need to remove
487*03831d35Sstevel  * the "dummy (i.e unusable)" nodes from solaris.  We then call down to OBP
488*03831d35Sstevel  * to prune its tree.  After all has been cleaned up from OBP and Solaris
489*03831d35Sstevel  * We call the SC to "detach/unclain" the board. A side effect is that the
490*03831d35Sstevel  * SC will clear the pda entries for this board
491*03831d35Sstevel  */
492*03831d35Sstevel int
sbdp_disconnect_board(sbdp_handle_t * hp)493*03831d35Sstevel sbdp_disconnect_board(sbdp_handle_t *hp)
494*03831d35Sstevel {
495*03831d35Sstevel 	sbbc_msg_t	request, *reqp = &request;
496*03831d35Sstevel 	sbbc_msg_t	response, *resp = &response;
497*03831d35Sstevel 	int		rv = 0;
498*03831d35Sstevel 	int		board, node;
499*03831d35Sstevel 	sbd_error_t	*sep;
500*03831d35Sstevel 	static fn_t	f = "sbdp_disconnect_board";
501*03831d35Sstevel 
502*03831d35Sstevel 	SBDP_DBG_FUNC("%s\n", f);
503*03831d35Sstevel 
504*03831d35Sstevel 	board = hp->h_board;
505*03831d35Sstevel 	node = hp->h_wnode;
506*03831d35Sstevel 	sep = hp->h_err;
507*03831d35Sstevel 
508*03831d35Sstevel 	SBDP_DBG_MISC("sbdp_disconnect_board: board = %d node = %d\n",
509*03831d35Sstevel 	    board, node);
510*03831d35Sstevel 
511*03831d35Sstevel 	/*
512*03831d35Sstevel 	 * Check for options.  If there are any, fail the operation
513*03831d35Sstevel 	 */
514*03831d35Sstevel 	if (hp->h_opts != NULL && hp->h_opts->copts != NULL) {
515*03831d35Sstevel 		sbdp_set_err(sep, ESBD_INVAL_OPT, hp->h_opts->copts);
516*03831d35Sstevel 		return (-1);
517*03831d35Sstevel 	}
518*03831d35Sstevel 
519*03831d35Sstevel 	if (sbdp_detach_bd(node, board, sep)) {
520*03831d35Sstevel 		sbdp_attach_bd(node, board);
521*03831d35Sstevel 		SBDP_DBG_ALL("failed to detach board %d\n", board);
522*03831d35Sstevel 		return (-1);
523*03831d35Sstevel 	}
524*03831d35Sstevel 
525*03831d35Sstevel 	rv = prom_tree_update(sg_detach_board, hp);
526*03831d35Sstevel 	if (rv == -1) {
527*03831d35Sstevel 		/*
528*03831d35Sstevel 		 * Clean up
529*03831d35Sstevel 		 */
530*03831d35Sstevel 		sbdp_attach_bd(node, board);
531*03831d35Sstevel 		SBDP_DBG_MISC("failed to prom detach board: rv = %d\n", rv);
532*03831d35Sstevel 		sbdp_set_err(sep, ESGT_PROM_DETACH, NULL);
533*03831d35Sstevel 		return (rv);
534*03831d35Sstevel 	}
535*03831d35Sstevel 
536*03831d35Sstevel 	SBDP_DBG_MISC("prom detach worked\n");
537*03831d35Sstevel 	/*
538*03831d35Sstevel 	 * Currently, we pass the info in the extra data fields.
539*03831d35Sstevel 	 * This may change in the SC.  We need to change it then
540*03831d35Sstevel 	 */
541*03831d35Sstevel 	sbdp_init_msg_pkt(reqp, DR_MBOX_UNCLAIM, 0, (caddr_t)NULL);
542*03831d35Sstevel 	reqp->msg_data[0] = node;
543*03831d35Sstevel 	reqp->msg_data[1] = board;
544*03831d35Sstevel 
545*03831d35Sstevel 	sbdp_init_msg_pkt(resp, DR_MBOX_UNCLAIM, 0, (caddr_t)NULL);
546*03831d35Sstevel 
547*03831d35Sstevel 	rv = sbbc_mbox_request_response(reqp, resp, sbdp_mbox_wait);
548*03831d35Sstevel 
549*03831d35Sstevel 	if (rv != 0 || (rv = resp->msg_status != SG_MBOX_STATUS_SUCCESS)) {
550*03831d35Sstevel 		SBDP_DBG_MISC("failed to unclaim board: rv = %d\n", rv);
551*03831d35Sstevel 		sbdp_set_err(sep, sbdp_sc_err_translation(resp->msg_status),
552*03831d35Sstevel 		    NULL);
553*03831d35Sstevel 		/* bring back the obp tree to what it was */
554*03831d35Sstevel 		(void) prom_tree_update(sg_attach_board, hp);
555*03831d35Sstevel 	}
556*03831d35Sstevel 
557*03831d35Sstevel 	/*
558*03831d35Sstevel 	 * Now that the board has been successfully detached, discard
559*03831d35Sstevel 	 * platform-specific DIMM serial id information for the board.
560*03831d35Sstevel 	 */
561*03831d35Sstevel 	if (!rv && SG_BOARD_IS_CPU_TYPE(board) &&
562*03831d35Sstevel 	    plat_ecc_capability_sc_get(PLAT_ECC_DIMM_SID_MESSAGE)) {
563*03831d35Sstevel 		(void) plat_discard_mem_sids(board);
564*03831d35Sstevel 	}
565*03831d35Sstevel 
566*03831d35Sstevel 	return (rv);
567*03831d35Sstevel }
568*03831d35Sstevel 
569*03831d35Sstevel /*
570*03831d35Sstevel  * Entry point from sbd.  Very simple.  Just ask the SC to poweoff the board
571*03831d35Sstevel  * Return the status from the SC
572*03831d35Sstevel  */
573*03831d35Sstevel int
sbdp_poweroff_board(sbdp_handle_t * hp)574*03831d35Sstevel sbdp_poweroff_board(sbdp_handle_t *hp)
575*03831d35Sstevel {
576*03831d35Sstevel 	sbbc_msg_t	request, *reqp = &request;
577*03831d35Sstevel 	sbbc_msg_t	response, *resp = &response;
578*03831d35Sstevel 	int		cmd_rev = -1;
579*03831d35Sstevel 	info2_t		inform, *informp;
580*03831d35Sstevel 	int		rv = 0;
581*03831d35Sstevel 	sbd_error_t	*sep;
582*03831d35Sstevel 	int		len;
583*03831d35Sstevel 	static fn_t	f = "sbdp_poweroff_board";
584*03831d35Sstevel 
585*03831d35Sstevel 	SBDP_DBG_FUNC("%s\n", f);
586*03831d35Sstevel 
587*03831d35Sstevel 	sep = hp->h_err;
588*03831d35Sstevel 	/*
589*03831d35Sstevel 	 * Check for options.  If there are any, fail the operation
590*03831d35Sstevel 	 */
591*03831d35Sstevel 	if (hp->h_opts != NULL && hp->h_opts->copts != NULL) {
592*03831d35Sstevel 		sbdp_set_err(sep, ESBD_INVAL_OPT, hp->h_opts->copts);
593*03831d35Sstevel 		return (-1);
594*03831d35Sstevel 	}
595*03831d35Sstevel 
596*03831d35Sstevel 	/*
597*03831d35Sstevel 	 * Can't check for bad options here since we use this for workaround
598*03831d35Sstevel 	 * on poweron.
599*03831d35Sstevel 	 */
600*03831d35Sstevel 
601*03831d35Sstevel 	informp = &inform;
602*03831d35Sstevel 	informp->board = hp->h_board;
603*03831d35Sstevel 	informp->node = hp->h_wnode;
604*03831d35Sstevel 	informp->extra = SBDP_POWER_OFF;
605*03831d35Sstevel 
606*03831d35Sstevel 	len = sizeof (info2_t);
607*03831d35Sstevel 	sbdp_init_msg_pkt(reqp, DR_MBOX_POWER, len, (caddr_t)informp);
608*03831d35Sstevel 
609*03831d35Sstevel 	len = sizeof (cmd_rev);
610*03831d35Sstevel 	sbdp_init_msg_pkt(resp, DR_MBOX_POWER, len, (caddr_t)&cmd_rev);
611*03831d35Sstevel 
612*03831d35Sstevel 	rv = sbbc_mbox_request_response(reqp, resp, sbdp_mbox_wait);
613*03831d35Sstevel 
614*03831d35Sstevel 	if (rv != 0 || (rv = resp->msg_status != SG_MBOX_STATUS_SUCCESS)) {
615*03831d35Sstevel 		SBDP_DBG_MISC("failed to poweroff board: rv = %d\n", rv);
616*03831d35Sstevel 		sbdp_set_err(sep, sbdp_sc_err_translation(resp->msg_status),
617*03831d35Sstevel 		    NULL);
618*03831d35Sstevel 	}
619*03831d35Sstevel 
620*03831d35Sstevel 	return (rv);
621*03831d35Sstevel }
622*03831d35Sstevel 
623*03831d35Sstevel /*
624*03831d35Sstevel  * Entry point from sbd.  Ask the SC to poweron the board
625*03831d35Sstevel  * Return the status from the SC
626*03831d35Sstevel  */
627*03831d35Sstevel int
sbdp_poweron_board(sbdp_handle_t * hp)628*03831d35Sstevel sbdp_poweron_board(sbdp_handle_t *hp)
629*03831d35Sstevel {
630*03831d35Sstevel 	sbbc_msg_t	request, *reqp = &request;
631*03831d35Sstevel 	sbbc_msg_t	response, *resp = &response;
632*03831d35Sstevel 	int		cmd_rev = -1;
633*03831d35Sstevel 	info2_t		inform, *informp;
634*03831d35Sstevel 	int		rv = 0;
635*03831d35Sstevel 	sbd_error_t	*sep;
636*03831d35Sstevel 	int		len;
637*03831d35Sstevel 	int		board = hp->h_board;
638*03831d35Sstevel 	static fn_t	f = "sbdp_poweron_board";
639*03831d35Sstevel 
640*03831d35Sstevel 	SBDP_DBG_FUNC("%s\n", f);
641*03831d35Sstevel 
642*03831d35Sstevel 	sep = hp->h_err;
643*03831d35Sstevel 	/*
644*03831d35Sstevel 	 * Check for options.  If there are any, fail the operation
645*03831d35Sstevel 	 */
646*03831d35Sstevel 	if (hp->h_opts != NULL && hp->h_opts->copts != NULL) {
647*03831d35Sstevel 		sbdp_set_err(sep, ESBD_INVAL_OPT, hp->h_opts->copts);
648*03831d35Sstevel 		return (-1);
649*03831d35Sstevel 	}
650*03831d35Sstevel 
651*03831d35Sstevel 	if (sbdp_poweroff_wkaround)
652*03831d35Sstevel 		if (SG_BOARD_IS_CPU_TYPE(board)) {
653*03831d35Sstevel 
654*03831d35Sstevel 			if ((rv = sbdp_poweroff_board(hp)) != 0)
655*03831d35Sstevel 				return (rv);
656*03831d35Sstevel 		}
657*03831d35Sstevel 
658*03831d35Sstevel 	informp = &inform;
659*03831d35Sstevel 	informp->board = hp->h_board;
660*03831d35Sstevel 	informp->node = hp->h_wnode;
661*03831d35Sstevel 	informp->extra = SBDP_POWER_ON;
662*03831d35Sstevel 
663*03831d35Sstevel 	len = sizeof (info2_t);
664*03831d35Sstevel 	sbdp_init_msg_pkt(reqp, DR_MBOX_POWER, len, (caddr_t)informp);
665*03831d35Sstevel 
666*03831d35Sstevel 	len = sizeof (cmd_rev);
667*03831d35Sstevel 	sbdp_init_msg_pkt(resp, DR_MBOX_POWER, len, (caddr_t)&cmd_rev);
668*03831d35Sstevel 
669*03831d35Sstevel 	rv = sbbc_mbox_request_response(reqp, resp, sbdp_mbox_wait);
670*03831d35Sstevel 
671*03831d35Sstevel 	if (rv != 0 || (rv = resp->msg_status != SG_MBOX_STATUS_SUCCESS)) {
672*03831d35Sstevel 		SBDP_DBG_MISC("failed to poweron board: rv = %d\n", rv);
673*03831d35Sstevel 		sbdp_set_err(sep, sbdp_sc_err_translation(resp->msg_status),
674*03831d35Sstevel 		    NULL);
675*03831d35Sstevel 	}
676*03831d35Sstevel 
677*03831d35Sstevel 	return (rv);
678*03831d35Sstevel }
679*03831d35Sstevel 
680*03831d35Sstevel int
sbdp_get_diag(sbdp_opts_t * opts)681*03831d35Sstevel sbdp_get_diag(sbdp_opts_t *opts)
682*03831d35Sstevel {
683*03831d35Sstevel 	char		*cptr;
684*03831d35Sstevel 	static fn_t	f = "sbdp_get_diag";
685*03831d35Sstevel 
686*03831d35Sstevel 	SBDP_DBG_FUNC("%s\n", f);
687*03831d35Sstevel 
688*03831d35Sstevel 	if ((opts == NULL) || (opts->copts == NULL))
689*03831d35Sstevel 		return (SBDP_DIAG_NVCI);
690*03831d35Sstevel 
691*03831d35Sstevel 	if ((cptr = strstr(opts->copts, "diag=")) != NULL) {
692*03831d35Sstevel 		/*
693*03831d35Sstevel 		 * We have args and need to process them
694*03831d35Sstevel 		 */
695*03831d35Sstevel 		cptr += strlen("diag=");
696*03831d35Sstevel 
697*03831d35Sstevel 		if (strncmp(cptr, "off", sizeof ("off")) == 0) {
698*03831d35Sstevel 			return (SBDP_DIAG_OFF);
699*03831d35Sstevel 		} else if (strncmp(cptr, "init", sizeof ("init")) == 0) {
700*03831d35Sstevel 			return (SBDP_DIAG_INIT);
701*03831d35Sstevel 		} else if (strncmp(cptr, "quick", sizeof ("quick")) == 0) {
702*03831d35Sstevel 			return (SBDP_DIAG_QUICK);
703*03831d35Sstevel 		} else if (strncmp(cptr, "min", sizeof ("min")) == 0) {
704*03831d35Sstevel 			return (SBDP_DIAG_MIN);
705*03831d35Sstevel 		} else if (strncmp(cptr, "default", sizeof ("default")) == 0 ||
706*03831d35Sstevel 			strncmp(cptr, "max", sizeof ("max")) == 0) {
707*03831d35Sstevel 			return (SBDP_DIAG_DEFAULT);
708*03831d35Sstevel 		} else if (strncmp(cptr, "mem1", sizeof ("mem1")) == 0) {
709*03831d35Sstevel 			return (SBDP_DIAG_MEM1);
710*03831d35Sstevel 		} else if (strncmp(cptr, "mem2", sizeof ("mem2")) == 0) {
711*03831d35Sstevel 			return (SBDP_DIAG_MEM2);
712*03831d35Sstevel 		}
713*03831d35Sstevel 	}
714*03831d35Sstevel 	SBDP_DBG_MISC("error: unrecognized arg\n");
715*03831d35Sstevel 	return (-1);
716*03831d35Sstevel }
717*03831d35Sstevel 
718*03831d35Sstevel 
719*03831d35Sstevel /*
720*03831d35Sstevel  * Entry point from sbd.  Ask the SC to test the board.  We still need to
721*03831d35Sstevel  * worry about the diag level.  The user may have changed it
722*03831d35Sstevel  *
723*03831d35Sstevel  * NOTE: The flag field has 2 different meanings whether we are dealing
724*03831d35Sstevel  * with a cpu/mem board or an io board.  In the case of a cpu/mem board it
725*03831d35Sstevel  * means retest the board to the diag level specified. In the case of an IO
726*03831d35Sstevel  * board, it means: Perform the necessary steps to prepare the board
727*03831d35Sstevel  * for the claim without running POST at the diag level specified.
728*03831d35Sstevel  */
729*03831d35Sstevel int
sbdp_test_board(sbdp_handle_t * hp,sbdp_opts_t * opts)730*03831d35Sstevel sbdp_test_board(sbdp_handle_t *hp, sbdp_opts_t *opts)
731*03831d35Sstevel {
732*03831d35Sstevel 	int		board = hp->h_board;
733*03831d35Sstevel 	int		node = hp->h_wnode;
734*03831d35Sstevel 	sbbc_msg_t	request, *reqp = &request;
735*03831d35Sstevel 	sbbc_msg_t	response, *resp = &response;
736*03831d35Sstevel 	int		cmd_rev = -1;
737*03831d35Sstevel 	testb_t		inform, *informp = &inform;
738*03831d35Sstevel 	int		rv = 0;
739*03831d35Sstevel 	sbd_error_t	*sep;
740*03831d35Sstevel 	int		diag;
741*03831d35Sstevel 	int		len;
742*03831d35Sstevel 	static fn_t	f = "sbdp_test_board";
743*03831d35Sstevel 
744*03831d35Sstevel 	SBDP_DBG_FUNC("%s\n", f);
745*03831d35Sstevel 
746*03831d35Sstevel 	sep = hp->h_err;
747*03831d35Sstevel 
748*03831d35Sstevel 	diag = sbdp_get_diag(opts);
749*03831d35Sstevel 
750*03831d35Sstevel 	if (diag == -1) {
751*03831d35Sstevel 		sbdp_set_err(sep, ESBD_INVAL_OPT, opts != NULL ?
752*03831d35Sstevel 		    opts->copts : NULL);
753*03831d35Sstevel 		return (-1);
754*03831d35Sstevel 	}
755*03831d35Sstevel 
756*03831d35Sstevel 	SBDP_DBG_MISC("Diag level is 0x%x\n", diag);
757*03831d35Sstevel 
758*03831d35Sstevel 	informp->info.board = board;
759*03831d35Sstevel 	informp->info.node = node;
760*03831d35Sstevel 
761*03831d35Sstevel 	informp->info.extra = diag;
762*03831d35Sstevel 
763*03831d35Sstevel 	/*
764*03831d35Sstevel 	 * Only force retest on CPU boards
765*03831d35Sstevel 	 */
766*03831d35Sstevel 	if (SG_BOARD_IS_CPU_TYPE(board))
767*03831d35Sstevel 		informp->flag = 1;
768*03831d35Sstevel 	else {
769*03831d35Sstevel 		/*
770*03831d35Sstevel 		 * For CPULESS IO pass the force to the SC
771*03831d35Sstevel 		 */
772*03831d35Sstevel 		if (hp->h_flags & SBDP_IOCTL_FLAG_FORCE)
773*03831d35Sstevel 			informp->flag = 1;
774*03831d35Sstevel 		else
775*03831d35Sstevel 			informp->flag = 0;
776*03831d35Sstevel 
777*03831d35Sstevel 	}
778*03831d35Sstevel 
779*03831d35Sstevel 	len = sizeof (testb_t);
780*03831d35Sstevel 	sbdp_init_msg_pkt(reqp, DR_MBOX_TEST_BD, len, (caddr_t)informp);
781*03831d35Sstevel 
782*03831d35Sstevel 
783*03831d35Sstevel 	len = sizeof (cmd_rev);
784*03831d35Sstevel 	sbdp_init_msg_pkt(resp, DR_MBOX_TEST_BD, len, (caddr_t)&cmd_rev);
785*03831d35Sstevel 
786*03831d35Sstevel 	rv = sbbc_mbox_request_response(reqp, resp, sbdp_mbox_wait);
787*03831d35Sstevel 
788*03831d35Sstevel 	if (rv != 0 || (resp->msg_status != SG_MBOX_STATUS_SUCCESS)) {
789*03831d35Sstevel 		SBDP_DBG_MISC("failed to test board: rv = %d status = %d\n",
790*03831d35Sstevel 		    rv, resp->msg_status);
791*03831d35Sstevel 		rv = resp->msg_status;
792*03831d35Sstevel 		sbdp_set_err(sep, sbdp_sc_err_translation(resp->msg_status),
793*03831d35Sstevel 		    NULL);
794*03831d35Sstevel 	}
795*03831d35Sstevel 
796*03831d35Sstevel 	return (rv);
797*03831d35Sstevel }
798*03831d35Sstevel 
799*03831d35Sstevel /*
800*03831d35Sstevel  * Request the SC to update POST's memory slice table by swapping
801*03831d35Sstevel  * the entries for the two board numbers given
802*03831d35Sstevel  * This is used when performing a copy-rename operation.
803*03831d35Sstevel  */
804*03831d35Sstevel int
sbdp_swap_slices(int bd1,int bd2)805*03831d35Sstevel sbdp_swap_slices(int bd1, int bd2)
806*03831d35Sstevel {
807*03831d35Sstevel 	sbbc_msg_t	request, *reqp = &request;
808*03831d35Sstevel 	sbbc_msg_t	response, *resp = &response;
809*03831d35Sstevel 	int		cmd_rev = -1;
810*03831d35Sstevel 	swap_slices_t	inform, *informp = &inform;
811*03831d35Sstevel 	int		rv;
812*03831d35Sstevel 	int		len;
813*03831d35Sstevel 	static fn_t	f = "sbdp_swap_slices";
814*03831d35Sstevel 
815*03831d35Sstevel 	SBDP_DBG_FUNC("%s\n", f);
816*03831d35Sstevel 
817*03831d35Sstevel 	informp->board1 = bd1;
818*03831d35Sstevel 	informp->board2 = bd2;
819*03831d35Sstevel 
820*03831d35Sstevel 	len = sizeof (swap_slices_t);
821*03831d35Sstevel 	sbdp_init_msg_pkt(reqp, DR_MBOX_SWAP_SLICES, len, (caddr_t)informp);
822*03831d35Sstevel 
823*03831d35Sstevel 	len = sizeof (cmd_rev);
824*03831d35Sstevel 	sbdp_init_msg_pkt(resp, DR_MBOX_SWAP_SLICES, len, (caddr_t)&cmd_rev);
825*03831d35Sstevel 
826*03831d35Sstevel 	rv = sbbc_mbox_request_response(reqp, resp, sbdp_mbox_wait);
827*03831d35Sstevel 
828*03831d35Sstevel 	if (rv != 0 || (resp->msg_status != SG_MBOX_STATUS_SUCCESS)) {
829*03831d35Sstevel 		SBDP_DBG_MISC("failed to swap slices %d<->%d: rv = %d "
830*03831d35Sstevel 		    "status = %d\n", bd1, bd2, rv, resp->msg_status);
831*03831d35Sstevel 		rv = sbdp_sc_err_translation(resp->msg_status);
832*03831d35Sstevel 	}
833*03831d35Sstevel 
834*03831d35Sstevel 	return (rv);
835*03831d35Sstevel }
836*03831d35Sstevel 
837*03831d35Sstevel int
sbdp_sc_err_translation(int error)838*03831d35Sstevel sbdp_sc_err_translation(int error)
839*03831d35Sstevel {
840*03831d35Sstevel 	int err;
841*03831d35Sstevel 	static fn_t	f = "sbdp_sc_err_translation";
842*03831d35Sstevel 
843*03831d35Sstevel 	SBDP_DBG_FUNC("%s\n", f);
844*03831d35Sstevel 
845*03831d35Sstevel 	switch (error) {
846*03831d35Sstevel 	case SG_MBOX_STATUS_HARDWARE_FAILURE:
847*03831d35Sstevel 		err = ESGT_HW_FAIL;
848*03831d35Sstevel 		break;
849*03831d35Sstevel 	case SG_MBOX_STATUS_ILLEGAL_PARAMETER:
850*03831d35Sstevel 	case SG_MBOX_STATUS_ILLEGAL_NODE:
851*03831d35Sstevel 	case SG_MBOX_STATUS_ILLEGAL_SLOT:
852*03831d35Sstevel 		err = ESGT_INVAL;
853*03831d35Sstevel 		break;
854*03831d35Sstevel 	case SG_MBOX_STATUS_BOARD_ACCESS_DENIED:
855*03831d35Sstevel 		err = ESGT_BD_ACCESS;
856*03831d35Sstevel 		break;
857*03831d35Sstevel 	case SG_MBOX_STATUS_STALE_CONTENTS:
858*03831d35Sstevel 		err = ESGT_STALE_CMP;
859*03831d35Sstevel 		break;
860*03831d35Sstevel 	case SG_MBOX_STATUS_STALE_OBJECT:
861*03831d35Sstevel 		err = ESGT_STALE_OBJ;
862*03831d35Sstevel 		break;
863*03831d35Sstevel 	case SG_MBOX_STATUS_NO_SEPROM_SPACE:
864*03831d35Sstevel 		err = ESGT_NO_SEPROM_SPACE;
865*03831d35Sstevel 		break;
866*03831d35Sstevel 	case SG_MBOX_STATUS_NO_MEMORY:
867*03831d35Sstevel 		err = ESGT_NO_MEM;
868*03831d35Sstevel 		break;
869*03831d35Sstevel 	case SG_MBOX_STATUS_NOT_SUPPORTED:
870*03831d35Sstevel 		err = ESGT_NOT_SUPP;
871*03831d35Sstevel 		break;
872*03831d35Sstevel 	case SG_MBOX_STATUS_COMMAND_FAILURE:
873*03831d35Sstevel 	default:
874*03831d35Sstevel 		err = ESGT_INTERNAL;
875*03831d35Sstevel 		break;
876*03831d35Sstevel 	}
877*03831d35Sstevel 
878*03831d35Sstevel 	return (err);
879*03831d35Sstevel }
880*03831d35Sstevel 
881*03831d35Sstevel int
sbdp_stop_cpu(processorid_t cpu)882*03831d35Sstevel sbdp_stop_cpu(processorid_t cpu)
883*03831d35Sstevel {
884*03831d35Sstevel 	sbbc_msg_t	request, *reqp = &request;
885*03831d35Sstevel 	sbbc_msg_t	response, *resp = &response;
886*03831d35Sstevel 	int		rv = 0;
887*03831d35Sstevel 	int		len;
888*03831d35Sstevel 	static fn_t	f = "sbdp_stop_cpu";
889*03831d35Sstevel 
890*03831d35Sstevel 	SBDP_DBG_FUNC("%s\n", f);
891*03831d35Sstevel 
892*03831d35Sstevel 	len = sizeof (processorid_t);
893*03831d35Sstevel 	sbdp_init_msg_pkt(reqp, DR_MBOX_STOP_CPU, len, (caddr_t)&cpu);
894*03831d35Sstevel 
895*03831d35Sstevel 	sbdp_init_msg_pkt(resp, DR_MBOX_STOP_CPU, 0, (caddr_t)NULL);
896*03831d35Sstevel 
897*03831d35Sstevel 	rv = sbbc_mbox_request_response(reqp, resp, sbdp_mbox_wait);
898*03831d35Sstevel 
899*03831d35Sstevel 	if (rv != 0 || (rv = resp->msg_status != SG_MBOX_STATUS_SUCCESS)) {
900*03831d35Sstevel 		SBDP_DBG_MISC("failed to stop cpu: rv = %d\n", rv);
901*03831d35Sstevel 	}
902*03831d35Sstevel 
903*03831d35Sstevel 	return (rv);
904*03831d35Sstevel }
905*03831d35Sstevel 
906*03831d35Sstevel int
sbdp_start_cpu(processorid_t cpu)907*03831d35Sstevel sbdp_start_cpu(processorid_t cpu)
908*03831d35Sstevel {
909*03831d35Sstevel 	sbbc_msg_t	request, *reqp = &request;
910*03831d35Sstevel 	sbbc_msg_t	response, *resp = &response;
911*03831d35Sstevel 	int		rv = 0;
912*03831d35Sstevel 	int		len;
913*03831d35Sstevel 	static fn_t	f = "sbdp_start_cpu";
914*03831d35Sstevel 
915*03831d35Sstevel 	SBDP_DBG_FUNC("%s\n", f);
916*03831d35Sstevel 
917*03831d35Sstevel 	len = sizeof (cpu);
918*03831d35Sstevel 	sbdp_init_msg_pkt(reqp, DR_MBOX_START_CPU, len, (caddr_t)&cpu);
919*03831d35Sstevel 
920*03831d35Sstevel 	sbdp_init_msg_pkt(resp, DR_MBOX_START_CPU, 0, (caddr_t)NULL);
921*03831d35Sstevel 
922*03831d35Sstevel 	rv = sbbc_mbox_request_response(reqp, resp, sbdp_mbox_wait);
923*03831d35Sstevel 
924*03831d35Sstevel 	if (rv != 0 || (rv = resp->msg_status != SG_MBOX_STATUS_SUCCESS)) {
925*03831d35Sstevel 		SBDP_DBG_MISC("failed to start cpu: rv = %d\n", rv);
926*03831d35Sstevel 	}
927*03831d35Sstevel 
928*03831d35Sstevel 	return (rv);
929*03831d35Sstevel }
930*03831d35Sstevel 
931*03831d35Sstevel /*
932*03831d35Sstevel  * With the SIR implementation for CPU unconfigure, this mailbox
933*03831d35Sstevel  * call is obsolete.
934*03831d35Sstevel  */
935*03831d35Sstevel int
sbdp_start_cpu_pairs(processorid_t cpu)936*03831d35Sstevel sbdp_start_cpu_pairs(processorid_t cpu)
937*03831d35Sstevel {
938*03831d35Sstevel 	sbbc_msg_t	request, *reqp = &request;
939*03831d35Sstevel 	sbbc_msg_t	response, *resp = &response;
940*03831d35Sstevel 	int		rv = 0;
941*03831d35Sstevel 	int		len;
942*03831d35Sstevel 	static fn_t	f = "sbdp_start_cpu_pairs";
943*03831d35Sstevel 
944*03831d35Sstevel 	SBDP_DBG_FUNC("%s\n", f);
945*03831d35Sstevel 
946*03831d35Sstevel 	len = sizeof (cpu);
947*03831d35Sstevel 	sbdp_init_msg_pkt(reqp, DR_MBOX_START_CPU_PAIRS, len, (caddr_t)&cpu);
948*03831d35Sstevel 
949*03831d35Sstevel 	sbdp_init_msg_pkt(resp, DR_MBOX_START_CPU_PAIRS, 0, (caddr_t)NULL);
950*03831d35Sstevel 
951*03831d35Sstevel 	rv = sbbc_mbox_request_response(reqp, resp, sbdp_mbox_wait);
952*03831d35Sstevel 
953*03831d35Sstevel 	if (rv != 0 || (rv = resp->msg_status != SG_MBOX_STATUS_SUCCESS)) {
954*03831d35Sstevel 		SBDP_DBG_MISC("failed to start cpu pair: rv = %d\n", rv);
955*03831d35Sstevel 	}
956*03831d35Sstevel 
957*03831d35Sstevel 	return (rv);
958*03831d35Sstevel }
959