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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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