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