1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate /* 30*7c478bd9Sstevel@tonic-gate * safari system board DR module. 31*7c478bd9Sstevel@tonic-gate */ 32*7c478bd9Sstevel@tonic-gate 33*7c478bd9Sstevel@tonic-gate #include <sys/debug.h> 34*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 35*7c478bd9Sstevel@tonic-gate #include <sys/errno.h> 36*7c478bd9Sstevel@tonic-gate #include <sys/cred.h> 37*7c478bd9Sstevel@tonic-gate #include <sys/dditypes.h> 38*7c478bd9Sstevel@tonic-gate #include <sys/devops.h> 39*7c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/poll.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/conf.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 43*7c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 44*7c478bd9Sstevel@tonic-gate #include <sys/sunndi.h> 45*7c478bd9Sstevel@tonic-gate #include <sys/ndi_impldefs.h> 46*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 47*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 48*7c478bd9Sstevel@tonic-gate #include <sys/cpuvar.h> 49*7c478bd9Sstevel@tonic-gate #include <sys/mem_config.h> 50*7c478bd9Sstevel@tonic-gate #include <sys/mem_cage.h> 51*7c478bd9Sstevel@tonic-gate 52*7c478bd9Sstevel@tonic-gate #include <sys/autoconf.h> 53*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 54*7c478bd9Sstevel@tonic-gate 55*7c478bd9Sstevel@tonic-gate #include <sys/ddi_impldefs.h> 56*7c478bd9Sstevel@tonic-gate #include <sys/machsystm.h> 57*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 58*7c478bd9Sstevel@tonic-gate 59*7c478bd9Sstevel@tonic-gate #include <sys/sbdpriv.h> 60*7c478bd9Sstevel@tonic-gate #include <sys/sbd_io.h> 61*7c478bd9Sstevel@tonic-gate 62*7c478bd9Sstevel@tonic-gate /* start sbd includes */ 63*7c478bd9Sstevel@tonic-gate 64*7c478bd9Sstevel@tonic-gate #include <sys/systm.h> 65*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 66*7c478bd9Sstevel@tonic-gate #include <sys/x_call.h> 67*7c478bd9Sstevel@tonic-gate #include <sys/membar.h> 68*7c478bd9Sstevel@tonic-gate #include <vm/seg_kmem.h> 69*7c478bd9Sstevel@tonic-gate 70*7c478bd9Sstevel@tonic-gate extern int nulldev(); 71*7c478bd9Sstevel@tonic-gate extern int nodev(); 72*7c478bd9Sstevel@tonic-gate 73*7c478bd9Sstevel@tonic-gate typedef struct { /* arg to sbd_get_handle */ 74*7c478bd9Sstevel@tonic-gate dev_t dev; 75*7c478bd9Sstevel@tonic-gate int cmd; 76*7c478bd9Sstevel@tonic-gate int mode; 77*7c478bd9Sstevel@tonic-gate sbd_ioctl_arg_t *ioargp; 78*7c478bd9Sstevel@tonic-gate } sbd_init_arg_t; 79*7c478bd9Sstevel@tonic-gate 80*7c478bd9Sstevel@tonic-gate 81*7c478bd9Sstevel@tonic-gate /* 82*7c478bd9Sstevel@tonic-gate * sbd support operations. 83*7c478bd9Sstevel@tonic-gate */ 84*7c478bd9Sstevel@tonic-gate static void sbd_exec_op(sbd_handle_t *hp); 85*7c478bd9Sstevel@tonic-gate static void sbd_dev_configure(sbd_handle_t *hp); 86*7c478bd9Sstevel@tonic-gate static int sbd_dev_release(sbd_handle_t *hp); 87*7c478bd9Sstevel@tonic-gate static int sbd_dev_unconfigure(sbd_handle_t *hp); 88*7c478bd9Sstevel@tonic-gate static void sbd_attach_cpu(sbd_handle_t *hp, sbderror_t *ep, 89*7c478bd9Sstevel@tonic-gate dev_info_t *dip, int unit); 90*7c478bd9Sstevel@tonic-gate static void sbd_detach_cpu(sbd_handle_t *hp, sbderror_t *ep, 91*7c478bd9Sstevel@tonic-gate dev_info_t *dip, int unit); 92*7c478bd9Sstevel@tonic-gate static int sbd_detach_mem(sbd_handle_t *hp, sbderror_t *ep, int unit); 93*7c478bd9Sstevel@tonic-gate static void sbd_cancel(sbd_handle_t *hp); 94*7c478bd9Sstevel@tonic-gate void sbd_errno_decode(int err, sbderror_t *ep, dev_info_t *dip); 95*7c478bd9Sstevel@tonic-gate int sbd_dealloc_instance(sbd_board_t *sbp, int max_boards); 96*7c478bd9Sstevel@tonic-gate int sbd_errno2ecode(int error); 97*7c478bd9Sstevel@tonic-gate #pragma weak sbdp_cpu_get_impl 98*7c478bd9Sstevel@tonic-gate 99*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 100*7c478bd9Sstevel@tonic-gate uint_t sbd_debug = (uint_t)0x0; 101*7c478bd9Sstevel@tonic-gate 102*7c478bd9Sstevel@tonic-gate #ifdef SBD_DEBUG_ERRS 103*7c478bd9Sstevel@tonic-gate /* controls which errors are injected */ 104*7c478bd9Sstevel@tonic-gate uint_t sbd_err_debug = (uint_t)0x0; 105*7c478bd9Sstevel@tonic-gate 106*7c478bd9Sstevel@tonic-gate /* controls printing about error injection */ 107*7c478bd9Sstevel@tonic-gate uint_t sbd_print_errs = (uint_t)0x0; 108*7c478bd9Sstevel@tonic-gate 109*7c478bd9Sstevel@tonic-gate #endif /* SBD_DEBUG_ERRS */ 110*7c478bd9Sstevel@tonic-gate 111*7c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 112*7c478bd9Sstevel@tonic-gate 113*7c478bd9Sstevel@tonic-gate char *sbd_state_str[] = { 114*7c478bd9Sstevel@tonic-gate "EMPTY", "OCCUPIED", "CONNECTED", "UNCONFIGURED", 115*7c478bd9Sstevel@tonic-gate "PARTIAL", "CONFIGURED", "RELEASE", "UNREFERENCED", 116*7c478bd9Sstevel@tonic-gate "FATAL" 117*7c478bd9Sstevel@tonic-gate }; 118*7c478bd9Sstevel@tonic-gate 119*7c478bd9Sstevel@tonic-gate /* Note: this must be changed in tandem with sbd_ioctl.h */ 120*7c478bd9Sstevel@tonic-gate char *sbd_ct_str[] = { 121*7c478bd9Sstevel@tonic-gate "NONE", "CPU", "MEM", "IO", "UNKNOWN" 122*7c478bd9Sstevel@tonic-gate }; 123*7c478bd9Sstevel@tonic-gate 124*7c478bd9Sstevel@tonic-gate /* Note: this must also be changed in tandem with sbd_ioctl.h */ 125*7c478bd9Sstevel@tonic-gate #define SBD_CMD_STR(c) \ 126*7c478bd9Sstevel@tonic-gate (((c) == SBD_CMD_ASSIGN) ? "ASSIGN" : \ 127*7c478bd9Sstevel@tonic-gate ((c) == SBD_CMD_UNASSIGN) ? "UNASSIGN" : \ 128*7c478bd9Sstevel@tonic-gate ((c) == SBD_CMD_POWERON) ? "POWERON" : \ 129*7c478bd9Sstevel@tonic-gate ((c) == SBD_CMD_POWEROFF) ? "POWEROFF" : \ 130*7c478bd9Sstevel@tonic-gate ((c) == SBD_CMD_TEST) ? "TEST" : \ 131*7c478bd9Sstevel@tonic-gate ((c) == SBD_CMD_CONNECT) ? "CONNECT" : \ 132*7c478bd9Sstevel@tonic-gate ((c) == SBD_CMD_CONFIGURE) ? "CONFIGURE" : \ 133*7c478bd9Sstevel@tonic-gate ((c) == SBD_CMD_UNCONFIGURE) ? "UNCONFIGURE" : \ 134*7c478bd9Sstevel@tonic-gate ((c) == SBD_CMD_DISCONNECT) ? "DISCONNECT" : \ 135*7c478bd9Sstevel@tonic-gate ((c) == SBD_CMD_STATUS) ? "STATUS" : \ 136*7c478bd9Sstevel@tonic-gate ((c) == SBD_CMD_GETNCM) ? "GETNCM" : \ 137*7c478bd9Sstevel@tonic-gate ((c) == SBD_CMD_PASSTHRU) ? "PASSTHRU" : "unknown") 138*7c478bd9Sstevel@tonic-gate 139*7c478bd9Sstevel@tonic-gate /* 140*7c478bd9Sstevel@tonic-gate * Defines and structures for device tree naming and mapping 141*7c478bd9Sstevel@tonic-gate * to node types 142*7c478bd9Sstevel@tonic-gate */ 143*7c478bd9Sstevel@tonic-gate 144*7c478bd9Sstevel@tonic-gate sbd_devattr_t *sbd_devattr; 145*7c478bd9Sstevel@tonic-gate 146*7c478bd9Sstevel@tonic-gate /* defines to access the attribute struct */ 147*7c478bd9Sstevel@tonic-gate #define SBD_DEVNAME(i) sbd_devattr[i].s_devname 148*7c478bd9Sstevel@tonic-gate #define SBD_OTYPE(i) sbd_devattr[(i)].s_obp_type 149*7c478bd9Sstevel@tonic-gate #define SBD_COMP(i) sbd_devattr[i].s_dnodetype 150*7c478bd9Sstevel@tonic-gate 151*7c478bd9Sstevel@tonic-gate /* 152*7c478bd9Sstevel@tonic-gate * State transition table. States valid transitions for "board" state. 153*7c478bd9Sstevel@tonic-gate * Recall that non-zero return value terminates operation, however 154*7c478bd9Sstevel@tonic-gate * the herrno value is what really indicates an error , if any. 155*7c478bd9Sstevel@tonic-gate */ 156*7c478bd9Sstevel@tonic-gate static int 157*7c478bd9Sstevel@tonic-gate _cmd2index(int c) 158*7c478bd9Sstevel@tonic-gate { 159*7c478bd9Sstevel@tonic-gate /* 160*7c478bd9Sstevel@tonic-gate * Translate DR CMD to index into sbd_state_transition. 161*7c478bd9Sstevel@tonic-gate */ 162*7c478bd9Sstevel@tonic-gate switch (c) { 163*7c478bd9Sstevel@tonic-gate case SBD_CMD_CONNECT: return (0); 164*7c478bd9Sstevel@tonic-gate case SBD_CMD_DISCONNECT: return (1); 165*7c478bd9Sstevel@tonic-gate case SBD_CMD_CONFIGURE: return (2); 166*7c478bd9Sstevel@tonic-gate case SBD_CMD_UNCONFIGURE: return (3); 167*7c478bd9Sstevel@tonic-gate case SBD_CMD_POWEROFF: return (4); 168*7c478bd9Sstevel@tonic-gate case SBD_CMD_POWERON: return (5); 169*7c478bd9Sstevel@tonic-gate case SBD_CMD_UNASSIGN: return (6); 170*7c478bd9Sstevel@tonic-gate case SBD_CMD_ASSIGN: return (7); 171*7c478bd9Sstevel@tonic-gate case SBD_CMD_TEST: return (8); 172*7c478bd9Sstevel@tonic-gate default: return (-1); 173*7c478bd9Sstevel@tonic-gate } 174*7c478bd9Sstevel@tonic-gate } 175*7c478bd9Sstevel@tonic-gate 176*7c478bd9Sstevel@tonic-gate #define CMD2INDEX(c) _cmd2index(c) 177*7c478bd9Sstevel@tonic-gate 178*7c478bd9Sstevel@tonic-gate static struct sbd_state_trans { 179*7c478bd9Sstevel@tonic-gate int x_cmd; 180*7c478bd9Sstevel@tonic-gate struct { 181*7c478bd9Sstevel@tonic-gate int x_rv; /* return value of pre_op */ 182*7c478bd9Sstevel@tonic-gate int x_err; /* errno, if any */ 183*7c478bd9Sstevel@tonic-gate } x_op[SBD_NUM_STATES]; 184*7c478bd9Sstevel@tonic-gate } sbd_state_transition[] = { 185*7c478bd9Sstevel@tonic-gate { SBD_CMD_CONNECT, 186*7c478bd9Sstevel@tonic-gate { 187*7c478bd9Sstevel@tonic-gate { 0, 0 }, /* empty */ 188*7c478bd9Sstevel@tonic-gate { 0, 0 }, /* occupied */ 189*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* connected */ 190*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* unconfigured */ 191*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* partial */ 192*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* configured */ 193*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* release */ 194*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* unreferenced */ 195*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* fatal */ 196*7c478bd9Sstevel@tonic-gate } 197*7c478bd9Sstevel@tonic-gate }, 198*7c478bd9Sstevel@tonic-gate { SBD_CMD_DISCONNECT, 199*7c478bd9Sstevel@tonic-gate { 200*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* empty */ 201*7c478bd9Sstevel@tonic-gate { 0, 0 }, /* occupied */ 202*7c478bd9Sstevel@tonic-gate { 0, 0 }, /* connected */ 203*7c478bd9Sstevel@tonic-gate { 0, 0 }, /* unconfigured */ 204*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* partial */ 205*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* configured */ 206*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* release */ 207*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* unreferenced */ 208*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* fatal */ 209*7c478bd9Sstevel@tonic-gate } 210*7c478bd9Sstevel@tonic-gate }, 211*7c478bd9Sstevel@tonic-gate { SBD_CMD_CONFIGURE, 212*7c478bd9Sstevel@tonic-gate { 213*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* empty */ 214*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* occupied */ 215*7c478bd9Sstevel@tonic-gate { 0, 0 }, /* connected */ 216*7c478bd9Sstevel@tonic-gate { 0, 0 }, /* unconfigured */ 217*7c478bd9Sstevel@tonic-gate { 0, 0 }, /* partial */ 218*7c478bd9Sstevel@tonic-gate { 1, 0 }, /* configured */ 219*7c478bd9Sstevel@tonic-gate { 0, 0 }, /* release */ 220*7c478bd9Sstevel@tonic-gate { 0, 0 }, /* unreferenced */ 221*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* fatal */ 222*7c478bd9Sstevel@tonic-gate } 223*7c478bd9Sstevel@tonic-gate }, 224*7c478bd9Sstevel@tonic-gate { SBD_CMD_UNCONFIGURE, 225*7c478bd9Sstevel@tonic-gate { 226*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* empty */ 227*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* occupied */ 228*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* connected */ 229*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* unconfigured */ 230*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* partial */ 231*7c478bd9Sstevel@tonic-gate { 0, 0 }, /* configured */ 232*7c478bd9Sstevel@tonic-gate { 0, 0 }, /* release */ 233*7c478bd9Sstevel@tonic-gate { 0, 0 }, /* unreferenced */ 234*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* fatal */ 235*7c478bd9Sstevel@tonic-gate } 236*7c478bd9Sstevel@tonic-gate }, 237*7c478bd9Sstevel@tonic-gate { SBD_CMD_POWEROFF, 238*7c478bd9Sstevel@tonic-gate { 239*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* empty */ 240*7c478bd9Sstevel@tonic-gate { 0, 0 }, /* occupied */ 241*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* connected */ 242*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* unconfigured */ 243*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* partial */ 244*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* configured */ 245*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* release */ 246*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* unreferenced */ 247*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* fatal */ 248*7c478bd9Sstevel@tonic-gate } 249*7c478bd9Sstevel@tonic-gate }, 250*7c478bd9Sstevel@tonic-gate { SBD_CMD_POWERON, 251*7c478bd9Sstevel@tonic-gate { 252*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* empty */ 253*7c478bd9Sstevel@tonic-gate { 0, 0 }, /* occupied */ 254*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* connected */ 255*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* unconfigured */ 256*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* partial */ 257*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* configured */ 258*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* release */ 259*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* unreferenced */ 260*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* fatal */ 261*7c478bd9Sstevel@tonic-gate } 262*7c478bd9Sstevel@tonic-gate }, 263*7c478bd9Sstevel@tonic-gate { SBD_CMD_UNASSIGN, 264*7c478bd9Sstevel@tonic-gate { 265*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* empty */ 266*7c478bd9Sstevel@tonic-gate { 0, 0 }, /* occupied */ 267*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* connected */ 268*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* unconfigured */ 269*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* partial */ 270*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* configured */ 271*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* release */ 272*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* unreferenced */ 273*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* fatal */ 274*7c478bd9Sstevel@tonic-gate } 275*7c478bd9Sstevel@tonic-gate }, 276*7c478bd9Sstevel@tonic-gate { SBD_CMD_ASSIGN, 277*7c478bd9Sstevel@tonic-gate { 278*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* empty */ 279*7c478bd9Sstevel@tonic-gate { 0, 0 }, /* occupied */ 280*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* connected */ 281*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* unconfigured */ 282*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* partial */ 283*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* configured */ 284*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* release */ 285*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* unreferenced */ 286*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* fatal */ 287*7c478bd9Sstevel@tonic-gate } 288*7c478bd9Sstevel@tonic-gate }, 289*7c478bd9Sstevel@tonic-gate { SBD_CMD_TEST, 290*7c478bd9Sstevel@tonic-gate { 291*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* empty */ 292*7c478bd9Sstevel@tonic-gate { 0, 0 }, /* occupied */ 293*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* connected */ 294*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* unconfigured */ 295*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* partial */ 296*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* configured */ 297*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* release */ 298*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* unreferenced */ 299*7c478bd9Sstevel@tonic-gate { 1, EIO }, /* fatal */ 300*7c478bd9Sstevel@tonic-gate } 301*7c478bd9Sstevel@tonic-gate }, 302*7c478bd9Sstevel@tonic-gate }; 303*7c478bd9Sstevel@tonic-gate 304*7c478bd9Sstevel@tonic-gate /* 305*7c478bd9Sstevel@tonic-gate * Global R/W lock to synchronize access across 306*7c478bd9Sstevel@tonic-gate * multiple boards. Users wanting multi-board access 307*7c478bd9Sstevel@tonic-gate * must grab WRITE lock, others must grab READ lock. 308*7c478bd9Sstevel@tonic-gate */ 309*7c478bd9Sstevel@tonic-gate krwlock_t sbd_grwlock; 310*7c478bd9Sstevel@tonic-gate 311*7c478bd9Sstevel@tonic-gate /* 312*7c478bd9Sstevel@tonic-gate * Global to determine if an event needs to be sent 313*7c478bd9Sstevel@tonic-gate */ 314*7c478bd9Sstevel@tonic-gate char send_event = 0; 315*7c478bd9Sstevel@tonic-gate 316*7c478bd9Sstevel@tonic-gate /* 317*7c478bd9Sstevel@tonic-gate * Required/Expected functions. 318*7c478bd9Sstevel@tonic-gate */ 319*7c478bd9Sstevel@tonic-gate 320*7c478bd9Sstevel@tonic-gate static sbd_handle_t *sbd_get_handle(dev_t dev, sbd_softstate_t *softsp, 321*7c478bd9Sstevel@tonic-gate intptr_t arg, sbd_init_arg_t *iap); 322*7c478bd9Sstevel@tonic-gate static void sbd_release_handle(sbd_handle_t *hp); 323*7c478bd9Sstevel@tonic-gate static int sbd_pre_op(sbd_handle_t *hp); 324*7c478bd9Sstevel@tonic-gate static void sbd_post_op(sbd_handle_t *hp); 325*7c478bd9Sstevel@tonic-gate static int sbd_probe_board(sbd_handle_t *hp); 326*7c478bd9Sstevel@tonic-gate static int sbd_deprobe_board(sbd_handle_t *hp); 327*7c478bd9Sstevel@tonic-gate static void sbd_connect(sbd_handle_t *hp); 328*7c478bd9Sstevel@tonic-gate static void sbd_assign_board(sbd_handle_t *hp); 329*7c478bd9Sstevel@tonic-gate static void sbd_unassign_board(sbd_handle_t *hp); 330*7c478bd9Sstevel@tonic-gate static void sbd_poweron_board(sbd_handle_t *hp); 331*7c478bd9Sstevel@tonic-gate static void sbd_poweroff_board(sbd_handle_t *hp); 332*7c478bd9Sstevel@tonic-gate static void sbd_test_board(sbd_handle_t *hp); 333*7c478bd9Sstevel@tonic-gate 334*7c478bd9Sstevel@tonic-gate static int sbd_disconnect(sbd_handle_t *hp); 335*7c478bd9Sstevel@tonic-gate static sbd_devlist_t *sbd_get_attach_devlist(sbd_handle_t *hp, 336*7c478bd9Sstevel@tonic-gate int32_t *devnump, int32_t pass); 337*7c478bd9Sstevel@tonic-gate static int sbd_pre_attach_devlist(sbd_handle_t *hp, 338*7c478bd9Sstevel@tonic-gate sbd_devlist_t *devlist, int32_t devnum); 339*7c478bd9Sstevel@tonic-gate static int sbd_post_attach_devlist(sbd_handle_t *hp, 340*7c478bd9Sstevel@tonic-gate sbd_devlist_t *devlist, int32_t devnum); 341*7c478bd9Sstevel@tonic-gate static sbd_devlist_t *sbd_get_release_devlist(sbd_handle_t *hp, 342*7c478bd9Sstevel@tonic-gate int32_t *devnump, int32_t pass); 343*7c478bd9Sstevel@tonic-gate static int sbd_pre_release_devlist(sbd_handle_t *hp, 344*7c478bd9Sstevel@tonic-gate sbd_devlist_t *devlist, int32_t devnum); 345*7c478bd9Sstevel@tonic-gate static int sbd_post_release_devlist(sbd_handle_t *hp, 346*7c478bd9Sstevel@tonic-gate sbd_devlist_t *devlist, int32_t devnum); 347*7c478bd9Sstevel@tonic-gate static void sbd_release_done(sbd_handle_t *hp, 348*7c478bd9Sstevel@tonic-gate sbd_comp_type_t nodetype, 349*7c478bd9Sstevel@tonic-gate dev_info_t *dip); 350*7c478bd9Sstevel@tonic-gate static sbd_devlist_t *sbd_get_detach_devlist(sbd_handle_t *hp, 351*7c478bd9Sstevel@tonic-gate int32_t *devnump, int32_t pass); 352*7c478bd9Sstevel@tonic-gate static int sbd_pre_detach_devlist(sbd_handle_t *hp, 353*7c478bd9Sstevel@tonic-gate sbd_devlist_t *devlist, int32_t devnum); 354*7c478bd9Sstevel@tonic-gate static int sbd_post_detach_devlist(sbd_handle_t *hp, 355*7c478bd9Sstevel@tonic-gate sbd_devlist_t *devlist, int32_t devnum); 356*7c478bd9Sstevel@tonic-gate static void sbd_status(sbd_handle_t *hp); 357*7c478bd9Sstevel@tonic-gate static void sbd_get_ncm(sbd_handle_t *hp); 358*7c478bd9Sstevel@tonic-gate 359*7c478bd9Sstevel@tonic-gate 360*7c478bd9Sstevel@tonic-gate /* 361*7c478bd9Sstevel@tonic-gate * Support functions. 362*7c478bd9Sstevel@tonic-gate */ 363*7c478bd9Sstevel@tonic-gate static sbd_devset_t sbd_dev2devset(sbd_comp_id_t *cid); 364*7c478bd9Sstevel@tonic-gate static int sbd_copyin_ioarg(sbd_handle_t *hp, int mode, int cmd, 365*7c478bd9Sstevel@tonic-gate sbd_cmd_t *cmdp, sbd_ioctl_arg_t *iap); 366*7c478bd9Sstevel@tonic-gate static int sbd_copyout_errs(int mode, sbd_ioctl_arg_t *iap, 367*7c478bd9Sstevel@tonic-gate void *arg); 368*7c478bd9Sstevel@tonic-gate static int sbd_copyout_ioarg(int mode, int cmd, sbd_cmd_t *scp, 369*7c478bd9Sstevel@tonic-gate sbd_ioctl_arg_t *iap); 370*7c478bd9Sstevel@tonic-gate static int sbd_check_transition(sbd_board_t *sbp, 371*7c478bd9Sstevel@tonic-gate sbd_devset_t *devsetp, 372*7c478bd9Sstevel@tonic-gate struct sbd_state_trans *transp); 373*7c478bd9Sstevel@tonic-gate static sbd_devlist_t *sbd_get_devlist(sbd_handle_t *hp, 374*7c478bd9Sstevel@tonic-gate sbd_board_t *sbp, 375*7c478bd9Sstevel@tonic-gate sbd_comp_type_t nodetype, 376*7c478bd9Sstevel@tonic-gate int max_units, uint_t uset, 377*7c478bd9Sstevel@tonic-gate int *count, int present_only); 378*7c478bd9Sstevel@tonic-gate static int sbd_mem_status(sbd_handle_t *hp, sbd_devset_t devset, 379*7c478bd9Sstevel@tonic-gate sbd_dev_stat_t *dsp); 380*7c478bd9Sstevel@tonic-gate 381*7c478bd9Sstevel@tonic-gate static int sbd_init_devlists(sbd_board_t *sbp); 382*7c478bd9Sstevel@tonic-gate static int sbd_name_to_idx(char *name); 383*7c478bd9Sstevel@tonic-gate static int sbd_otype_to_idx(char *otpye); 384*7c478bd9Sstevel@tonic-gate static int sbd_setup_devlists(dev_info_t *dip, void *arg); 385*7c478bd9Sstevel@tonic-gate static void sbd_init_mem_devlists(sbd_board_t *sbp); 386*7c478bd9Sstevel@tonic-gate static void sbd_init_cpu_unit(sbd_board_t *sbp, int unit); 387*7c478bd9Sstevel@tonic-gate static void sbd_board_discovery(sbd_board_t *sbp); 388*7c478bd9Sstevel@tonic-gate static void sbd_board_init(sbd_board_t *sbp, 389*7c478bd9Sstevel@tonic-gate sbd_softstate_t *softsp, 390*7c478bd9Sstevel@tonic-gate int bd, dev_info_t *dip, int wnode); 391*7c478bd9Sstevel@tonic-gate static void sbd_board_destroy(sbd_board_t *sbp); 392*7c478bd9Sstevel@tonic-gate static int sbd_check_unit_attached(sbd_board_t *sbp, 393*7c478bd9Sstevel@tonic-gate dev_info_t *dip, int unit, 394*7c478bd9Sstevel@tonic-gate sbd_comp_type_t nodetype, sbderror_t *ep); 395*7c478bd9Sstevel@tonic-gate 396*7c478bd9Sstevel@tonic-gate static sbd_state_t rstate_cvt(sbd_istate_t state); 397*7c478bd9Sstevel@tonic-gate 398*7c478bd9Sstevel@tonic-gate /* 399*7c478bd9Sstevel@tonic-gate * Autoconfiguration data structures 400*7c478bd9Sstevel@tonic-gate */ 401*7c478bd9Sstevel@tonic-gate 402*7c478bd9Sstevel@tonic-gate extern struct mod_ops mod_miscops; 403*7c478bd9Sstevel@tonic-gate 404*7c478bd9Sstevel@tonic-gate static struct modlmisc modlmisc = { 405*7c478bd9Sstevel@tonic-gate &mod_miscops, 406*7c478bd9Sstevel@tonic-gate "System Board DR v%I%" 407*7c478bd9Sstevel@tonic-gate }; 408*7c478bd9Sstevel@tonic-gate 409*7c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = { 410*7c478bd9Sstevel@tonic-gate MODREV_1, 411*7c478bd9Sstevel@tonic-gate (void *)&modlmisc, 412*7c478bd9Sstevel@tonic-gate NULL 413*7c478bd9Sstevel@tonic-gate }; 414*7c478bd9Sstevel@tonic-gate 415*7c478bd9Sstevel@tonic-gate static int sbd_instances = 0; 416*7c478bd9Sstevel@tonic-gate 417*7c478bd9Sstevel@tonic-gate /* 418*7c478bd9Sstevel@tonic-gate * dr Global data elements 419*7c478bd9Sstevel@tonic-gate */ 420*7c478bd9Sstevel@tonic-gate sbd_global sbd_g; 421*7c478bd9Sstevel@tonic-gate 422*7c478bd9Sstevel@tonic-gate /* 423*7c478bd9Sstevel@tonic-gate * We want to be able to unload the module when we wish to do so, but we don't 424*7c478bd9Sstevel@tonic-gate * want anything else to unload it. Unloading cannot occur until 425*7c478bd9Sstevel@tonic-gate * sbd_teardown_instance is called by an explicit IOCTL into the parent node. 426*7c478bd9Sstevel@tonic-gate * This support is for debugging purposes and should it be expected to work 427*7c478bd9Sstevel@tonic-gate * on the field, it should be enhanced: 428*7c478bd9Sstevel@tonic-gate * Currently, there is still a window where sbd_teardow_instance gets called, 429*7c478bd9Sstevel@tonic-gate * sbd_prevent_unloading now = 0, the driver doesn't get unloaded, and 430*7c478bd9Sstevel@tonic-gate * sbd_setup_instance gets called. This may cause a panic. 431*7c478bd9Sstevel@tonic-gate */ 432*7c478bd9Sstevel@tonic-gate int sbd_prevent_unloading = 1; 433*7c478bd9Sstevel@tonic-gate 434*7c478bd9Sstevel@tonic-gate /* 435*7c478bd9Sstevel@tonic-gate * Driver entry points. 436*7c478bd9Sstevel@tonic-gate */ 437*7c478bd9Sstevel@tonic-gate int 438*7c478bd9Sstevel@tonic-gate _init(void) 439*7c478bd9Sstevel@tonic-gate { 440*7c478bd9Sstevel@tonic-gate int err; 441*7c478bd9Sstevel@tonic-gate 442*7c478bd9Sstevel@tonic-gate /* 443*7c478bd9Sstevel@tonic-gate * If you need to support multiple nodes (instances), then 444*7c478bd9Sstevel@tonic-gate * whatever the maximum number of supported nodes is would 445*7c478bd9Sstevel@tonic-gate * need to passed as the third parameter to ddi_soft_state_init(). 446*7c478bd9Sstevel@tonic-gate * Alternative would be to dynamically fini and re-init the 447*7c478bd9Sstevel@tonic-gate * soft state structure each time a node is attached. 448*7c478bd9Sstevel@tonic-gate */ 449*7c478bd9Sstevel@tonic-gate err = ddi_soft_state_init((void **)&sbd_g.softsp, 450*7c478bd9Sstevel@tonic-gate sizeof (sbd_softstate_t), SBD_MAX_INSTANCES); 451*7c478bd9Sstevel@tonic-gate if (err) 452*7c478bd9Sstevel@tonic-gate return (err); 453*7c478bd9Sstevel@tonic-gate 454*7c478bd9Sstevel@tonic-gate if ((err = mod_install(&modlinkage)) != 0) { 455*7c478bd9Sstevel@tonic-gate ddi_soft_state_fini((void **)&sbd_g.softsp); 456*7c478bd9Sstevel@tonic-gate return (err); 457*7c478bd9Sstevel@tonic-gate } 458*7c478bd9Sstevel@tonic-gate 459*7c478bd9Sstevel@tonic-gate /* Get the array of names from platform helper routine */ 460*7c478bd9Sstevel@tonic-gate sbd_devattr = sbdp_get_devattr(); 461*7c478bd9Sstevel@tonic-gate 462*7c478bd9Sstevel@tonic-gate return (err); 463*7c478bd9Sstevel@tonic-gate } 464*7c478bd9Sstevel@tonic-gate 465*7c478bd9Sstevel@tonic-gate int 466*7c478bd9Sstevel@tonic-gate _fini(void) 467*7c478bd9Sstevel@tonic-gate { 468*7c478bd9Sstevel@tonic-gate int err; 469*7c478bd9Sstevel@tonic-gate 470*7c478bd9Sstevel@tonic-gate if (sbd_prevent_unloading) 471*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 472*7c478bd9Sstevel@tonic-gate 473*7c478bd9Sstevel@tonic-gate ASSERT(sbd_instances == 0); 474*7c478bd9Sstevel@tonic-gate 475*7c478bd9Sstevel@tonic-gate if ((err = mod_remove(&modlinkage)) != 0) 476*7c478bd9Sstevel@tonic-gate return (err); 477*7c478bd9Sstevel@tonic-gate 478*7c478bd9Sstevel@tonic-gate ddi_soft_state_fini((void **)&sbd_g.softsp); 479*7c478bd9Sstevel@tonic-gate 480*7c478bd9Sstevel@tonic-gate return (0); 481*7c478bd9Sstevel@tonic-gate } 482*7c478bd9Sstevel@tonic-gate 483*7c478bd9Sstevel@tonic-gate int 484*7c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop) 485*7c478bd9Sstevel@tonic-gate { 486*7c478bd9Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 487*7c478bd9Sstevel@tonic-gate } 488*7c478bd9Sstevel@tonic-gate 489*7c478bd9Sstevel@tonic-gate int 490*7c478bd9Sstevel@tonic-gate sbd_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, char *event) 491*7c478bd9Sstevel@tonic-gate { 492*7c478bd9Sstevel@tonic-gate int rv = 0, instance; 493*7c478bd9Sstevel@tonic-gate sbd_handle_t *hp; 494*7c478bd9Sstevel@tonic-gate sbd_softstate_t *softsp; 495*7c478bd9Sstevel@tonic-gate sbd_init_arg_t init_arg; 496*7c478bd9Sstevel@tonic-gate static fn_t f = "sbd_ioctl"; 497*7c478bd9Sstevel@tonic-gate int dr_avail; 498*7c478bd9Sstevel@tonic-gate 499*7c478bd9Sstevel@tonic-gate PR_BYP("sbd_ioctl cmd=%x, arg=%x\n", cmd, arg); 500*7c478bd9Sstevel@tonic-gate 501*7c478bd9Sstevel@tonic-gate /* Note: this must also be changed in tandem with sbd_ioctl.h */ 502*7c478bd9Sstevel@tonic-gate switch (cmd) { 503*7c478bd9Sstevel@tonic-gate case SBD_CMD_ASSIGN: 504*7c478bd9Sstevel@tonic-gate case SBD_CMD_UNASSIGN: 505*7c478bd9Sstevel@tonic-gate case SBD_CMD_POWERON: 506*7c478bd9Sstevel@tonic-gate case SBD_CMD_POWEROFF: 507*7c478bd9Sstevel@tonic-gate case SBD_CMD_TEST: 508*7c478bd9Sstevel@tonic-gate case SBD_CMD_CONNECT: 509*7c478bd9Sstevel@tonic-gate case SBD_CMD_CONFIGURE: 510*7c478bd9Sstevel@tonic-gate case SBD_CMD_UNCONFIGURE: 511*7c478bd9Sstevel@tonic-gate case SBD_CMD_DISCONNECT: 512*7c478bd9Sstevel@tonic-gate case SBD_CMD_STATUS: 513*7c478bd9Sstevel@tonic-gate case SBD_CMD_GETNCM: 514*7c478bd9Sstevel@tonic-gate case SBD_CMD_PASSTHRU: 515*7c478bd9Sstevel@tonic-gate break; 516*7c478bd9Sstevel@tonic-gate default: 517*7c478bd9Sstevel@tonic-gate return (ENOTTY); 518*7c478bd9Sstevel@tonic-gate } 519*7c478bd9Sstevel@tonic-gate 520*7c478bd9Sstevel@tonic-gate instance = SBD_GET_MINOR2INST(getminor(dev)); 521*7c478bd9Sstevel@tonic-gate if ((softsp = (sbd_softstate_t *)GET_SOFTC(instance)) == NULL) { 522*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 523*7c478bd9Sstevel@tonic-gate "sbd:%s:%d: module not yet attached", 524*7c478bd9Sstevel@tonic-gate f, instance); 525*7c478bd9Sstevel@tonic-gate return (ENXIO); 526*7c478bd9Sstevel@tonic-gate } 527*7c478bd9Sstevel@tonic-gate 528*7c478bd9Sstevel@tonic-gate init_arg.dev = dev; 529*7c478bd9Sstevel@tonic-gate init_arg.cmd = cmd; 530*7c478bd9Sstevel@tonic-gate init_arg.mode = mode; 531*7c478bd9Sstevel@tonic-gate init_arg.ioargp = (sbd_ioctl_arg_t *)arg; 532*7c478bd9Sstevel@tonic-gate 533*7c478bd9Sstevel@tonic-gate hp = sbd_get_handle(dev, softsp, arg, &init_arg); 534*7c478bd9Sstevel@tonic-gate /* Check to see if we support dr */ 535*7c478bd9Sstevel@tonic-gate dr_avail = sbdp_dr_avail(); 536*7c478bd9Sstevel@tonic-gate if (dr_avail != 1) { 537*7c478bd9Sstevel@tonic-gate switch (hp->h_cmd) { 538*7c478bd9Sstevel@tonic-gate case SBD_CMD_STATUS: 539*7c478bd9Sstevel@tonic-gate case SBD_CMD_GETNCM: 540*7c478bd9Sstevel@tonic-gate case SBD_CMD_PASSTHRU: 541*7c478bd9Sstevel@tonic-gate break; 542*7c478bd9Sstevel@tonic-gate default: 543*7c478bd9Sstevel@tonic-gate sbd_release_handle(hp); 544*7c478bd9Sstevel@tonic-gate return (ENOTSUP); 545*7c478bd9Sstevel@tonic-gate } 546*7c478bd9Sstevel@tonic-gate } 547*7c478bd9Sstevel@tonic-gate 548*7c478bd9Sstevel@tonic-gate switch (hp->h_cmd) { 549*7c478bd9Sstevel@tonic-gate case SBD_CMD_STATUS: 550*7c478bd9Sstevel@tonic-gate case SBD_CMD_GETNCM: 551*7c478bd9Sstevel@tonic-gate case SBD_CMD_PASSTHRU: 552*7c478bd9Sstevel@tonic-gate /* no locks needed for these commands */ 553*7c478bd9Sstevel@tonic-gate break; 554*7c478bd9Sstevel@tonic-gate 555*7c478bd9Sstevel@tonic-gate default: 556*7c478bd9Sstevel@tonic-gate rw_enter(&sbd_grwlock, RW_WRITER); 557*7c478bd9Sstevel@tonic-gate mutex_enter(&SBDH2BD(hp->h_sbd)->sb_mutex); 558*7c478bd9Sstevel@tonic-gate 559*7c478bd9Sstevel@tonic-gate /* 560*7c478bd9Sstevel@tonic-gate * If we're dealing with memory at all, then we have 561*7c478bd9Sstevel@tonic-gate * to keep the "exclusive" global lock held. This is 562*7c478bd9Sstevel@tonic-gate * necessary since we will probably need to look at 563*7c478bd9Sstevel@tonic-gate * multiple board structs. Otherwise, we only have 564*7c478bd9Sstevel@tonic-gate * to deal with the board in question and so can drop 565*7c478bd9Sstevel@tonic-gate * the global lock to "shared". 566*7c478bd9Sstevel@tonic-gate */ 567*7c478bd9Sstevel@tonic-gate /* 568*7c478bd9Sstevel@tonic-gate * XXX This is incorrect. The sh_devset has not 569*7c478bd9Sstevel@tonic-gate * been set at this point - it is 0. 570*7c478bd9Sstevel@tonic-gate */ 571*7c478bd9Sstevel@tonic-gate rv = DEVSET_IN_SET(HD2MACHHD(hp)->sh_devset, 572*7c478bd9Sstevel@tonic-gate SBD_COMP_MEM, DEVSET_ANYUNIT); 573*7c478bd9Sstevel@tonic-gate if (rv == 0) 574*7c478bd9Sstevel@tonic-gate rw_downgrade(&sbd_grwlock); 575*7c478bd9Sstevel@tonic-gate break; 576*7c478bd9Sstevel@tonic-gate } 577*7c478bd9Sstevel@tonic-gate 578*7c478bd9Sstevel@tonic-gate /* 579*7c478bd9Sstevel@tonic-gate * Before any operations happen, reset the event flag 580*7c478bd9Sstevel@tonic-gate */ 581*7c478bd9Sstevel@tonic-gate send_event = 0; 582*7c478bd9Sstevel@tonic-gate 583*7c478bd9Sstevel@tonic-gate if (sbd_pre_op(hp) == 0) { 584*7c478bd9Sstevel@tonic-gate sbd_exec_op(hp); 585*7c478bd9Sstevel@tonic-gate sbd_post_op(hp); 586*7c478bd9Sstevel@tonic-gate } 587*7c478bd9Sstevel@tonic-gate 588*7c478bd9Sstevel@tonic-gate rv = SBD_GET_ERRNO(SBD_HD2ERR(hp)); 589*7c478bd9Sstevel@tonic-gate *event = send_event; 590*7c478bd9Sstevel@tonic-gate 591*7c478bd9Sstevel@tonic-gate /* undo locking, if any, done before sbd_pre_op */ 592*7c478bd9Sstevel@tonic-gate switch (hp->h_cmd) { 593*7c478bd9Sstevel@tonic-gate case SBD_CMD_STATUS: 594*7c478bd9Sstevel@tonic-gate case SBD_CMD_GETNCM: 595*7c478bd9Sstevel@tonic-gate case SBD_CMD_PASSTHRU: 596*7c478bd9Sstevel@tonic-gate break; 597*7c478bd9Sstevel@tonic-gate default: 598*7c478bd9Sstevel@tonic-gate mutex_exit(&SBDH2BD(hp->h_sbd)->sb_mutex); 599*7c478bd9Sstevel@tonic-gate rw_exit(&sbd_grwlock); 600*7c478bd9Sstevel@tonic-gate } 601*7c478bd9Sstevel@tonic-gate 602*7c478bd9Sstevel@tonic-gate sbd_release_handle(hp); 603*7c478bd9Sstevel@tonic-gate 604*7c478bd9Sstevel@tonic-gate return (rv); 605*7c478bd9Sstevel@tonic-gate } 606*7c478bd9Sstevel@tonic-gate 607*7c478bd9Sstevel@tonic-gate int 608*7c478bd9Sstevel@tonic-gate sbd_setup_instance(int instance, dev_info_t *root, int max_boards, int wnode, 609*7c478bd9Sstevel@tonic-gate caddr_t sbdp_arg) 610*7c478bd9Sstevel@tonic-gate { 611*7c478bd9Sstevel@tonic-gate int b; 612*7c478bd9Sstevel@tonic-gate sbd_softstate_t *softsp; 613*7c478bd9Sstevel@tonic-gate sbd_board_t *sbd_boardlist; 614*7c478bd9Sstevel@tonic-gate static fn_t f = "sbd_setup_instance"; 615*7c478bd9Sstevel@tonic-gate 616*7c478bd9Sstevel@tonic-gate sbd_instances++; 617*7c478bd9Sstevel@tonic-gate 618*7c478bd9Sstevel@tonic-gate if (sbdp_setup_instance(sbdp_arg) != DDI_SUCCESS) { 619*7c478bd9Sstevel@tonic-gate sbd_instances--; 620*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 621*7c478bd9Sstevel@tonic-gate } 622*7c478bd9Sstevel@tonic-gate 623*7c478bd9Sstevel@tonic-gate if (ALLOC_SOFTC(instance) != DDI_SUCCESS) { 624*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 625*7c478bd9Sstevel@tonic-gate "sbd:%s:%d: failed to alloc soft-state", 626*7c478bd9Sstevel@tonic-gate f, instance); 627*7c478bd9Sstevel@tonic-gate sbdp_teardown_instance(sbdp_arg); 628*7c478bd9Sstevel@tonic-gate sbd_instances--; 629*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 630*7c478bd9Sstevel@tonic-gate } 631*7c478bd9Sstevel@tonic-gate 632*7c478bd9Sstevel@tonic-gate softsp = (sbd_softstate_t *)GET_SOFTC(instance); 633*7c478bd9Sstevel@tonic-gate 634*7c478bd9Sstevel@tonic-gate if (softsp == NULL) { 635*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 636*7c478bd9Sstevel@tonic-gate "sbd:%s:%d: failed to get soft-state instance", 637*7c478bd9Sstevel@tonic-gate f, instance); 638*7c478bd9Sstevel@tonic-gate goto exit; 639*7c478bd9Sstevel@tonic-gate } 640*7c478bd9Sstevel@tonic-gate 641*7c478bd9Sstevel@tonic-gate sbd_boardlist = GETSTRUCT(sbd_board_t, max_boards); 642*7c478bd9Sstevel@tonic-gate if (sbd_boardlist == NULL) { 643*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 644*7c478bd9Sstevel@tonic-gate "sbd:%s: failed to alloc board list %d", 645*7c478bd9Sstevel@tonic-gate f, instance); 646*7c478bd9Sstevel@tonic-gate goto exit; 647*7c478bd9Sstevel@tonic-gate } 648*7c478bd9Sstevel@tonic-gate 649*7c478bd9Sstevel@tonic-gate 650*7c478bd9Sstevel@tonic-gate softsp->sbd_boardlist = (void *)sbd_boardlist; 651*7c478bd9Sstevel@tonic-gate softsp->max_boards = max_boards; 652*7c478bd9Sstevel@tonic-gate softsp->wnode = wnode; 653*7c478bd9Sstevel@tonic-gate 654*7c478bd9Sstevel@tonic-gate 655*7c478bd9Sstevel@tonic-gate for (b = 0; b < max_boards; b++) { 656*7c478bd9Sstevel@tonic-gate sbd_board_init(sbd_boardlist++, softsp, b, root, wnode); 657*7c478bd9Sstevel@tonic-gate } 658*7c478bd9Sstevel@tonic-gate 659*7c478bd9Sstevel@tonic-gate 660*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 661*7c478bd9Sstevel@tonic-gate exit: 662*7c478bd9Sstevel@tonic-gate (void) sbdp_teardown_instance(sbdp_arg); 663*7c478bd9Sstevel@tonic-gate FREE_SOFTC(instance); 664*7c478bd9Sstevel@tonic-gate sbd_instances--; 665*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 666*7c478bd9Sstevel@tonic-gate } 667*7c478bd9Sstevel@tonic-gate 668*7c478bd9Sstevel@tonic-gate int 669*7c478bd9Sstevel@tonic-gate sbd_teardown_instance(int instance, caddr_t sbdp_arg) 670*7c478bd9Sstevel@tonic-gate { 671*7c478bd9Sstevel@tonic-gate sbd_softstate_t *softsp; 672*7c478bd9Sstevel@tonic-gate 673*7c478bd9Sstevel@tonic-gate if (sbdp_teardown_instance(sbdp_arg) != DDI_SUCCESS) 674*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 675*7c478bd9Sstevel@tonic-gate 676*7c478bd9Sstevel@tonic-gate softsp = (sbd_softstate_t *)GET_SOFTC(instance); 677*7c478bd9Sstevel@tonic-gate if (softsp == NULL) { 678*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 679*7c478bd9Sstevel@tonic-gate } 680*7c478bd9Sstevel@tonic-gate 681*7c478bd9Sstevel@tonic-gate (void) sbd_dealloc_instance((sbd_board_t *)softsp->sbd_boardlist, 682*7c478bd9Sstevel@tonic-gate softsp->max_boards); 683*7c478bd9Sstevel@tonic-gate 684*7c478bd9Sstevel@tonic-gate FREE_SOFTC(instance); 685*7c478bd9Sstevel@tonic-gate sbd_instances--; 686*7c478bd9Sstevel@tonic-gate sbd_prevent_unloading = 0; 687*7c478bd9Sstevel@tonic-gate 688*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 689*7c478bd9Sstevel@tonic-gate } 690*7c478bd9Sstevel@tonic-gate 691*7c478bd9Sstevel@tonic-gate static void 692*7c478bd9Sstevel@tonic-gate sbd_exec_op(sbd_handle_t *hp) 693*7c478bd9Sstevel@tonic-gate { 694*7c478bd9Sstevel@tonic-gate sbd_board_t *sbp = SBDH2BD(hp->h_sbd); 695*7c478bd9Sstevel@tonic-gate static fn_t f = "sbd_exec_op"; 696*7c478bd9Sstevel@tonic-gate 697*7c478bd9Sstevel@tonic-gate switch (hp->h_cmd) { 698*7c478bd9Sstevel@tonic-gate int dev_canceled; 699*7c478bd9Sstevel@tonic-gate 700*7c478bd9Sstevel@tonic-gate case SBD_CMD_CONNECT: 701*7c478bd9Sstevel@tonic-gate if (sbd_probe_board(hp)) 702*7c478bd9Sstevel@tonic-gate break; 703*7c478bd9Sstevel@tonic-gate 704*7c478bd9Sstevel@tonic-gate sbd_connect(hp); 705*7c478bd9Sstevel@tonic-gate break; 706*7c478bd9Sstevel@tonic-gate 707*7c478bd9Sstevel@tonic-gate case SBD_CMD_CONFIGURE: 708*7c478bd9Sstevel@tonic-gate sbd_dev_configure(hp); 709*7c478bd9Sstevel@tonic-gate break; 710*7c478bd9Sstevel@tonic-gate 711*7c478bd9Sstevel@tonic-gate case SBD_CMD_UNCONFIGURE: 712*7c478bd9Sstevel@tonic-gate if (((dev_canceled = sbd_dev_release(hp)) == 0) && 713*7c478bd9Sstevel@tonic-gate (SBD_GET_ERRNO(SBD_HD2ERR(hp)) == 0 && 714*7c478bd9Sstevel@tonic-gate SBD_GET_ERR(SBD_HD2ERR(hp)) == 0)) 715*7c478bd9Sstevel@tonic-gate dev_canceled = sbd_dev_unconfigure(hp); 716*7c478bd9Sstevel@tonic-gate 717*7c478bd9Sstevel@tonic-gate if (dev_canceled) 718*7c478bd9Sstevel@tonic-gate sbd_cancel(hp); 719*7c478bd9Sstevel@tonic-gate break; 720*7c478bd9Sstevel@tonic-gate 721*7c478bd9Sstevel@tonic-gate case SBD_CMD_DISCONNECT: 722*7c478bd9Sstevel@tonic-gate mutex_enter(&sbp->sb_slock); 723*7c478bd9Sstevel@tonic-gate if (sbd_disconnect(hp) == 0) 724*7c478bd9Sstevel@tonic-gate (void) sbd_deprobe_board(hp); 725*7c478bd9Sstevel@tonic-gate mutex_exit(&sbp->sb_slock); 726*7c478bd9Sstevel@tonic-gate break; 727*7c478bd9Sstevel@tonic-gate 728*7c478bd9Sstevel@tonic-gate case SBD_CMD_STATUS: 729*7c478bd9Sstevel@tonic-gate sbd_status(hp); 730*7c478bd9Sstevel@tonic-gate break; 731*7c478bd9Sstevel@tonic-gate 732*7c478bd9Sstevel@tonic-gate case SBD_CMD_GETNCM: 733*7c478bd9Sstevel@tonic-gate sbd_get_ncm(hp); 734*7c478bd9Sstevel@tonic-gate break; 735*7c478bd9Sstevel@tonic-gate 736*7c478bd9Sstevel@tonic-gate case SBD_CMD_ASSIGN: 737*7c478bd9Sstevel@tonic-gate sbd_assign_board(hp); 738*7c478bd9Sstevel@tonic-gate break; 739*7c478bd9Sstevel@tonic-gate 740*7c478bd9Sstevel@tonic-gate case SBD_CMD_UNASSIGN: 741*7c478bd9Sstevel@tonic-gate sbd_unassign_board(hp); 742*7c478bd9Sstevel@tonic-gate break; 743*7c478bd9Sstevel@tonic-gate 744*7c478bd9Sstevel@tonic-gate case SBD_CMD_POWEROFF: 745*7c478bd9Sstevel@tonic-gate sbd_poweroff_board(hp); 746*7c478bd9Sstevel@tonic-gate break; 747*7c478bd9Sstevel@tonic-gate 748*7c478bd9Sstevel@tonic-gate case SBD_CMD_POWERON: 749*7c478bd9Sstevel@tonic-gate sbd_poweron_board(hp); 750*7c478bd9Sstevel@tonic-gate break; 751*7c478bd9Sstevel@tonic-gate 752*7c478bd9Sstevel@tonic-gate case SBD_CMD_TEST: 753*7c478bd9Sstevel@tonic-gate sbd_test_board(hp); 754*7c478bd9Sstevel@tonic-gate break; 755*7c478bd9Sstevel@tonic-gate 756*7c478bd9Sstevel@tonic-gate case SBD_CMD_PASSTHRU: 757*7c478bd9Sstevel@tonic-gate { 758*7c478bd9Sstevel@tonic-gate int rv; 759*7c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 760*7c478bd9Sstevel@tonic-gate sbderror_t *ep = SBD_HD2ERR(hp); 761*7c478bd9Sstevel@tonic-gate sbdp_ioctl_arg_t ia, *iap; 762*7c478bd9Sstevel@tonic-gate 763*7c478bd9Sstevel@tonic-gate iap = &ia; 764*7c478bd9Sstevel@tonic-gate 765*7c478bd9Sstevel@tonic-gate iap->h_dev = hp->h_dev; 766*7c478bd9Sstevel@tonic-gate iap->h_cmd = hp->h_cmd; 767*7c478bd9Sstevel@tonic-gate iap->h_iap = (intptr_t)hp->h_iap; 768*7c478bd9Sstevel@tonic-gate iap->h_mode = hp->h_mode; 769*7c478bd9Sstevel@tonic-gate 770*7c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 771*7c478bd9Sstevel@tonic-gate rv = sbdp_ioctl(hdp, iap); 772*7c478bd9Sstevel@tonic-gate if (rv != 0) { 773*7c478bd9Sstevel@tonic-gate SBD_GET_PERR(hdp->h_err, SBD_HD2ERR(hp)); 774*7c478bd9Sstevel@tonic-gate ep->e_errno = rv; 775*7c478bd9Sstevel@tonic-gate } 776*7c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 777*7c478bd9Sstevel@tonic-gate break; 778*7c478bd9Sstevel@tonic-gate } 779*7c478bd9Sstevel@tonic-gate 780*7c478bd9Sstevel@tonic-gate default: 781*7c478bd9Sstevel@tonic-gate SBD_SET_ERRNO(SBD_HD2ERR(hp), ENOTTY); 782*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 783*7c478bd9Sstevel@tonic-gate "sbd:%s: unknown command (%d)", 784*7c478bd9Sstevel@tonic-gate f, hp->h_cmd); 785*7c478bd9Sstevel@tonic-gate break; 786*7c478bd9Sstevel@tonic-gate 787*7c478bd9Sstevel@tonic-gate } 788*7c478bd9Sstevel@tonic-gate 789*7c478bd9Sstevel@tonic-gate if (SBD_GET_ERR(SBD_HD2ERR(hp))) 790*7c478bd9Sstevel@tonic-gate PR_BYP("XXX e_code=%d", SBD_GET_ERR(SBD_HD2ERR(hp))); 791*7c478bd9Sstevel@tonic-gate if (SBD_GET_ERRNO(SBD_HD2ERR(hp))) 792*7c478bd9Sstevel@tonic-gate PR_BYP("XXX errno=%d", SBD_GET_ERRNO(SBD_HD2ERR(hp))); 793*7c478bd9Sstevel@tonic-gate } 794*7c478bd9Sstevel@tonic-gate 795*7c478bd9Sstevel@tonic-gate sbd_comp_type_t 796*7c478bd9Sstevel@tonic-gate sbd_get_devtype(sbd_handle_t *hp, dev_info_t *dip) 797*7c478bd9Sstevel@tonic-gate { 798*7c478bd9Sstevel@tonic-gate sbd_board_t *sbp = hp ? SBDH2BD(hp->h_sbd) : NULL; 799*7c478bd9Sstevel@tonic-gate sbd_istate_t bstate; 800*7c478bd9Sstevel@tonic-gate dev_info_t **devlist; 801*7c478bd9Sstevel@tonic-gate int i; 802*7c478bd9Sstevel@tonic-gate char device[OBP_MAXDRVNAME]; 803*7c478bd9Sstevel@tonic-gate int devicelen; 804*7c478bd9Sstevel@tonic-gate 805*7c478bd9Sstevel@tonic-gate devicelen = sizeof (device); 806*7c478bd9Sstevel@tonic-gate 807*7c478bd9Sstevel@tonic-gate bstate = sbp ? SBD_BOARD_STATE(sbp) : SBD_STATE_EMPTY; 808*7c478bd9Sstevel@tonic-gate /* 809*7c478bd9Sstevel@tonic-gate * if the board's connected or configured, search the 810*7c478bd9Sstevel@tonic-gate * devlists. Otherwise check the device tree 811*7c478bd9Sstevel@tonic-gate */ 812*7c478bd9Sstevel@tonic-gate switch (bstate) { 813*7c478bd9Sstevel@tonic-gate 814*7c478bd9Sstevel@tonic-gate case SBD_STATE_CONNECTED: 815*7c478bd9Sstevel@tonic-gate case SBD_STATE_CONFIGURED: 816*7c478bd9Sstevel@tonic-gate case SBD_STATE_UNREFERENCED: 817*7c478bd9Sstevel@tonic-gate case SBD_STATE_UNCONFIGURED: 818*7c478bd9Sstevel@tonic-gate devlist = sbp->sb_devlist[NIX(SBD_COMP_MEM)]; 819*7c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_MEM_UNITS_PER_BOARD; i++) 820*7c478bd9Sstevel@tonic-gate if (devlist[i] == dip) 821*7c478bd9Sstevel@tonic-gate return (SBD_COMP_MEM); 822*7c478bd9Sstevel@tonic-gate 823*7c478bd9Sstevel@tonic-gate devlist = sbp->sb_devlist[NIX(SBD_COMP_CPU)]; 824*7c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_CPU_UNITS_PER_BOARD; i++) 825*7c478bd9Sstevel@tonic-gate if (devlist[i] == dip) 826*7c478bd9Sstevel@tonic-gate return (SBD_COMP_CPU); 827*7c478bd9Sstevel@tonic-gate 828*7c478bd9Sstevel@tonic-gate devlist = sbp->sb_devlist[NIX(SBD_COMP_IO)]; 829*7c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_IO_UNITS_PER_BOARD; i++) 830*7c478bd9Sstevel@tonic-gate if (devlist[i] == dip) 831*7c478bd9Sstevel@tonic-gate return (SBD_COMP_IO); 832*7c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 833*7c478bd9Sstevel@tonic-gate 834*7c478bd9Sstevel@tonic-gate default: 835*7c478bd9Sstevel@tonic-gate if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 836*7c478bd9Sstevel@tonic-gate OBP_DEVICETYPE, (caddr_t)device, &devicelen)) 837*7c478bd9Sstevel@tonic-gate break; 838*7c478bd9Sstevel@tonic-gate 839*7c478bd9Sstevel@tonic-gate for (i = 0; SBD_COMP(i) != SBD_COMP_UNKNOWN; i++) { 840*7c478bd9Sstevel@tonic-gate if (strcmp(device, SBD_OTYPE(i)) != 0) 841*7c478bd9Sstevel@tonic-gate continue; 842*7c478bd9Sstevel@tonic-gate return (SBD_COMP(i)); 843*7c478bd9Sstevel@tonic-gate } 844*7c478bd9Sstevel@tonic-gate 845*7c478bd9Sstevel@tonic-gate break; 846*7c478bd9Sstevel@tonic-gate } 847*7c478bd9Sstevel@tonic-gate return (SBD_COMP_UNKNOWN); 848*7c478bd9Sstevel@tonic-gate } 849*7c478bd9Sstevel@tonic-gate 850*7c478bd9Sstevel@tonic-gate static void 851*7c478bd9Sstevel@tonic-gate sbd_dev_configure(sbd_handle_t *hp) 852*7c478bd9Sstevel@tonic-gate { 853*7c478bd9Sstevel@tonic-gate int n, unit; 854*7c478bd9Sstevel@tonic-gate int32_t pass, devnum; 855*7c478bd9Sstevel@tonic-gate dev_info_t *dip; 856*7c478bd9Sstevel@tonic-gate sbd_devlist_t *devlist; 857*7c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 858*7c478bd9Sstevel@tonic-gate sbd_comp_type_t nodetype; 859*7c478bd9Sstevel@tonic-gate sbd_board_t *sbp = SBDH2BD(hp->h_sbd); 860*7c478bd9Sstevel@tonic-gate 861*7c478bd9Sstevel@tonic-gate pass = 1; 862*7c478bd9Sstevel@tonic-gate 863*7c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 864*7c478bd9Sstevel@tonic-gate while ((devlist = sbd_get_attach_devlist(hp, &devnum, pass)) != NULL) { 865*7c478bd9Sstevel@tonic-gate int err; 866*7c478bd9Sstevel@tonic-gate 867*7c478bd9Sstevel@tonic-gate err = sbd_pre_attach_devlist(hp, devlist, devnum); 868*7c478bd9Sstevel@tonic-gate if (err < 0) { 869*7c478bd9Sstevel@tonic-gate break; 870*7c478bd9Sstevel@tonic-gate } else if (err > 0) { 871*7c478bd9Sstevel@tonic-gate pass++; 872*7c478bd9Sstevel@tonic-gate continue; 873*7c478bd9Sstevel@tonic-gate } 874*7c478bd9Sstevel@tonic-gate 875*7c478bd9Sstevel@tonic-gate for (n = 0; n < devnum; n++) { 876*7c478bd9Sstevel@tonic-gate sbderror_t *ep; 877*7c478bd9Sstevel@tonic-gate 878*7c478bd9Sstevel@tonic-gate ep = &devlist[n].dv_error; 879*7c478bd9Sstevel@tonic-gate SBD_SET_ERRNO(ep, 0); 880*7c478bd9Sstevel@tonic-gate SBD_SET_ERR(ep, 0); 881*7c478bd9Sstevel@tonic-gate dip = devlist[n].dv_dip; 882*7c478bd9Sstevel@tonic-gate nodetype = sbd_get_devtype(hp, dip); 883*7c478bd9Sstevel@tonic-gate 884*7c478bd9Sstevel@tonic-gate unit = sbdp_get_unit_num(hdp, dip); 885*7c478bd9Sstevel@tonic-gate if (unit < 0) { 886*7c478bd9Sstevel@tonic-gate SBD_GET_PERR(hdp->h_err, SBD_HD2ERR(hp)); 887*7c478bd9Sstevel@tonic-gate break; 888*7c478bd9Sstevel@tonic-gate } 889*7c478bd9Sstevel@tonic-gate 890*7c478bd9Sstevel@tonic-gate switch (nodetype) { 891*7c478bd9Sstevel@tonic-gate case SBD_COMP_MEM: 892*7c478bd9Sstevel@tonic-gate sbd_attach_mem(hp, ep); 893*7c478bd9Sstevel@tonic-gate if (SBD_GET_ERR(ep) == ESBD_CPUONLINE) { 894*7c478bd9Sstevel@tonic-gate FREESTRUCT(devlist, sbd_devlist_t, 895*7c478bd9Sstevel@tonic-gate MAX_MEM_UNITS_PER_BOARD); 896*7c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 897*7c478bd9Sstevel@tonic-gate return; 898*7c478bd9Sstevel@tonic-gate } 899*7c478bd9Sstevel@tonic-gate break; 900*7c478bd9Sstevel@tonic-gate 901*7c478bd9Sstevel@tonic-gate case SBD_COMP_CPU: 902*7c478bd9Sstevel@tonic-gate sbd_attach_cpu(hp, ep, dip, unit); 903*7c478bd9Sstevel@tonic-gate break; 904*7c478bd9Sstevel@tonic-gate 905*7c478bd9Sstevel@tonic-gate case SBD_COMP_IO: 906*7c478bd9Sstevel@tonic-gate sbd_attach_io(hp, ep, dip, unit); 907*7c478bd9Sstevel@tonic-gate break; 908*7c478bd9Sstevel@tonic-gate 909*7c478bd9Sstevel@tonic-gate default: 910*7c478bd9Sstevel@tonic-gate SBD_SET_ERRNO(ep, ENOTTY); 911*7c478bd9Sstevel@tonic-gate break; 912*7c478bd9Sstevel@tonic-gate } 913*7c478bd9Sstevel@tonic-gate 914*7c478bd9Sstevel@tonic-gate if (sbd_set_err_in_hdl(hp, ep) == 0) 915*7c478bd9Sstevel@tonic-gate continue; 916*7c478bd9Sstevel@tonic-gate } 917*7c478bd9Sstevel@tonic-gate 918*7c478bd9Sstevel@tonic-gate err = sbd_post_attach_devlist(hp, devlist, devnum); 919*7c478bd9Sstevel@tonic-gate if (err < 0) 920*7c478bd9Sstevel@tonic-gate break; 921*7c478bd9Sstevel@tonic-gate 922*7c478bd9Sstevel@tonic-gate pass++; 923*7c478bd9Sstevel@tonic-gate } 924*7c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 925*7c478bd9Sstevel@tonic-gate } 926*7c478bd9Sstevel@tonic-gate 927*7c478bd9Sstevel@tonic-gate static int 928*7c478bd9Sstevel@tonic-gate sbd_dev_release(sbd_handle_t *hp) 929*7c478bd9Sstevel@tonic-gate { 930*7c478bd9Sstevel@tonic-gate int n, unit; 931*7c478bd9Sstevel@tonic-gate int32_t pass, devnum; 932*7c478bd9Sstevel@tonic-gate dev_info_t *dip; 933*7c478bd9Sstevel@tonic-gate sbd_board_t *sbp = SBDH2BD(hp->h_sbd); 934*7c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 935*7c478bd9Sstevel@tonic-gate sbd_devlist_t *devlist; 936*7c478bd9Sstevel@tonic-gate sbd_comp_type_t nodetype; 937*7c478bd9Sstevel@tonic-gate int err = 0; 938*7c478bd9Sstevel@tonic-gate int dev_canceled; 939*7c478bd9Sstevel@tonic-gate 940*7c478bd9Sstevel@tonic-gate pass = 1; 941*7c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 942*7c478bd9Sstevel@tonic-gate 943*7c478bd9Sstevel@tonic-gate sbp->sb_busy = 1; 944*7c478bd9Sstevel@tonic-gate while ((devlist = 945*7c478bd9Sstevel@tonic-gate sbd_get_release_devlist(hp, &devnum, pass)) != NULL) { 946*7c478bd9Sstevel@tonic-gate 947*7c478bd9Sstevel@tonic-gate err = sbd_pre_release_devlist(hp, devlist, devnum); 948*7c478bd9Sstevel@tonic-gate if (err < 0) { 949*7c478bd9Sstevel@tonic-gate dev_canceled = 1; 950*7c478bd9Sstevel@tonic-gate break; 951*7c478bd9Sstevel@tonic-gate } else if (err > 0) { 952*7c478bd9Sstevel@tonic-gate pass++; 953*7c478bd9Sstevel@tonic-gate continue; 954*7c478bd9Sstevel@tonic-gate } 955*7c478bd9Sstevel@tonic-gate 956*7c478bd9Sstevel@tonic-gate dev_canceled = 0; 957*7c478bd9Sstevel@tonic-gate for (n = 0; n < devnum; n++) { 958*7c478bd9Sstevel@tonic-gate dip = devlist[n].dv_dip; 959*7c478bd9Sstevel@tonic-gate nodetype = sbd_get_devtype(hp, dip); 960*7c478bd9Sstevel@tonic-gate 961*7c478bd9Sstevel@tonic-gate unit = sbdp_get_unit_num(hdp, dip); 962*7c478bd9Sstevel@tonic-gate if (unit < 0) { 963*7c478bd9Sstevel@tonic-gate SBD_GET_PERR(hdp->h_err, SBD_HD2ERR(hp)); 964*7c478bd9Sstevel@tonic-gate break; 965*7c478bd9Sstevel@tonic-gate } 966*7c478bd9Sstevel@tonic-gate 967*7c478bd9Sstevel@tonic-gate if ((nodetype == SBD_COMP_MEM) && 968*7c478bd9Sstevel@tonic-gate sbd_release_mem(hp, dip, unit)) { 969*7c478bd9Sstevel@tonic-gate 970*7c478bd9Sstevel@tonic-gate dev_canceled++; 971*7c478bd9Sstevel@tonic-gate } 972*7c478bd9Sstevel@tonic-gate 973*7c478bd9Sstevel@tonic-gate sbd_release_done(hp, nodetype, dip); 974*7c478bd9Sstevel@tonic-gate } 975*7c478bd9Sstevel@tonic-gate 976*7c478bd9Sstevel@tonic-gate err = sbd_post_release_devlist(hp, devlist, devnum); 977*7c478bd9Sstevel@tonic-gate 978*7c478bd9Sstevel@tonic-gate if (err < 0) 979*7c478bd9Sstevel@tonic-gate break; 980*7c478bd9Sstevel@tonic-gate 981*7c478bd9Sstevel@tonic-gate if (dev_canceled) 982*7c478bd9Sstevel@tonic-gate break; 983*7c478bd9Sstevel@tonic-gate 984*7c478bd9Sstevel@tonic-gate pass++; 985*7c478bd9Sstevel@tonic-gate } 986*7c478bd9Sstevel@tonic-gate sbp->sb_busy = 0; 987*7c478bd9Sstevel@tonic-gate 988*7c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 989*7c478bd9Sstevel@tonic-gate 990*7c478bd9Sstevel@tonic-gate if (dev_canceled) 991*7c478bd9Sstevel@tonic-gate return (dev_canceled); 992*7c478bd9Sstevel@tonic-gate 993*7c478bd9Sstevel@tonic-gate return (err); 994*7c478bd9Sstevel@tonic-gate } 995*7c478bd9Sstevel@tonic-gate 996*7c478bd9Sstevel@tonic-gate static int 997*7c478bd9Sstevel@tonic-gate sbd_dev_unconfigure(sbd_handle_t *hp) 998*7c478bd9Sstevel@tonic-gate { 999*7c478bd9Sstevel@tonic-gate int n, unit; 1000*7c478bd9Sstevel@tonic-gate int32_t pass, devnum; 1001*7c478bd9Sstevel@tonic-gate dev_info_t *dip; 1002*7c478bd9Sstevel@tonic-gate sbd_devlist_t *devlist; 1003*7c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 1004*7c478bd9Sstevel@tonic-gate sbd_comp_type_t nodetype; 1005*7c478bd9Sstevel@tonic-gate sbd_board_t *sbp = SBDH2BD(hp->h_sbd); 1006*7c478bd9Sstevel@tonic-gate int dev_canceled = 0; 1007*7c478bd9Sstevel@tonic-gate static fn_t f = "sbd_dev_unconfigure"; 1008*7c478bd9Sstevel@tonic-gate 1009*7c478bd9Sstevel@tonic-gate PR_ALL("%s...\n", f); 1010*7c478bd9Sstevel@tonic-gate 1011*7c478bd9Sstevel@tonic-gate pass = 1; 1012*7c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 1013*7c478bd9Sstevel@tonic-gate 1014*7c478bd9Sstevel@tonic-gate while ((devlist = sbd_get_detach_devlist(hp, &devnum, pass)) != NULL) { 1015*7c478bd9Sstevel@tonic-gate int err, detach_err = 0; 1016*7c478bd9Sstevel@tonic-gate 1017*7c478bd9Sstevel@tonic-gate err = sbd_pre_detach_devlist(hp, devlist, devnum); 1018*7c478bd9Sstevel@tonic-gate if (err) { 1019*7c478bd9Sstevel@tonic-gate /* 1020*7c478bd9Sstevel@tonic-gate * Only cancel the operation for memory in 1021*7c478bd9Sstevel@tonic-gate * case of failure. 1022*7c478bd9Sstevel@tonic-gate */ 1023*7c478bd9Sstevel@tonic-gate nodetype = sbd_get_devtype(hp, devlist->dv_dip); 1024*7c478bd9Sstevel@tonic-gate if (nodetype == SBD_COMP_MEM) 1025*7c478bd9Sstevel@tonic-gate dev_canceled = 1; 1026*7c478bd9Sstevel@tonic-gate (void) sbd_post_detach_devlist(hp, devlist, devnum); 1027*7c478bd9Sstevel@tonic-gate break; 1028*7c478bd9Sstevel@tonic-gate } 1029*7c478bd9Sstevel@tonic-gate 1030*7c478bd9Sstevel@tonic-gate for (n = 0; n < devnum; n++) { 1031*7c478bd9Sstevel@tonic-gate sbderror_t *ep; 1032*7c478bd9Sstevel@tonic-gate 1033*7c478bd9Sstevel@tonic-gate ep = &devlist[n].dv_error; 1034*7c478bd9Sstevel@tonic-gate SBD_SET_ERRNO(ep, 0); 1035*7c478bd9Sstevel@tonic-gate SBD_SET_ERR(ep, 0); 1036*7c478bd9Sstevel@tonic-gate dip = devlist[n].dv_dip; 1037*7c478bd9Sstevel@tonic-gate nodetype = sbd_get_devtype(hp, dip); 1038*7c478bd9Sstevel@tonic-gate 1039*7c478bd9Sstevel@tonic-gate unit = sbdp_get_unit_num(hdp, dip); 1040*7c478bd9Sstevel@tonic-gate if (unit < 0) { 1041*7c478bd9Sstevel@tonic-gate SBD_GET_PERR(hdp->h_err, SBD_HD2ERR(hp)); 1042*7c478bd9Sstevel@tonic-gate break; 1043*7c478bd9Sstevel@tonic-gate } 1044*7c478bd9Sstevel@tonic-gate 1045*7c478bd9Sstevel@tonic-gate switch (nodetype) { 1046*7c478bd9Sstevel@tonic-gate case SBD_COMP_MEM: 1047*7c478bd9Sstevel@tonic-gate dev_canceled = sbd_detach_mem(hp, ep, unit); 1048*7c478bd9Sstevel@tonic-gate break; 1049*7c478bd9Sstevel@tonic-gate 1050*7c478bd9Sstevel@tonic-gate case SBD_COMP_CPU: 1051*7c478bd9Sstevel@tonic-gate sbd_detach_cpu(hp, ep, dip, unit); 1052*7c478bd9Sstevel@tonic-gate break; 1053*7c478bd9Sstevel@tonic-gate 1054*7c478bd9Sstevel@tonic-gate case SBD_COMP_IO: 1055*7c478bd9Sstevel@tonic-gate sbd_detach_io(hp, ep, dip, unit); 1056*7c478bd9Sstevel@tonic-gate break; 1057*7c478bd9Sstevel@tonic-gate 1058*7c478bd9Sstevel@tonic-gate default: 1059*7c478bd9Sstevel@tonic-gate SBD_SET_ERRNO(ep, ENOTTY); 1060*7c478bd9Sstevel@tonic-gate break; 1061*7c478bd9Sstevel@tonic-gate } 1062*7c478bd9Sstevel@tonic-gate 1063*7c478bd9Sstevel@tonic-gate if (sbd_set_err_in_hdl(hp, ep) == 0) { 1064*7c478bd9Sstevel@tonic-gate detach_err = -1; 1065*7c478bd9Sstevel@tonic-gate break; 1066*7c478bd9Sstevel@tonic-gate } 1067*7c478bd9Sstevel@tonic-gate 1068*7c478bd9Sstevel@tonic-gate } 1069*7c478bd9Sstevel@tonic-gate err = sbd_post_detach_devlist(hp, devlist, devnum); 1070*7c478bd9Sstevel@tonic-gate if ((err < 0) || (detach_err < 0)) 1071*7c478bd9Sstevel@tonic-gate break; 1072*7c478bd9Sstevel@tonic-gate 1073*7c478bd9Sstevel@tonic-gate pass++; 1074*7c478bd9Sstevel@tonic-gate } 1075*7c478bd9Sstevel@tonic-gate 1076*7c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 1077*7c478bd9Sstevel@tonic-gate return (dev_canceled); 1078*7c478bd9Sstevel@tonic-gate } 1079*7c478bd9Sstevel@tonic-gate 1080*7c478bd9Sstevel@tonic-gate int 1081*7c478bd9Sstevel@tonic-gate sbd_errno2ecode(int error) 1082*7c478bd9Sstevel@tonic-gate { 1083*7c478bd9Sstevel@tonic-gate int rv; 1084*7c478bd9Sstevel@tonic-gate 1085*7c478bd9Sstevel@tonic-gate switch (error) { 1086*7c478bd9Sstevel@tonic-gate case EBUSY: 1087*7c478bd9Sstevel@tonic-gate rv = ESBD_BUSY; 1088*7c478bd9Sstevel@tonic-gate break; 1089*7c478bd9Sstevel@tonic-gate case EINVAL: 1090*7c478bd9Sstevel@tonic-gate rv = ESBD_INVAL; 1091*7c478bd9Sstevel@tonic-gate break; 1092*7c478bd9Sstevel@tonic-gate case EALREADY: 1093*7c478bd9Sstevel@tonic-gate rv = ESBD_ALREADY; 1094*7c478bd9Sstevel@tonic-gate break; 1095*7c478bd9Sstevel@tonic-gate case ENODEV: 1096*7c478bd9Sstevel@tonic-gate rv = ESBD_NODEV; 1097*7c478bd9Sstevel@tonic-gate break; 1098*7c478bd9Sstevel@tonic-gate case ENOMEM: 1099*7c478bd9Sstevel@tonic-gate rv = ESBD_NOMEM; 1100*7c478bd9Sstevel@tonic-gate break; 1101*7c478bd9Sstevel@tonic-gate default: 1102*7c478bd9Sstevel@tonic-gate rv = ESBD_INVAL; 1103*7c478bd9Sstevel@tonic-gate } 1104*7c478bd9Sstevel@tonic-gate 1105*7c478bd9Sstevel@tonic-gate return (rv); 1106*7c478bd9Sstevel@tonic-gate } 1107*7c478bd9Sstevel@tonic-gate 1108*7c478bd9Sstevel@tonic-gate static void 1109*7c478bd9Sstevel@tonic-gate sbd_attach_cpu(sbd_handle_t *hp, sbderror_t *ep, dev_info_t *dip, int unit) 1110*7c478bd9Sstevel@tonic-gate { 1111*7c478bd9Sstevel@tonic-gate int rv = 0; 1112*7c478bd9Sstevel@tonic-gate processorid_t cpuid; 1113*7c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 1114*7c478bd9Sstevel@tonic-gate sbd_board_t *sbp = SBDH2BD(hp->h_sbd); 1115*7c478bd9Sstevel@tonic-gate static fn_t f = "sbd_attach_cpu"; 1116*7c478bd9Sstevel@tonic-gate char *pathname; 1117*7c478bd9Sstevel@tonic-gate 1118*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&cpu_lock)); 1119*7c478bd9Sstevel@tonic-gate 1120*7c478bd9Sstevel@tonic-gate ASSERT(dip); 1121*7c478bd9Sstevel@tonic-gate 1122*7c478bd9Sstevel@tonic-gate /* 1123*7c478bd9Sstevel@tonic-gate * With the introduction of CMP devices, the CPU nodes 1124*7c478bd9Sstevel@tonic-gate * are no longer directly under the top node. Since 1125*7c478bd9Sstevel@tonic-gate * there is no plan to support CPU attach in the near 1126*7c478bd9Sstevel@tonic-gate * future, a branch configure operation is not required. 1127*7c478bd9Sstevel@tonic-gate */ 1128*7c478bd9Sstevel@tonic-gate 1129*7c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 1130*7c478bd9Sstevel@tonic-gate cpuid = sbdp_get_cpuid(hdp, dip); 1131*7c478bd9Sstevel@tonic-gate if (cpuid < 0) { 1132*7c478bd9Sstevel@tonic-gate rv = -1; 1133*7c478bd9Sstevel@tonic-gate SBD_GET_PERR(hdp->h_err, ep); 1134*7c478bd9Sstevel@tonic-gate } else if ((rv = cpu_configure(cpuid)) != 0) { 1135*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 1136*7c478bd9Sstevel@tonic-gate "sbd:%s: cpu_configure for cpuid %d failed", 1137*7c478bd9Sstevel@tonic-gate f, cpuid); 1138*7c478bd9Sstevel@tonic-gate SBD_SET_ERR(ep, sbd_errno2ecode(rv)); 1139*7c478bd9Sstevel@tonic-gate } 1140*7c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 1141*7c478bd9Sstevel@tonic-gate 1142*7c478bd9Sstevel@tonic-gate if (rv == 0) { 1143*7c478bd9Sstevel@tonic-gate ASSERT(sbp->sb_cpupath[unit] != NULL); 1144*7c478bd9Sstevel@tonic-gate pathname = sbp->sb_cpupath[unit]; 1145*7c478bd9Sstevel@tonic-gate (void) ddi_pathname(dip, pathname); 1146*7c478bd9Sstevel@tonic-gate } 1147*7c478bd9Sstevel@tonic-gate } 1148*7c478bd9Sstevel@tonic-gate 1149*7c478bd9Sstevel@tonic-gate /* 1150*7c478bd9Sstevel@tonic-gate * translate errno 1151*7c478bd9Sstevel@tonic-gate */ 1152*7c478bd9Sstevel@tonic-gate void 1153*7c478bd9Sstevel@tonic-gate sbd_errno_decode(int err, sbderror_t *ep, dev_info_t *dip) 1154*7c478bd9Sstevel@tonic-gate { 1155*7c478bd9Sstevel@tonic-gate ASSERT(err != 0); 1156*7c478bd9Sstevel@tonic-gate 1157*7c478bd9Sstevel@tonic-gate switch (err) { 1158*7c478bd9Sstevel@tonic-gate case ENOMEM: 1159*7c478bd9Sstevel@tonic-gate SBD_SET_ERR(ep, ESBD_NOMEM); 1160*7c478bd9Sstevel@tonic-gate break; 1161*7c478bd9Sstevel@tonic-gate 1162*7c478bd9Sstevel@tonic-gate case EBUSY: 1163*7c478bd9Sstevel@tonic-gate SBD_SET_ERR(ep, ESBD_BUSY); 1164*7c478bd9Sstevel@tonic-gate break; 1165*7c478bd9Sstevel@tonic-gate 1166*7c478bd9Sstevel@tonic-gate case EIO: 1167*7c478bd9Sstevel@tonic-gate SBD_SET_ERR(ep, ESBD_IO); 1168*7c478bd9Sstevel@tonic-gate break; 1169*7c478bd9Sstevel@tonic-gate 1170*7c478bd9Sstevel@tonic-gate case ENXIO: 1171*7c478bd9Sstevel@tonic-gate SBD_SET_ERR(ep, ESBD_NODEV); 1172*7c478bd9Sstevel@tonic-gate break; 1173*7c478bd9Sstevel@tonic-gate 1174*7c478bd9Sstevel@tonic-gate case EINVAL: 1175*7c478bd9Sstevel@tonic-gate SBD_SET_ERR(ep, ESBD_INVAL); 1176*7c478bd9Sstevel@tonic-gate break; 1177*7c478bd9Sstevel@tonic-gate 1178*7c478bd9Sstevel@tonic-gate case EFAULT: 1179*7c478bd9Sstevel@tonic-gate default: 1180*7c478bd9Sstevel@tonic-gate SBD_SET_ERR(ep, ESBD_FAULT); 1181*7c478bd9Sstevel@tonic-gate break; 1182*7c478bd9Sstevel@tonic-gate } 1183*7c478bd9Sstevel@tonic-gate 1184*7c478bd9Sstevel@tonic-gate (void) ddi_pathname(dip, SBD_GET_ERRSTR(ep)); 1185*7c478bd9Sstevel@tonic-gate } 1186*7c478bd9Sstevel@tonic-gate 1187*7c478bd9Sstevel@tonic-gate static void 1188*7c478bd9Sstevel@tonic-gate sbd_detach_cpu(sbd_handle_t *hp, sbderror_t *ep, dev_info_t *dip, int unit) 1189*7c478bd9Sstevel@tonic-gate { 1190*7c478bd9Sstevel@tonic-gate processorid_t cpuid; 1191*7c478bd9Sstevel@tonic-gate int rv; 1192*7c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 1193*7c478bd9Sstevel@tonic-gate sbd_board_t *sbp = SBDH2BD(hp->h_sbd); 1194*7c478bd9Sstevel@tonic-gate sbd_error_t *spe; 1195*7c478bd9Sstevel@tonic-gate static fn_t f = "sbd_detach_cpu"; 1196*7c478bd9Sstevel@tonic-gate 1197*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&cpu_lock)); 1198*7c478bd9Sstevel@tonic-gate 1199*7c478bd9Sstevel@tonic-gate ASSERT(dip); 1200*7c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 1201*7c478bd9Sstevel@tonic-gate spe = hdp->h_err; 1202*7c478bd9Sstevel@tonic-gate cpuid = sbdp_get_cpuid(hdp, dip); 1203*7c478bd9Sstevel@tonic-gate if (cpuid < 0) { 1204*7c478bd9Sstevel@tonic-gate SBD_GET_PERR(spe, ep); 1205*7c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 1206*7c478bd9Sstevel@tonic-gate return; 1207*7c478bd9Sstevel@tonic-gate } 1208*7c478bd9Sstevel@tonic-gate 1209*7c478bd9Sstevel@tonic-gate if ((rv = cpu_unconfigure(cpuid)) != 0) { 1210*7c478bd9Sstevel@tonic-gate SBD_SET_ERR(ep, sbd_errno2ecode(rv)); 1211*7c478bd9Sstevel@tonic-gate SBD_SET_ERRSTR(ep, sbp->sb_cpupath[unit]); 1212*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 1213*7c478bd9Sstevel@tonic-gate "sbd:%s: cpu_unconfigure for cpu %d failed", 1214*7c478bd9Sstevel@tonic-gate f, cpuid); 1215*7c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 1216*7c478bd9Sstevel@tonic-gate return; 1217*7c478bd9Sstevel@tonic-gate } 1218*7c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 1219*7c478bd9Sstevel@tonic-gate 1220*7c478bd9Sstevel@tonic-gate /* 1221*7c478bd9Sstevel@tonic-gate * Since CPU nodes are no longer configured in CPU 1222*7c478bd9Sstevel@tonic-gate * attach, the corresponding branch unconfigure 1223*7c478bd9Sstevel@tonic-gate * operation that would be performed here is also 1224*7c478bd9Sstevel@tonic-gate * no longer required. 1225*7c478bd9Sstevel@tonic-gate */ 1226*7c478bd9Sstevel@tonic-gate } 1227*7c478bd9Sstevel@tonic-gate 1228*7c478bd9Sstevel@tonic-gate 1229*7c478bd9Sstevel@tonic-gate int 1230*7c478bd9Sstevel@tonic-gate sbd_detach_mem(sbd_handle_t *hp, sbderror_t *ep, int unit) 1231*7c478bd9Sstevel@tonic-gate { 1232*7c478bd9Sstevel@tonic-gate sbd_mem_unit_t *mp; 1233*7c478bd9Sstevel@tonic-gate sbd_board_t *sbp = SBDH2BD(hp->h_sbd); 1234*7c478bd9Sstevel@tonic-gate int i, rv; 1235*7c478bd9Sstevel@tonic-gate static fn_t f = "sbd_detach_mem"; 1236*7c478bd9Sstevel@tonic-gate 1237*7c478bd9Sstevel@tonic-gate mp = SBD_GET_BOARD_MEMUNIT(sbp, unit); 1238*7c478bd9Sstevel@tonic-gate 1239*7c478bd9Sstevel@tonic-gate if (sbd_detach_memory(hp, ep, mp, unit)) { 1240*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "%s: detach fail", f); 1241*7c478bd9Sstevel@tonic-gate return (-1); 1242*7c478bd9Sstevel@tonic-gate } 1243*7c478bd9Sstevel@tonic-gate 1244*7c478bd9Sstevel@tonic-gate /* 1245*7c478bd9Sstevel@tonic-gate * Now detach mem devinfo nodes with status lock held. 1246*7c478bd9Sstevel@tonic-gate */ 1247*7c478bd9Sstevel@tonic-gate for (i = 0; i < SBD_NUM_MC_PER_BOARD; i++) { 1248*7c478bd9Sstevel@tonic-gate dev_info_t *fdip = NULL; 1249*7c478bd9Sstevel@tonic-gate 1250*7c478bd9Sstevel@tonic-gate if (mp->sbm_dip[i] == NULL) 1251*7c478bd9Sstevel@tonic-gate continue; 1252*7c478bd9Sstevel@tonic-gate ASSERT(e_ddi_branch_held(mp->sbm_dip[i])); 1253*7c478bd9Sstevel@tonic-gate mutex_enter(&sbp->sb_slock); 1254*7c478bd9Sstevel@tonic-gate rv = e_ddi_branch_unconfigure(mp->sbm_dip[i], &fdip, 1255*7c478bd9Sstevel@tonic-gate DEVI_BRANCH_EVENT); 1256*7c478bd9Sstevel@tonic-gate mutex_exit(&sbp->sb_slock); 1257*7c478bd9Sstevel@tonic-gate if (rv) { 1258*7c478bd9Sstevel@tonic-gate /* 1259*7c478bd9Sstevel@tonic-gate * If non-NULL, fdip is returned held and must be 1260*7c478bd9Sstevel@tonic-gate * released. 1261*7c478bd9Sstevel@tonic-gate */ 1262*7c478bd9Sstevel@tonic-gate if (fdip != NULL) { 1263*7c478bd9Sstevel@tonic-gate sbd_errno_decode(rv, ep, fdip); 1264*7c478bd9Sstevel@tonic-gate ddi_release_devi(fdip); 1265*7c478bd9Sstevel@tonic-gate } else { 1266*7c478bd9Sstevel@tonic-gate sbd_errno_decode(rv, ep, mp->sbm_dip[i]); 1267*7c478bd9Sstevel@tonic-gate } 1268*7c478bd9Sstevel@tonic-gate } 1269*7c478bd9Sstevel@tonic-gate } 1270*7c478bd9Sstevel@tonic-gate 1271*7c478bd9Sstevel@tonic-gate return (0); 1272*7c478bd9Sstevel@tonic-gate } 1273*7c478bd9Sstevel@tonic-gate 1274*7c478bd9Sstevel@tonic-gate /* start beginning of sbd.c */ 1275*7c478bd9Sstevel@tonic-gate 1276*7c478bd9Sstevel@tonic-gate /* 1277*7c478bd9Sstevel@tonic-gate * MDR memory support - somewhat disabled for now. 1278*7c478bd9Sstevel@tonic-gate * UNSAFE unsafe driver code - I don't think we want this. 1279*7c478bd9Sstevel@tonic-gate * need to check. 1280*7c478bd9Sstevel@tonic-gate * DEVNODE This driver creates attachment points for individual 1281*7c478bd9Sstevel@tonic-gate * components as well as boards. We only need board 1282*7c478bd9Sstevel@tonic-gate * support. 1283*7c478bd9Sstevel@tonic-gate * DEV2DEVSET Put only present devices in devset. 1284*7c478bd9Sstevel@tonic-gate */ 1285*7c478bd9Sstevel@tonic-gate 1286*7c478bd9Sstevel@tonic-gate 1287*7c478bd9Sstevel@tonic-gate static sbd_state_t 1288*7c478bd9Sstevel@tonic-gate rstate_cvt(sbd_istate_t state) 1289*7c478bd9Sstevel@tonic-gate { 1290*7c478bd9Sstevel@tonic-gate sbd_state_t cs; 1291*7c478bd9Sstevel@tonic-gate 1292*7c478bd9Sstevel@tonic-gate switch (state) { 1293*7c478bd9Sstevel@tonic-gate case SBD_STATE_EMPTY: 1294*7c478bd9Sstevel@tonic-gate cs = SBD_STAT_EMPTY; 1295*7c478bd9Sstevel@tonic-gate break; 1296*7c478bd9Sstevel@tonic-gate case SBD_STATE_OCCUPIED: 1297*7c478bd9Sstevel@tonic-gate case SBD_STATE_FATAL: 1298*7c478bd9Sstevel@tonic-gate cs = SBD_STAT_DISCONNECTED; 1299*7c478bd9Sstevel@tonic-gate break; 1300*7c478bd9Sstevel@tonic-gate case SBD_STATE_CONFIGURED: 1301*7c478bd9Sstevel@tonic-gate case SBD_STATE_CONNECTED: 1302*7c478bd9Sstevel@tonic-gate case SBD_STATE_UNCONFIGURED: 1303*7c478bd9Sstevel@tonic-gate case SBD_STATE_PARTIAL: 1304*7c478bd9Sstevel@tonic-gate case SBD_STATE_RELEASE: 1305*7c478bd9Sstevel@tonic-gate case SBD_STATE_UNREFERENCED: 1306*7c478bd9Sstevel@tonic-gate cs = SBD_STAT_CONNECTED; 1307*7c478bd9Sstevel@tonic-gate break; 1308*7c478bd9Sstevel@tonic-gate default: 1309*7c478bd9Sstevel@tonic-gate cs = SBD_STAT_NONE; 1310*7c478bd9Sstevel@tonic-gate break; 1311*7c478bd9Sstevel@tonic-gate } 1312*7c478bd9Sstevel@tonic-gate 1313*7c478bd9Sstevel@tonic-gate return (cs); 1314*7c478bd9Sstevel@tonic-gate } 1315*7c478bd9Sstevel@tonic-gate 1316*7c478bd9Sstevel@tonic-gate 1317*7c478bd9Sstevel@tonic-gate sbd_state_t 1318*7c478bd9Sstevel@tonic-gate ostate_cvt(sbd_istate_t state) 1319*7c478bd9Sstevel@tonic-gate { 1320*7c478bd9Sstevel@tonic-gate sbd_state_t cs; 1321*7c478bd9Sstevel@tonic-gate 1322*7c478bd9Sstevel@tonic-gate switch (state) { 1323*7c478bd9Sstevel@tonic-gate case SBD_STATE_EMPTY: 1324*7c478bd9Sstevel@tonic-gate case SBD_STATE_OCCUPIED: 1325*7c478bd9Sstevel@tonic-gate case SBD_STATE_UNCONFIGURED: 1326*7c478bd9Sstevel@tonic-gate case SBD_STATE_CONNECTED: 1327*7c478bd9Sstevel@tonic-gate case SBD_STATE_FATAL: 1328*7c478bd9Sstevel@tonic-gate cs = SBD_STAT_UNCONFIGURED; 1329*7c478bd9Sstevel@tonic-gate break; 1330*7c478bd9Sstevel@tonic-gate case SBD_STATE_PARTIAL: 1331*7c478bd9Sstevel@tonic-gate case SBD_STATE_CONFIGURED: 1332*7c478bd9Sstevel@tonic-gate case SBD_STATE_RELEASE: 1333*7c478bd9Sstevel@tonic-gate case SBD_STATE_UNREFERENCED: 1334*7c478bd9Sstevel@tonic-gate cs = SBD_STAT_CONFIGURED; 1335*7c478bd9Sstevel@tonic-gate break; 1336*7c478bd9Sstevel@tonic-gate default: 1337*7c478bd9Sstevel@tonic-gate cs = SBD_STAT_NONE; 1338*7c478bd9Sstevel@tonic-gate break; 1339*7c478bd9Sstevel@tonic-gate } 1340*7c478bd9Sstevel@tonic-gate 1341*7c478bd9Sstevel@tonic-gate return (cs); 1342*7c478bd9Sstevel@tonic-gate } 1343*7c478bd9Sstevel@tonic-gate 1344*7c478bd9Sstevel@tonic-gate int 1345*7c478bd9Sstevel@tonic-gate sbd_dealloc_instance(sbd_board_t *sbp, int max_boards) 1346*7c478bd9Sstevel@tonic-gate { 1347*7c478bd9Sstevel@tonic-gate int b; 1348*7c478bd9Sstevel@tonic-gate sbd_board_t *list = sbp; 1349*7c478bd9Sstevel@tonic-gate static fn_t f = "sbd_dealloc_instance"; 1350*7c478bd9Sstevel@tonic-gate 1351*7c478bd9Sstevel@tonic-gate PR_ALL("%s...\n", f); 1352*7c478bd9Sstevel@tonic-gate 1353*7c478bd9Sstevel@tonic-gate if (sbp == NULL) { 1354*7c478bd9Sstevel@tonic-gate return (-1); 1355*7c478bd9Sstevel@tonic-gate } 1356*7c478bd9Sstevel@tonic-gate 1357*7c478bd9Sstevel@tonic-gate for (b = 0; b < max_boards; b++) { 1358*7c478bd9Sstevel@tonic-gate sbd_board_destroy(sbp++); 1359*7c478bd9Sstevel@tonic-gate } 1360*7c478bd9Sstevel@tonic-gate 1361*7c478bd9Sstevel@tonic-gate FREESTRUCT(list, sbd_board_t, max_boards); 1362*7c478bd9Sstevel@tonic-gate 1363*7c478bd9Sstevel@tonic-gate return (0); 1364*7c478bd9Sstevel@tonic-gate } 1365*7c478bd9Sstevel@tonic-gate 1366*7c478bd9Sstevel@tonic-gate static sbd_devset_t 1367*7c478bd9Sstevel@tonic-gate sbd_dev2devset(sbd_comp_id_t *cid) 1368*7c478bd9Sstevel@tonic-gate { 1369*7c478bd9Sstevel@tonic-gate static fn_t f = "sbd_dev2devset"; 1370*7c478bd9Sstevel@tonic-gate 1371*7c478bd9Sstevel@tonic-gate sbd_devset_t devset; 1372*7c478bd9Sstevel@tonic-gate int unit = cid->c_unit; 1373*7c478bd9Sstevel@tonic-gate 1374*7c478bd9Sstevel@tonic-gate switch (cid->c_type) { 1375*7c478bd9Sstevel@tonic-gate case SBD_COMP_NONE: 1376*7c478bd9Sstevel@tonic-gate devset = DEVSET(SBD_COMP_CPU, DEVSET_ANYUNIT); 1377*7c478bd9Sstevel@tonic-gate devset |= DEVSET(SBD_COMP_MEM, DEVSET_ANYUNIT); 1378*7c478bd9Sstevel@tonic-gate devset |= DEVSET(SBD_COMP_IO, DEVSET_ANYUNIT); 1379*7c478bd9Sstevel@tonic-gate break; 1380*7c478bd9Sstevel@tonic-gate 1381*7c478bd9Sstevel@tonic-gate case SBD_COMP_CPU: 1382*7c478bd9Sstevel@tonic-gate if ((unit > MAX_CPU_UNITS_PER_BOARD) || (unit < 0)) { 1383*7c478bd9Sstevel@tonic-gate PR_ALL("%s: invalid cpu unit# = %d", 1384*7c478bd9Sstevel@tonic-gate f, unit); 1385*7c478bd9Sstevel@tonic-gate devset = 0; 1386*7c478bd9Sstevel@tonic-gate } else 1387*7c478bd9Sstevel@tonic-gate /* 1388*7c478bd9Sstevel@tonic-gate * Generate a devset that includes all the 1389*7c478bd9Sstevel@tonic-gate * cores of a CMP device. If this is not a 1390*7c478bd9Sstevel@tonic-gate * CMP, the extra cores will be eliminated 1391*7c478bd9Sstevel@tonic-gate * later since they are not present. This is 1392*7c478bd9Sstevel@tonic-gate * also true for CMP devices that do not have 1393*7c478bd9Sstevel@tonic-gate * all cores active. 1394*7c478bd9Sstevel@tonic-gate */ 1395*7c478bd9Sstevel@tonic-gate devset = DEVSET(SBD_COMP_CMP, unit); 1396*7c478bd9Sstevel@tonic-gate 1397*7c478bd9Sstevel@tonic-gate break; 1398*7c478bd9Sstevel@tonic-gate 1399*7c478bd9Sstevel@tonic-gate case SBD_COMP_MEM: 1400*7c478bd9Sstevel@tonic-gate 1401*7c478bd9Sstevel@tonic-gate if ((unit > MAX_MEM_UNITS_PER_BOARD) || (unit < 0)) { 1402*7c478bd9Sstevel@tonic-gate #ifdef XXX_jeffco 1403*7c478bd9Sstevel@tonic-gate PR_ALL("%s: invalid mem unit# = %d", 1404*7c478bd9Sstevel@tonic-gate f, unit); 1405*7c478bd9Sstevel@tonic-gate devset = 0; 1406*7c478bd9Sstevel@tonic-gate #endif 1407*7c478bd9Sstevel@tonic-gate devset = DEVSET(cid->c_type, 0); 1408*7c478bd9Sstevel@tonic-gate PR_ALL("%s: adjusted MEM devset = 0x%x\n", 1409*7c478bd9Sstevel@tonic-gate f, devset); 1410*7c478bd9Sstevel@tonic-gate } else 1411*7c478bd9Sstevel@tonic-gate devset = DEVSET(cid->c_type, unit); 1412*7c478bd9Sstevel@tonic-gate break; 1413*7c478bd9Sstevel@tonic-gate 1414*7c478bd9Sstevel@tonic-gate case SBD_COMP_IO: 1415*7c478bd9Sstevel@tonic-gate if ((unit > MAX_IO_UNITS_PER_BOARD) || (unit < 0)) { 1416*7c478bd9Sstevel@tonic-gate PR_ALL("%s: invalid io unit# = %d", 1417*7c478bd9Sstevel@tonic-gate f, unit); 1418*7c478bd9Sstevel@tonic-gate devset = 0; 1419*7c478bd9Sstevel@tonic-gate } else 1420*7c478bd9Sstevel@tonic-gate devset = DEVSET(cid->c_type, unit); 1421*7c478bd9Sstevel@tonic-gate 1422*7c478bd9Sstevel@tonic-gate break; 1423*7c478bd9Sstevel@tonic-gate 1424*7c478bd9Sstevel@tonic-gate default: 1425*7c478bd9Sstevel@tonic-gate case SBD_COMP_UNKNOWN: 1426*7c478bd9Sstevel@tonic-gate devset = 0; 1427*7c478bd9Sstevel@tonic-gate break; 1428*7c478bd9Sstevel@tonic-gate } 1429*7c478bd9Sstevel@tonic-gate 1430*7c478bd9Sstevel@tonic-gate return (devset); 1431*7c478bd9Sstevel@tonic-gate } 1432*7c478bd9Sstevel@tonic-gate 1433*7c478bd9Sstevel@tonic-gate /* 1434*7c478bd9Sstevel@tonic-gate * Simple mutex for covering handle list ops as it is only 1435*7c478bd9Sstevel@tonic-gate * used "infrequently". No need to add another mutex to the sbd_board_t. 1436*7c478bd9Sstevel@tonic-gate */ 1437*7c478bd9Sstevel@tonic-gate static kmutex_t sbd_handle_list_mutex; 1438*7c478bd9Sstevel@tonic-gate 1439*7c478bd9Sstevel@tonic-gate static sbd_handle_t * 1440*7c478bd9Sstevel@tonic-gate sbd_get_handle(dev_t dev, sbd_softstate_t *softsp, intptr_t arg, 1441*7c478bd9Sstevel@tonic-gate sbd_init_arg_t *iap) 1442*7c478bd9Sstevel@tonic-gate { 1443*7c478bd9Sstevel@tonic-gate sbd_handle_t *hp; 1444*7c478bd9Sstevel@tonic-gate sbderror_t *ep; 1445*7c478bd9Sstevel@tonic-gate sbd_priv_handle_t *shp; 1446*7c478bd9Sstevel@tonic-gate sbd_board_t *sbp = softsp->sbd_boardlist; 1447*7c478bd9Sstevel@tonic-gate int board; 1448*7c478bd9Sstevel@tonic-gate 1449*7c478bd9Sstevel@tonic-gate board = SBDGETSLOT(dev); 1450*7c478bd9Sstevel@tonic-gate ASSERT(board < softsp->max_boards); 1451*7c478bd9Sstevel@tonic-gate sbp += board; 1452*7c478bd9Sstevel@tonic-gate 1453*7c478bd9Sstevel@tonic-gate /* 1454*7c478bd9Sstevel@tonic-gate * Brand-new handle. 1455*7c478bd9Sstevel@tonic-gate */ 1456*7c478bd9Sstevel@tonic-gate shp = kmem_zalloc(sizeof (sbd_priv_handle_t), KM_SLEEP); 1457*7c478bd9Sstevel@tonic-gate shp->sh_arg = (void *)arg; 1458*7c478bd9Sstevel@tonic-gate 1459*7c478bd9Sstevel@tonic-gate hp = MACHHD2HD(shp); 1460*7c478bd9Sstevel@tonic-gate 1461*7c478bd9Sstevel@tonic-gate ep = &shp->sh_err; 1462*7c478bd9Sstevel@tonic-gate 1463*7c478bd9Sstevel@tonic-gate hp->h_err = ep; 1464*7c478bd9Sstevel@tonic-gate hp->h_sbd = (void *) sbp; 1465*7c478bd9Sstevel@tonic-gate hp->h_dev = iap->dev; 1466*7c478bd9Sstevel@tonic-gate hp->h_cmd = iap->cmd; 1467*7c478bd9Sstevel@tonic-gate hp->h_mode = iap->mode; 1468*7c478bd9Sstevel@tonic-gate sbd_init_err(ep); 1469*7c478bd9Sstevel@tonic-gate 1470*7c478bd9Sstevel@tonic-gate mutex_enter(&sbd_handle_list_mutex); 1471*7c478bd9Sstevel@tonic-gate shp->sh_next = sbp->sb_handle; 1472*7c478bd9Sstevel@tonic-gate sbp->sb_handle = shp; 1473*7c478bd9Sstevel@tonic-gate mutex_exit(&sbd_handle_list_mutex); 1474*7c478bd9Sstevel@tonic-gate 1475*7c478bd9Sstevel@tonic-gate return (hp); 1476*7c478bd9Sstevel@tonic-gate } 1477*7c478bd9Sstevel@tonic-gate 1478*7c478bd9Sstevel@tonic-gate void 1479*7c478bd9Sstevel@tonic-gate sbd_init_err(sbderror_t *ep) 1480*7c478bd9Sstevel@tonic-gate { 1481*7c478bd9Sstevel@tonic-gate ep->e_errno = 0; 1482*7c478bd9Sstevel@tonic-gate ep->e_code = 0; 1483*7c478bd9Sstevel@tonic-gate ep->e_rsc[0] = '\0'; 1484*7c478bd9Sstevel@tonic-gate } 1485*7c478bd9Sstevel@tonic-gate 1486*7c478bd9Sstevel@tonic-gate int 1487*7c478bd9Sstevel@tonic-gate sbd_set_err_in_hdl(sbd_handle_t *hp, sbderror_t *ep) 1488*7c478bd9Sstevel@tonic-gate { 1489*7c478bd9Sstevel@tonic-gate sbderror_t *hep = SBD_HD2ERR(hp); 1490*7c478bd9Sstevel@tonic-gate 1491*7c478bd9Sstevel@tonic-gate /* 1492*7c478bd9Sstevel@tonic-gate * If there is an error logged already, don't rewrite it 1493*7c478bd9Sstevel@tonic-gate */ 1494*7c478bd9Sstevel@tonic-gate if (SBD_GET_ERR(hep) || SBD_GET_ERRNO(hep)) { 1495*7c478bd9Sstevel@tonic-gate return (0); 1496*7c478bd9Sstevel@tonic-gate } 1497*7c478bd9Sstevel@tonic-gate 1498*7c478bd9Sstevel@tonic-gate if (SBD_GET_ERR(ep) || SBD_GET_ERRNO(ep)) { 1499*7c478bd9Sstevel@tonic-gate SBD_SET_ERR(hep, SBD_GET_ERR(ep)); 1500*7c478bd9Sstevel@tonic-gate SBD_SET_ERRNO(hep, SBD_GET_ERRNO(ep)); 1501*7c478bd9Sstevel@tonic-gate SBD_SET_ERRSTR(hep, SBD_GET_ERRSTR(ep)); 1502*7c478bd9Sstevel@tonic-gate return (0); 1503*7c478bd9Sstevel@tonic-gate } 1504*7c478bd9Sstevel@tonic-gate 1505*7c478bd9Sstevel@tonic-gate return (-1); 1506*7c478bd9Sstevel@tonic-gate } 1507*7c478bd9Sstevel@tonic-gate 1508*7c478bd9Sstevel@tonic-gate static void 1509*7c478bd9Sstevel@tonic-gate sbd_release_handle(sbd_handle_t *hp) 1510*7c478bd9Sstevel@tonic-gate { 1511*7c478bd9Sstevel@tonic-gate sbd_priv_handle_t *shp, **shpp; 1512*7c478bd9Sstevel@tonic-gate sbd_board_t *sbp; 1513*7c478bd9Sstevel@tonic-gate static fn_t f = "sbd_release_handle"; 1514*7c478bd9Sstevel@tonic-gate 1515*7c478bd9Sstevel@tonic-gate if (hp == NULL) 1516*7c478bd9Sstevel@tonic-gate return; 1517*7c478bd9Sstevel@tonic-gate 1518*7c478bd9Sstevel@tonic-gate sbp = SBDH2BD(hp->h_sbd); 1519*7c478bd9Sstevel@tonic-gate 1520*7c478bd9Sstevel@tonic-gate shp = HD2MACHHD(hp); 1521*7c478bd9Sstevel@tonic-gate 1522*7c478bd9Sstevel@tonic-gate mutex_enter(&sbd_handle_list_mutex); 1523*7c478bd9Sstevel@tonic-gate /* 1524*7c478bd9Sstevel@tonic-gate * Locate the handle in the board's reference list. 1525*7c478bd9Sstevel@tonic-gate */ 1526*7c478bd9Sstevel@tonic-gate for (shpp = &sbp->sb_handle; (*shpp) && ((*shpp) != shp); 1527*7c478bd9Sstevel@tonic-gate shpp = &((*shpp)->sh_next)) 1528*7c478bd9Sstevel@tonic-gate /* empty */; 1529*7c478bd9Sstevel@tonic-gate 1530*7c478bd9Sstevel@tonic-gate if (*shpp == NULL) { 1531*7c478bd9Sstevel@tonic-gate cmn_err(CE_PANIC, 1532*7c478bd9Sstevel@tonic-gate "sbd:%s: handle not found in board %d", 1533*7c478bd9Sstevel@tonic-gate f, sbp->sb_num); 1534*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 1535*7c478bd9Sstevel@tonic-gate } else { 1536*7c478bd9Sstevel@tonic-gate *shpp = shp->sh_next; 1537*7c478bd9Sstevel@tonic-gate } 1538*7c478bd9Sstevel@tonic-gate mutex_exit(&sbd_handle_list_mutex); 1539*7c478bd9Sstevel@tonic-gate 1540*7c478bd9Sstevel@tonic-gate if (hp->h_opts.copts != NULL) { 1541*7c478bd9Sstevel@tonic-gate FREESTRUCT(hp->h_opts.copts, char, hp->h_opts.size); 1542*7c478bd9Sstevel@tonic-gate } 1543*7c478bd9Sstevel@tonic-gate 1544*7c478bd9Sstevel@tonic-gate FREESTRUCT(shp, sbd_priv_handle_t, 1); 1545*7c478bd9Sstevel@tonic-gate } 1546*7c478bd9Sstevel@tonic-gate 1547*7c478bd9Sstevel@tonic-gate sbdp_handle_t * 1548*7c478bd9Sstevel@tonic-gate sbd_get_sbdp_handle(sbd_board_t *sbp, sbd_handle_t *hp) 1549*7c478bd9Sstevel@tonic-gate { 1550*7c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 1551*7c478bd9Sstevel@tonic-gate 1552*7c478bd9Sstevel@tonic-gate hdp = kmem_zalloc(sizeof (sbdp_handle_t), KM_SLEEP); 1553*7c478bd9Sstevel@tonic-gate hdp->h_err = kmem_zalloc(sizeof (sbd_error_t), KM_SLEEP); 1554*7c478bd9Sstevel@tonic-gate if (sbp == NULL) { 1555*7c478bd9Sstevel@tonic-gate hdp->h_board = -1; 1556*7c478bd9Sstevel@tonic-gate hdp->h_wnode = -1; 1557*7c478bd9Sstevel@tonic-gate } else { 1558*7c478bd9Sstevel@tonic-gate hdp->h_board = sbp->sb_num; 1559*7c478bd9Sstevel@tonic-gate hdp->h_wnode = sbp->sb_wnode; 1560*7c478bd9Sstevel@tonic-gate } 1561*7c478bd9Sstevel@tonic-gate 1562*7c478bd9Sstevel@tonic-gate if (hp == NULL) { 1563*7c478bd9Sstevel@tonic-gate hdp->h_flags = 0; 1564*7c478bd9Sstevel@tonic-gate hdp->h_opts = NULL; 1565*7c478bd9Sstevel@tonic-gate } else { 1566*7c478bd9Sstevel@tonic-gate hdp->h_flags = SBD_2_SBDP_FLAGS(hp->h_flags); 1567*7c478bd9Sstevel@tonic-gate hdp->h_opts = &hp->h_opts; 1568*7c478bd9Sstevel@tonic-gate } 1569*7c478bd9Sstevel@tonic-gate 1570*7c478bd9Sstevel@tonic-gate return (hdp); 1571*7c478bd9Sstevel@tonic-gate } 1572*7c478bd9Sstevel@tonic-gate 1573*7c478bd9Sstevel@tonic-gate void 1574*7c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(sbdp_handle_t *hdp) 1575*7c478bd9Sstevel@tonic-gate { 1576*7c478bd9Sstevel@tonic-gate if (hdp == NULL) 1577*7c478bd9Sstevel@tonic-gate return; 1578*7c478bd9Sstevel@tonic-gate 1579*7c478bd9Sstevel@tonic-gate kmem_free(hdp->h_err, sizeof (sbd_error_t)); 1580*7c478bd9Sstevel@tonic-gate kmem_free(hdp, sizeof (sbdp_handle_t)); 1581*7c478bd9Sstevel@tonic-gate } 1582*7c478bd9Sstevel@tonic-gate 1583*7c478bd9Sstevel@tonic-gate void 1584*7c478bd9Sstevel@tonic-gate sbd_reset_error_sbdph(sbdp_handle_t *hdp) 1585*7c478bd9Sstevel@tonic-gate { 1586*7c478bd9Sstevel@tonic-gate if ((hdp != NULL) && (hdp->h_err != NULL)) { 1587*7c478bd9Sstevel@tonic-gate bzero(hdp->h_err, sizeof (sbd_error_t)); 1588*7c478bd9Sstevel@tonic-gate } 1589*7c478bd9Sstevel@tonic-gate } 1590*7c478bd9Sstevel@tonic-gate 1591*7c478bd9Sstevel@tonic-gate static int 1592*7c478bd9Sstevel@tonic-gate sbd_copyin_ioarg(sbd_handle_t *hp, int mode, int cmd, sbd_cmd_t *cmdp, 1593*7c478bd9Sstevel@tonic-gate sbd_ioctl_arg_t *iap) 1594*7c478bd9Sstevel@tonic-gate { 1595*7c478bd9Sstevel@tonic-gate static fn_t f = "sbd_copyin_ioarg"; 1596*7c478bd9Sstevel@tonic-gate 1597*7c478bd9Sstevel@tonic-gate if (iap == NULL) 1598*7c478bd9Sstevel@tonic-gate return (EINVAL); 1599*7c478bd9Sstevel@tonic-gate 1600*7c478bd9Sstevel@tonic-gate bzero((caddr_t)cmdp, sizeof (sbd_cmd_t)); 1601*7c478bd9Sstevel@tonic-gate 1602*7c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 1603*7c478bd9Sstevel@tonic-gate if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) { 1604*7c478bd9Sstevel@tonic-gate sbd_cmd32_t scmd32; 1605*7c478bd9Sstevel@tonic-gate 1606*7c478bd9Sstevel@tonic-gate bzero((caddr_t)&scmd32, sizeof (sbd_cmd32_t)); 1607*7c478bd9Sstevel@tonic-gate 1608*7c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)iap, (void *)&scmd32, 1609*7c478bd9Sstevel@tonic-gate sizeof (sbd_cmd32_t), mode)) { 1610*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 1611*7c478bd9Sstevel@tonic-gate "sbd:%s: (32bit) failed to copyin " 1612*7c478bd9Sstevel@tonic-gate "sbdcmd-struct", f); 1613*7c478bd9Sstevel@tonic-gate return (EFAULT); 1614*7c478bd9Sstevel@tonic-gate } 1615*7c478bd9Sstevel@tonic-gate cmdp->cmd_cm.c_id.c_type = scmd32.cmd_cm.c_id.c_type; 1616*7c478bd9Sstevel@tonic-gate cmdp->cmd_cm.c_id.c_unit = scmd32.cmd_cm.c_id.c_unit; 1617*7c478bd9Sstevel@tonic-gate bcopy(&scmd32.cmd_cm.c_id.c_name[0], 1618*7c478bd9Sstevel@tonic-gate &cmdp->cmd_cm.c_id.c_name[0], OBP_MAXPROPNAME); 1619*7c478bd9Sstevel@tonic-gate cmdp->cmd_cm.c_flags = scmd32.cmd_cm.c_flags; 1620*7c478bd9Sstevel@tonic-gate cmdp->cmd_cm.c_len = scmd32.cmd_cm.c_len; 1621*7c478bd9Sstevel@tonic-gate cmdp->cmd_cm.c_opts = (caddr_t)scmd32.cmd_cm.c_opts; 1622*7c478bd9Sstevel@tonic-gate 1623*7c478bd9Sstevel@tonic-gate if (cmd == SBD_CMD_PASSTHRU) { 1624*7c478bd9Sstevel@tonic-gate PR_BYP("passthru copyin: iap=%p, sz=%d", iap, 1625*7c478bd9Sstevel@tonic-gate sizeof (sbd_cmd32_t)); 1626*7c478bd9Sstevel@tonic-gate PR_BYP("passthru copyin: c_opts=%p, c_len=%d", 1627*7c478bd9Sstevel@tonic-gate scmd32.cmd_cm.c_opts, 1628*7c478bd9Sstevel@tonic-gate scmd32.cmd_cm.c_len); 1629*7c478bd9Sstevel@tonic-gate } 1630*7c478bd9Sstevel@tonic-gate 1631*7c478bd9Sstevel@tonic-gate switch (cmd) { 1632*7c478bd9Sstevel@tonic-gate case SBD_CMD_STATUS: 1633*7c478bd9Sstevel@tonic-gate cmdp->cmd_stat.s_nbytes = scmd32.cmd_stat.s_nbytes; 1634*7c478bd9Sstevel@tonic-gate cmdp->cmd_stat.s_statp = 1635*7c478bd9Sstevel@tonic-gate (caddr_t)scmd32.cmd_stat.s_statp; 1636*7c478bd9Sstevel@tonic-gate break; 1637*7c478bd9Sstevel@tonic-gate default: 1638*7c478bd9Sstevel@tonic-gate break; 1639*7c478bd9Sstevel@tonic-gate 1640*7c478bd9Sstevel@tonic-gate } 1641*7c478bd9Sstevel@tonic-gate } else 1642*7c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */ 1643*7c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)iap, (void *)cmdp, 1644*7c478bd9Sstevel@tonic-gate sizeof (sbd_cmd_t), mode) != 0) { 1645*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 1646*7c478bd9Sstevel@tonic-gate "sbd:%s: failed to copyin sbd cmd_t struct", f); 1647*7c478bd9Sstevel@tonic-gate return (EFAULT); 1648*7c478bd9Sstevel@tonic-gate } 1649*7c478bd9Sstevel@tonic-gate /* 1650*7c478bd9Sstevel@tonic-gate * A user may set platform specific options so we need to 1651*7c478bd9Sstevel@tonic-gate * copy them in 1652*7c478bd9Sstevel@tonic-gate */ 1653*7c478bd9Sstevel@tonic-gate if ((cmd != SBD_CMD_STATUS) && ((hp->h_opts.size = cmdp->cmd_cm.c_len) 1654*7c478bd9Sstevel@tonic-gate > 0)) { 1655*7c478bd9Sstevel@tonic-gate hp->h_opts.size += 1; /* For null termination of string. */ 1656*7c478bd9Sstevel@tonic-gate hp->h_opts.copts = GETSTRUCT(char, hp->h_opts.size); 1657*7c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)cmdp->cmd_cm.c_opts, 1658*7c478bd9Sstevel@tonic-gate (void *)hp->h_opts.copts, 1659*7c478bd9Sstevel@tonic-gate cmdp->cmd_cm.c_len, hp->h_mode) != 0) { 1660*7c478bd9Sstevel@tonic-gate /* copts is freed in sbd_release_handle(). */ 1661*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 1662*7c478bd9Sstevel@tonic-gate "sbd:%s: failed to copyin options", f); 1663*7c478bd9Sstevel@tonic-gate return (EFAULT); 1664*7c478bd9Sstevel@tonic-gate } 1665*7c478bd9Sstevel@tonic-gate } 1666*7c478bd9Sstevel@tonic-gate 1667*7c478bd9Sstevel@tonic-gate return (0); 1668*7c478bd9Sstevel@tonic-gate } 1669*7c478bd9Sstevel@tonic-gate 1670*7c478bd9Sstevel@tonic-gate static int 1671*7c478bd9Sstevel@tonic-gate sbd_copyout_ioarg(int mode, int cmd, sbd_cmd_t *scp, sbd_ioctl_arg_t *iap) 1672*7c478bd9Sstevel@tonic-gate { 1673*7c478bd9Sstevel@tonic-gate static fn_t f = "sbd_copyout_ioarg"; 1674*7c478bd9Sstevel@tonic-gate 1675*7c478bd9Sstevel@tonic-gate if ((iap == NULL) || (scp == NULL)) 1676*7c478bd9Sstevel@tonic-gate return (EINVAL); 1677*7c478bd9Sstevel@tonic-gate 1678*7c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 1679*7c478bd9Sstevel@tonic-gate if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) { 1680*7c478bd9Sstevel@tonic-gate sbd_cmd32_t scmd32; 1681*7c478bd9Sstevel@tonic-gate 1682*7c478bd9Sstevel@tonic-gate scmd32.cmd_cm.c_id.c_type = scp->cmd_cm.c_id.c_type; 1683*7c478bd9Sstevel@tonic-gate scmd32.cmd_cm.c_id.c_unit = scp->cmd_cm.c_id.c_unit; 1684*7c478bd9Sstevel@tonic-gate bcopy(scp->cmd_cm.c_id.c_name, 1685*7c478bd9Sstevel@tonic-gate scmd32.cmd_cm.c_id.c_name, OBP_MAXPROPNAME); 1686*7c478bd9Sstevel@tonic-gate 1687*7c478bd9Sstevel@tonic-gate scmd32.cmd_cm.c_flags = scp->cmd_cm.c_flags; 1688*7c478bd9Sstevel@tonic-gate 1689*7c478bd9Sstevel@tonic-gate switch (cmd) { 1690*7c478bd9Sstevel@tonic-gate case SBD_CMD_GETNCM: 1691*7c478bd9Sstevel@tonic-gate scmd32.cmd_getncm.g_ncm = scp->cmd_getncm.g_ncm; 1692*7c478bd9Sstevel@tonic-gate break; 1693*7c478bd9Sstevel@tonic-gate default: 1694*7c478bd9Sstevel@tonic-gate break; 1695*7c478bd9Sstevel@tonic-gate } 1696*7c478bd9Sstevel@tonic-gate 1697*7c478bd9Sstevel@tonic-gate if (ddi_copyout((void *)&scmd32, (void *)iap, 1698*7c478bd9Sstevel@tonic-gate sizeof (sbd_cmd32_t), mode)) { 1699*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 1700*7c478bd9Sstevel@tonic-gate "sbd:%s: (32bit) failed to copyout " 1701*7c478bd9Sstevel@tonic-gate "sbdcmd struct", f); 1702*7c478bd9Sstevel@tonic-gate return (EFAULT); 1703*7c478bd9Sstevel@tonic-gate } 1704*7c478bd9Sstevel@tonic-gate } else 1705*7c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */ 1706*7c478bd9Sstevel@tonic-gate if (ddi_copyout((void *)scp, (void *)iap, 1707*7c478bd9Sstevel@tonic-gate sizeof (sbd_cmd_t), mode) != 0) { 1708*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 1709*7c478bd9Sstevel@tonic-gate "sbd:%s: failed to copyout sbdcmd struct", f); 1710*7c478bd9Sstevel@tonic-gate return (EFAULT); 1711*7c478bd9Sstevel@tonic-gate } 1712*7c478bd9Sstevel@tonic-gate 1713*7c478bd9Sstevel@tonic-gate return (0); 1714*7c478bd9Sstevel@tonic-gate } 1715*7c478bd9Sstevel@tonic-gate 1716*7c478bd9Sstevel@tonic-gate static int 1717*7c478bd9Sstevel@tonic-gate sbd_copyout_errs(int mode, sbd_ioctl_arg_t *iap, void *arg) 1718*7c478bd9Sstevel@tonic-gate { 1719*7c478bd9Sstevel@tonic-gate static fn_t f = "sbd_copyout_errs"; 1720*7c478bd9Sstevel@tonic-gate sbd_ioctl_arg_t *uap; 1721*7c478bd9Sstevel@tonic-gate 1722*7c478bd9Sstevel@tonic-gate uap = (sbd_ioctl_arg_t *)arg; 1723*7c478bd9Sstevel@tonic-gate 1724*7c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 1725*7c478bd9Sstevel@tonic-gate if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) { 1726*7c478bd9Sstevel@tonic-gate sbd_error32_t err32; 1727*7c478bd9Sstevel@tonic-gate sbd_ioctl_arg32_t *uap32; 1728*7c478bd9Sstevel@tonic-gate 1729*7c478bd9Sstevel@tonic-gate uap32 = (sbd_ioctl_arg32_t *)arg; 1730*7c478bd9Sstevel@tonic-gate 1731*7c478bd9Sstevel@tonic-gate err32.e_code = iap->ie_code; 1732*7c478bd9Sstevel@tonic-gate (void) strcpy(err32.e_rsc, iap->ie_rsc); 1733*7c478bd9Sstevel@tonic-gate 1734*7c478bd9Sstevel@tonic-gate if (ddi_copyout((void *)&err32, (void *)&uap32->i_err, 1735*7c478bd9Sstevel@tonic-gate sizeof (sbd_error32_t), mode)) { 1736*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 1737*7c478bd9Sstevel@tonic-gate "sbd:%s: failed to copyout ioctl32 errs", 1738*7c478bd9Sstevel@tonic-gate f); 1739*7c478bd9Sstevel@tonic-gate return (EFAULT); 1740*7c478bd9Sstevel@tonic-gate } 1741*7c478bd9Sstevel@tonic-gate } else 1742*7c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */ 1743*7c478bd9Sstevel@tonic-gate if (ddi_copyout((void *)&iap->i_err, (void *)&uap->i_err, 1744*7c478bd9Sstevel@tonic-gate sizeof (sbd_error_t), mode) != 0) { 1745*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 1746*7c478bd9Sstevel@tonic-gate "sbd:%s: failed to copyout ioctl errs", f); 1747*7c478bd9Sstevel@tonic-gate return (EFAULT); 1748*7c478bd9Sstevel@tonic-gate } 1749*7c478bd9Sstevel@tonic-gate 1750*7c478bd9Sstevel@tonic-gate return (0); 1751*7c478bd9Sstevel@tonic-gate } 1752*7c478bd9Sstevel@tonic-gate 1753*7c478bd9Sstevel@tonic-gate /* 1754*7c478bd9Sstevel@tonic-gate * State transition policy is that if at least one 1755*7c478bd9Sstevel@tonic-gate * device cannot make the transition, then none of 1756*7c478bd9Sstevel@tonic-gate * the requested devices are allowed to transition. 1757*7c478bd9Sstevel@tonic-gate * 1758*7c478bd9Sstevel@tonic-gate * Returns the state that is in error, if any. 1759*7c478bd9Sstevel@tonic-gate */ 1760*7c478bd9Sstevel@tonic-gate static int 1761*7c478bd9Sstevel@tonic-gate sbd_check_transition(sbd_board_t *sbp, sbd_devset_t *devsetp, 1762*7c478bd9Sstevel@tonic-gate struct sbd_state_trans *transp) 1763*7c478bd9Sstevel@tonic-gate { 1764*7c478bd9Sstevel@tonic-gate int s, ut; 1765*7c478bd9Sstevel@tonic-gate int state_err = 0; 1766*7c478bd9Sstevel@tonic-gate sbd_devset_t devset; 1767*7c478bd9Sstevel@tonic-gate static fn_t f = "sbd_check_transition"; 1768*7c478bd9Sstevel@tonic-gate 1769*7c478bd9Sstevel@tonic-gate devset = *devsetp; 1770*7c478bd9Sstevel@tonic-gate 1771*7c478bd9Sstevel@tonic-gate if (!devset) { 1772*7c478bd9Sstevel@tonic-gate /* 1773*7c478bd9Sstevel@tonic-gate * Transition does not deal with any components. 1774*7c478bd9Sstevel@tonic-gate * This is the case for addboard/deleteboard. 1775*7c478bd9Sstevel@tonic-gate */ 1776*7c478bd9Sstevel@tonic-gate PR_ALL("%s: no devs: requested devset = 0x%x," 1777*7c478bd9Sstevel@tonic-gate " final devset = 0x%x\n", 1778*7c478bd9Sstevel@tonic-gate f, (uint_t)*devsetp, (uint_t)devset); 1779*7c478bd9Sstevel@tonic-gate 1780*7c478bd9Sstevel@tonic-gate return (0); 1781*7c478bd9Sstevel@tonic-gate } 1782*7c478bd9Sstevel@tonic-gate 1783*7c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devset, SBD_COMP_MEM, DEVSET_ANYUNIT)) { 1784*7c478bd9Sstevel@tonic-gate for (ut = 0; ut < MAX_MEM_UNITS_PER_BOARD; ut++) { 1785*7c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devset, SBD_COMP_MEM, ut) == 0) 1786*7c478bd9Sstevel@tonic-gate continue; 1787*7c478bd9Sstevel@tonic-gate s = (int)SBD_DEVICE_STATE(sbp, SBD_COMP_MEM, ut); 1788*7c478bd9Sstevel@tonic-gate if (transp->x_op[s].x_rv) { 1789*7c478bd9Sstevel@tonic-gate if (!state_err) 1790*7c478bd9Sstevel@tonic-gate state_err = s; 1791*7c478bd9Sstevel@tonic-gate DEVSET_DEL(devset, SBD_COMP_MEM, ut); 1792*7c478bd9Sstevel@tonic-gate } 1793*7c478bd9Sstevel@tonic-gate } 1794*7c478bd9Sstevel@tonic-gate } 1795*7c478bd9Sstevel@tonic-gate 1796*7c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devset, SBD_COMP_CPU, DEVSET_ANYUNIT)) { 1797*7c478bd9Sstevel@tonic-gate for (ut = 0; ut < MAX_CPU_UNITS_PER_BOARD; ut++) { 1798*7c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devset, SBD_COMP_CPU, ut) == 0) 1799*7c478bd9Sstevel@tonic-gate continue; 1800*7c478bd9Sstevel@tonic-gate s = (int)SBD_DEVICE_STATE(sbp, SBD_COMP_CPU, ut); 1801*7c478bd9Sstevel@tonic-gate if (transp->x_op[s].x_rv) { 1802*7c478bd9Sstevel@tonic-gate if (!state_err) 1803*7c478bd9Sstevel@tonic-gate state_err = s; 1804*7c478bd9Sstevel@tonic-gate DEVSET_DEL(devset, SBD_COMP_CPU, ut); 1805*7c478bd9Sstevel@tonic-gate } 1806*7c478bd9Sstevel@tonic-gate } 1807*7c478bd9Sstevel@tonic-gate } 1808*7c478bd9Sstevel@tonic-gate 1809*7c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devset, SBD_COMP_IO, DEVSET_ANYUNIT)) { 1810*7c478bd9Sstevel@tonic-gate for (ut = 0; ut < MAX_IO_UNITS_PER_BOARD; ut++) { 1811*7c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devset, SBD_COMP_IO, ut) == 0) 1812*7c478bd9Sstevel@tonic-gate continue; 1813*7c478bd9Sstevel@tonic-gate s = (int)SBD_DEVICE_STATE(sbp, SBD_COMP_IO, ut); 1814*7c478bd9Sstevel@tonic-gate if (transp->x_op[s].x_rv) { 1815*7c478bd9Sstevel@tonic-gate if (!state_err) 1816*7c478bd9Sstevel@tonic-gate state_err = s; 1817*7c478bd9Sstevel@tonic-gate DEVSET_DEL(devset, SBD_COMP_IO, ut); 1818*7c478bd9Sstevel@tonic-gate } 1819*7c478bd9Sstevel@tonic-gate } 1820*7c478bd9Sstevel@tonic-gate } 1821*7c478bd9Sstevel@tonic-gate 1822*7c478bd9Sstevel@tonic-gate PR_ALL("%s: requested devset = 0x%x, final devset = 0x%x\n", 1823*7c478bd9Sstevel@tonic-gate f, (uint_t)*devsetp, (uint_t)devset); 1824*7c478bd9Sstevel@tonic-gate 1825*7c478bd9Sstevel@tonic-gate *devsetp = devset; 1826*7c478bd9Sstevel@tonic-gate /* 1827*7c478bd9Sstevel@tonic-gate * If there are some remaining components for which 1828*7c478bd9Sstevel@tonic-gate * this state transition is valid, then allow them 1829*7c478bd9Sstevel@tonic-gate * through, otherwise if none are left then return 1830*7c478bd9Sstevel@tonic-gate * the state error. 1831*7c478bd9Sstevel@tonic-gate */ 1832*7c478bd9Sstevel@tonic-gate return (devset ? 0 : state_err); 1833*7c478bd9Sstevel@tonic-gate } 1834*7c478bd9Sstevel@tonic-gate 1835*7c478bd9Sstevel@tonic-gate /* 1836*7c478bd9Sstevel@tonic-gate * pre-op entry point must SET_ERRNO(), if needed. 1837*7c478bd9Sstevel@tonic-gate * Return value of non-zero indicates failure. 1838*7c478bd9Sstevel@tonic-gate */ 1839*7c478bd9Sstevel@tonic-gate static int 1840*7c478bd9Sstevel@tonic-gate sbd_pre_op(sbd_handle_t *hp) 1841*7c478bd9Sstevel@tonic-gate { 1842*7c478bd9Sstevel@tonic-gate int rv = 0, t; 1843*7c478bd9Sstevel@tonic-gate int cmd, serr = 0; 1844*7c478bd9Sstevel@tonic-gate sbd_devset_t devset; 1845*7c478bd9Sstevel@tonic-gate sbd_board_t *sbp = SBDH2BD(hp->h_sbd); 1846*7c478bd9Sstevel@tonic-gate sbd_priv_handle_t *shp = HD2MACHHD(hp); 1847*7c478bd9Sstevel@tonic-gate sbderror_t *ep = SBD_HD2ERR(hp); 1848*7c478bd9Sstevel@tonic-gate sbd_cmd_t *cmdp; 1849*7c478bd9Sstevel@tonic-gate static fn_t f = "sbd_pre_op"; 1850*7c478bd9Sstevel@tonic-gate 1851*7c478bd9Sstevel@tonic-gate cmd = hp->h_cmd; 1852*7c478bd9Sstevel@tonic-gate devset = shp->sh_devset; 1853*7c478bd9Sstevel@tonic-gate 1854*7c478bd9Sstevel@tonic-gate switch (cmd) { 1855*7c478bd9Sstevel@tonic-gate case SBD_CMD_CONNECT: 1856*7c478bd9Sstevel@tonic-gate case SBD_CMD_DISCONNECT: 1857*7c478bd9Sstevel@tonic-gate case SBD_CMD_UNCONFIGURE: 1858*7c478bd9Sstevel@tonic-gate case SBD_CMD_CONFIGURE: 1859*7c478bd9Sstevel@tonic-gate case SBD_CMD_ASSIGN: 1860*7c478bd9Sstevel@tonic-gate case SBD_CMD_UNASSIGN: 1861*7c478bd9Sstevel@tonic-gate case SBD_CMD_POWERON: 1862*7c478bd9Sstevel@tonic-gate case SBD_CMD_POWEROFF: 1863*7c478bd9Sstevel@tonic-gate case SBD_CMD_TEST: 1864*7c478bd9Sstevel@tonic-gate /* ioctls allowed if caller has write permission */ 1865*7c478bd9Sstevel@tonic-gate if (!(hp->h_mode & FWRITE)) { 1866*7c478bd9Sstevel@tonic-gate SBD_SET_ERRNO(ep, EPERM); 1867*7c478bd9Sstevel@tonic-gate return (-1); 1868*7c478bd9Sstevel@tonic-gate } 1869*7c478bd9Sstevel@tonic-gate 1870*7c478bd9Sstevel@tonic-gate default: 1871*7c478bd9Sstevel@tonic-gate break; 1872*7c478bd9Sstevel@tonic-gate } 1873*7c478bd9Sstevel@tonic-gate 1874*7c478bd9Sstevel@tonic-gate hp->h_iap = GETSTRUCT(sbd_ioctl_arg_t, 1); 1875*7c478bd9Sstevel@tonic-gate rv = sbd_copyin_ioarg(hp, hp->h_mode, cmd, 1876*7c478bd9Sstevel@tonic-gate (sbd_cmd_t *)hp->h_iap, shp->sh_arg); 1877*7c478bd9Sstevel@tonic-gate if (rv) { 1878*7c478bd9Sstevel@tonic-gate SBD_SET_ERRNO(ep, rv); 1879*7c478bd9Sstevel@tonic-gate FREESTRUCT(hp->h_iap, sbd_ioctl_arg_t, 1); 1880*7c478bd9Sstevel@tonic-gate hp->h_iap = NULL; 1881*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "%s: copyin fail", f); 1882*7c478bd9Sstevel@tonic-gate return (-1); 1883*7c478bd9Sstevel@tonic-gate } else { 1884*7c478bd9Sstevel@tonic-gate cmdp = (sbd_cmd_t *)hp->h_iap; 1885*7c478bd9Sstevel@tonic-gate if (cmdp->cmd_cm.c_id.c_name[0] != '\0') { 1886*7c478bd9Sstevel@tonic-gate 1887*7c478bd9Sstevel@tonic-gate cmdp->cmd_cm.c_id.c_type = SBD_COMP(sbd_name_to_idx( 1888*7c478bd9Sstevel@tonic-gate cmdp->cmd_cm.c_id.c_name)); 1889*7c478bd9Sstevel@tonic-gate if (cmdp->cmd_cm.c_id.c_type == SBD_COMP_MEM) { 1890*7c478bd9Sstevel@tonic-gate if (cmdp->cmd_cm.c_id.c_unit == -1) 1891*7c478bd9Sstevel@tonic-gate cmdp->cmd_cm.c_id.c_unit = 0; 1892*7c478bd9Sstevel@tonic-gate } 1893*7c478bd9Sstevel@tonic-gate } 1894*7c478bd9Sstevel@tonic-gate devset = shp->sh_orig_devset = shp->sh_devset = 1895*7c478bd9Sstevel@tonic-gate sbd_dev2devset(&cmdp->cmd_cm.c_id); 1896*7c478bd9Sstevel@tonic-gate if (devset == 0) { 1897*7c478bd9Sstevel@tonic-gate SBD_SET_ERRNO(ep, EINVAL); 1898*7c478bd9Sstevel@tonic-gate FREESTRUCT(hp->h_iap, sbd_ioctl_arg_t, 1); 1899*7c478bd9Sstevel@tonic-gate hp->h_iap = NULL; 1900*7c478bd9Sstevel@tonic-gate return (-1); 1901*7c478bd9Sstevel@tonic-gate } 1902*7c478bd9Sstevel@tonic-gate } 1903*7c478bd9Sstevel@tonic-gate 1904*7c478bd9Sstevel@tonic-gate /* 1905*7c478bd9Sstevel@tonic-gate * Always turn on these bits ala Sunfire DR. 1906*7c478bd9Sstevel@tonic-gate */ 1907*7c478bd9Sstevel@tonic-gate hp->h_flags |= SBD_FLAG_DEVI_FORCE; 1908*7c478bd9Sstevel@tonic-gate 1909*7c478bd9Sstevel@tonic-gate if (cmdp->cmd_cm.c_flags & SBD_FLAG_FORCE) 1910*7c478bd9Sstevel@tonic-gate hp->h_flags |= SBD_IOCTL_FLAG_FORCE; 1911*7c478bd9Sstevel@tonic-gate 1912*7c478bd9Sstevel@tonic-gate /* 1913*7c478bd9Sstevel@tonic-gate * Check for valid state transitions. 1914*7c478bd9Sstevel@tonic-gate */ 1915*7c478bd9Sstevel@tonic-gate if (!serr && ((t = CMD2INDEX(cmd)) != -1)) { 1916*7c478bd9Sstevel@tonic-gate struct sbd_state_trans *transp; 1917*7c478bd9Sstevel@tonic-gate int state_err; 1918*7c478bd9Sstevel@tonic-gate 1919*7c478bd9Sstevel@tonic-gate transp = &sbd_state_transition[t]; 1920*7c478bd9Sstevel@tonic-gate ASSERT(transp->x_cmd == cmd); 1921*7c478bd9Sstevel@tonic-gate 1922*7c478bd9Sstevel@tonic-gate state_err = sbd_check_transition(sbp, &devset, transp); 1923*7c478bd9Sstevel@tonic-gate 1924*7c478bd9Sstevel@tonic-gate if (state_err < 0) { 1925*7c478bd9Sstevel@tonic-gate /* 1926*7c478bd9Sstevel@tonic-gate * Invalidate device. 1927*7c478bd9Sstevel@tonic-gate */ 1928*7c478bd9Sstevel@tonic-gate SBD_SET_ERRNO(ep, ENOTTY); 1929*7c478bd9Sstevel@tonic-gate serr = -1; 1930*7c478bd9Sstevel@tonic-gate PR_ALL("%s: invalid devset (0x%x)\n", 1931*7c478bd9Sstevel@tonic-gate f, (uint_t)devset); 1932*7c478bd9Sstevel@tonic-gate } else if (state_err != 0) { 1933*7c478bd9Sstevel@tonic-gate /* 1934*7c478bd9Sstevel@tonic-gate * State transition is not a valid one. 1935*7c478bd9Sstevel@tonic-gate */ 1936*7c478bd9Sstevel@tonic-gate SBD_SET_ERRNO(ep, transp->x_op[state_err].x_err); 1937*7c478bd9Sstevel@tonic-gate serr = transp->x_op[state_err].x_rv; 1938*7c478bd9Sstevel@tonic-gate PR_ALL("%s: invalid state %s(%d) for cmd %s(%d)\n", 1939*7c478bd9Sstevel@tonic-gate f, sbd_state_str[state_err], state_err, 1940*7c478bd9Sstevel@tonic-gate SBD_CMD_STR(cmd), cmd); 1941*7c478bd9Sstevel@tonic-gate } 1942*7c478bd9Sstevel@tonic-gate if (serr && SBD_GET_ERRNO(ep) != 0) { 1943*7c478bd9Sstevel@tonic-gate /* 1944*7c478bd9Sstevel@tonic-gate * A state transition error occurred. 1945*7c478bd9Sstevel@tonic-gate */ 1946*7c478bd9Sstevel@tonic-gate if (serr < 0) { 1947*7c478bd9Sstevel@tonic-gate SBD_SET_ERR(ep, ESBD_INVAL); 1948*7c478bd9Sstevel@tonic-gate } else { 1949*7c478bd9Sstevel@tonic-gate SBD_SET_ERR(ep, ESBD_STATE); 1950*7c478bd9Sstevel@tonic-gate } 1951*7c478bd9Sstevel@tonic-gate PR_ALL("%s: invalid state transition\n", f); 1952*7c478bd9Sstevel@tonic-gate } else { 1953*7c478bd9Sstevel@tonic-gate shp->sh_devset = devset; 1954*7c478bd9Sstevel@tonic-gate } 1955*7c478bd9Sstevel@tonic-gate } 1956*7c478bd9Sstevel@tonic-gate 1957*7c478bd9Sstevel@tonic-gate if (serr && !rv && hp->h_iap) { 1958*7c478bd9Sstevel@tonic-gate 1959*7c478bd9Sstevel@tonic-gate /* 1960*7c478bd9Sstevel@tonic-gate * There was a state error. We successfully copied 1961*7c478bd9Sstevel@tonic-gate * in the ioctl argument, so let's fill in the 1962*7c478bd9Sstevel@tonic-gate * error and copy it back out. 1963*7c478bd9Sstevel@tonic-gate */ 1964*7c478bd9Sstevel@tonic-gate 1965*7c478bd9Sstevel@tonic-gate if (SBD_GET_ERR(ep) && SBD_GET_ERRNO(ep) == 0) 1966*7c478bd9Sstevel@tonic-gate SBD_SET_ERRNO(ep, EIO); 1967*7c478bd9Sstevel@tonic-gate 1968*7c478bd9Sstevel@tonic-gate SBD_SET_IOCTL_ERR(&hp->h_iap->i_err, 1969*7c478bd9Sstevel@tonic-gate ep->e_code, 1970*7c478bd9Sstevel@tonic-gate ep->e_rsc); 1971*7c478bd9Sstevel@tonic-gate (void) sbd_copyout_errs(hp->h_mode, hp->h_iap, shp->sh_arg); 1972*7c478bd9Sstevel@tonic-gate FREESTRUCT(hp->h_iap, sbd_ioctl_arg_t, 1); 1973*7c478bd9Sstevel@tonic-gate hp->h_iap = NULL; 1974*7c478bd9Sstevel@tonic-gate rv = -1; 1975*7c478bd9Sstevel@tonic-gate } 1976*7c478bd9Sstevel@tonic-gate 1977*7c478bd9Sstevel@tonic-gate return (rv); 1978*7c478bd9Sstevel@tonic-gate } 1979*7c478bd9Sstevel@tonic-gate 1980*7c478bd9Sstevel@tonic-gate static void 1981*7c478bd9Sstevel@tonic-gate sbd_post_op(sbd_handle_t *hp) 1982*7c478bd9Sstevel@tonic-gate { 1983*7c478bd9Sstevel@tonic-gate int cmd; 1984*7c478bd9Sstevel@tonic-gate sbderror_t *ep = SBD_HD2ERR(hp); 1985*7c478bd9Sstevel@tonic-gate sbd_priv_handle_t *shp = HD2MACHHD(hp); 1986*7c478bd9Sstevel@tonic-gate sbd_board_t *sbp = SBDH2BD(hp->h_sbd); 1987*7c478bd9Sstevel@tonic-gate 1988*7c478bd9Sstevel@tonic-gate cmd = hp->h_cmd; 1989*7c478bd9Sstevel@tonic-gate 1990*7c478bd9Sstevel@tonic-gate switch (cmd) { 1991*7c478bd9Sstevel@tonic-gate case SBD_CMD_CONFIGURE: 1992*7c478bd9Sstevel@tonic-gate case SBD_CMD_UNCONFIGURE: 1993*7c478bd9Sstevel@tonic-gate case SBD_CMD_CONNECT: 1994*7c478bd9Sstevel@tonic-gate case SBD_CMD_DISCONNECT: 1995*7c478bd9Sstevel@tonic-gate sbp->sb_time = gethrestime_sec(); 1996*7c478bd9Sstevel@tonic-gate break; 1997*7c478bd9Sstevel@tonic-gate 1998*7c478bd9Sstevel@tonic-gate default: 1999*7c478bd9Sstevel@tonic-gate break; 2000*7c478bd9Sstevel@tonic-gate } 2001*7c478bd9Sstevel@tonic-gate 2002*7c478bd9Sstevel@tonic-gate if (SBD_GET_ERR(ep) && SBD_GET_ERRNO(ep) == 0) { 2003*7c478bd9Sstevel@tonic-gate SBD_SET_ERRNO(ep, EIO); 2004*7c478bd9Sstevel@tonic-gate } 2005*7c478bd9Sstevel@tonic-gate 2006*7c478bd9Sstevel@tonic-gate if (shp->sh_arg != NULL) { 2007*7c478bd9Sstevel@tonic-gate 2008*7c478bd9Sstevel@tonic-gate if (SBD_GET_ERR(ep) != ESBD_NOERROR) { 2009*7c478bd9Sstevel@tonic-gate 2010*7c478bd9Sstevel@tonic-gate SBD_SET_IOCTL_ERR(&hp->h_iap->i_err, 2011*7c478bd9Sstevel@tonic-gate ep->e_code, 2012*7c478bd9Sstevel@tonic-gate ep->e_rsc); 2013*7c478bd9Sstevel@tonic-gate 2014*7c478bd9Sstevel@tonic-gate (void) sbd_copyout_errs(hp->h_mode, hp->h_iap, 2015*7c478bd9Sstevel@tonic-gate shp->sh_arg); 2016*7c478bd9Sstevel@tonic-gate } 2017*7c478bd9Sstevel@tonic-gate 2018*7c478bd9Sstevel@tonic-gate if (hp->h_iap != NULL) { 2019*7c478bd9Sstevel@tonic-gate FREESTRUCT(hp->h_iap, sbd_ioctl_arg_t, 1); 2020*7c478bd9Sstevel@tonic-gate hp->h_iap = NULL; 2021*7c478bd9Sstevel@tonic-gate } 2022*7c478bd9Sstevel@tonic-gate } 2023*7c478bd9Sstevel@tonic-gate } 2024*7c478bd9Sstevel@tonic-gate 2025*7c478bd9Sstevel@tonic-gate static int 2026*7c478bd9Sstevel@tonic-gate sbd_probe_board(sbd_handle_t *hp) 2027*7c478bd9Sstevel@tonic-gate { 2028*7c478bd9Sstevel@tonic-gate int rv; 2029*7c478bd9Sstevel@tonic-gate sbd_board_t *sbp; 2030*7c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 2031*7c478bd9Sstevel@tonic-gate static fn_t f = "sbd_probe_board"; 2032*7c478bd9Sstevel@tonic-gate 2033*7c478bd9Sstevel@tonic-gate sbp = SBDH2BD(hp->h_sbd); 2034*7c478bd9Sstevel@tonic-gate 2035*7c478bd9Sstevel@tonic-gate ASSERT(sbp != NULL); 2036*7c478bd9Sstevel@tonic-gate PR_ALL("%s for board %d", f, sbp->sb_num); 2037*7c478bd9Sstevel@tonic-gate 2038*7c478bd9Sstevel@tonic-gate 2039*7c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 2040*7c478bd9Sstevel@tonic-gate 2041*7c478bd9Sstevel@tonic-gate if ((rv = sbdp_connect_board(hdp)) != 0) { 2042*7c478bd9Sstevel@tonic-gate sbderror_t *ep = SBD_HD2ERR(hp); 2043*7c478bd9Sstevel@tonic-gate 2044*7c478bd9Sstevel@tonic-gate SBD_GET_PERR(hdp->h_err, ep); 2045*7c478bd9Sstevel@tonic-gate } 2046*7c478bd9Sstevel@tonic-gate 2047*7c478bd9Sstevel@tonic-gate /* 2048*7c478bd9Sstevel@tonic-gate * We need to force a recache after the connect. The cached 2049*7c478bd9Sstevel@tonic-gate * info may be incorrect 2050*7c478bd9Sstevel@tonic-gate */ 2051*7c478bd9Sstevel@tonic-gate mutex_enter(&sbp->sb_flags_mutex); 2052*7c478bd9Sstevel@tonic-gate sbp->sb_flags &= ~SBD_BOARD_STATUS_CACHED; 2053*7c478bd9Sstevel@tonic-gate mutex_exit(&sbp->sb_flags_mutex); 2054*7c478bd9Sstevel@tonic-gate 2055*7c478bd9Sstevel@tonic-gate SBD_INJECT_ERR(SBD_PROBE_BOARD_PSEUDO_ERR, hp->h_err, EIO, 2056*7c478bd9Sstevel@tonic-gate ESGT_PROBE, NULL); 2057*7c478bd9Sstevel@tonic-gate 2058*7c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 2059*7c478bd9Sstevel@tonic-gate 2060*7c478bd9Sstevel@tonic-gate return (rv); 2061*7c478bd9Sstevel@tonic-gate } 2062*7c478bd9Sstevel@tonic-gate 2063*7c478bd9Sstevel@tonic-gate static int 2064*7c478bd9Sstevel@tonic-gate sbd_deprobe_board(sbd_handle_t *hp) 2065*7c478bd9Sstevel@tonic-gate { 2066*7c478bd9Sstevel@tonic-gate int rv; 2067*7c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 2068*7c478bd9Sstevel@tonic-gate sbd_board_t *sbp; 2069*7c478bd9Sstevel@tonic-gate static fn_t f = "sbd_deprobe_board"; 2070*7c478bd9Sstevel@tonic-gate 2071*7c478bd9Sstevel@tonic-gate PR_ALL("%s...\n", f); 2072*7c478bd9Sstevel@tonic-gate 2073*7c478bd9Sstevel@tonic-gate sbp = SBDH2BD(hp->h_sbd); 2074*7c478bd9Sstevel@tonic-gate 2075*7c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 2076*7c478bd9Sstevel@tonic-gate 2077*7c478bd9Sstevel@tonic-gate if ((rv = sbdp_disconnect_board(hdp)) != 0) { 2078*7c478bd9Sstevel@tonic-gate sbderror_t *ep = SBD_HD2ERR(hp); 2079*7c478bd9Sstevel@tonic-gate 2080*7c478bd9Sstevel@tonic-gate SBD_GET_PERR(hdp->h_err, ep); 2081*7c478bd9Sstevel@tonic-gate } 2082*7c478bd9Sstevel@tonic-gate 2083*7c478bd9Sstevel@tonic-gate mutex_enter(&sbp->sb_flags_mutex); 2084*7c478bd9Sstevel@tonic-gate sbp->sb_flags &= ~SBD_BOARD_STATUS_CACHED; 2085*7c478bd9Sstevel@tonic-gate mutex_exit(&sbp->sb_flags_mutex); 2086*7c478bd9Sstevel@tonic-gate 2087*7c478bd9Sstevel@tonic-gate SBD_INJECT_ERR(SBD_DEPROBE_BOARD_PSEUDO_ERR, hp->h_err, EIO, 2088*7c478bd9Sstevel@tonic-gate ESGT_DEPROBE, NULL); 2089*7c478bd9Sstevel@tonic-gate 2090*7c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 2091*7c478bd9Sstevel@tonic-gate return (rv); 2092*7c478bd9Sstevel@tonic-gate } 2093*7c478bd9Sstevel@tonic-gate 2094*7c478bd9Sstevel@tonic-gate /* 2095*7c478bd9Sstevel@tonic-gate * Check if a CPU node is part of a CMP. 2096*7c478bd9Sstevel@tonic-gate */ 2097*7c478bd9Sstevel@tonic-gate int 2098*7c478bd9Sstevel@tonic-gate sbd_is_cmp_child(dev_info_t *dip) 2099*7c478bd9Sstevel@tonic-gate { 2100*7c478bd9Sstevel@tonic-gate dev_info_t *pdip; 2101*7c478bd9Sstevel@tonic-gate 2102*7c478bd9Sstevel@tonic-gate if (strcmp(ddi_node_name(dip), "cpu") != 0) { 2103*7c478bd9Sstevel@tonic-gate return (0); 2104*7c478bd9Sstevel@tonic-gate } 2105*7c478bd9Sstevel@tonic-gate 2106*7c478bd9Sstevel@tonic-gate pdip = ddi_get_parent(dip); 2107*7c478bd9Sstevel@tonic-gate 2108*7c478bd9Sstevel@tonic-gate ASSERT(pdip); 2109*7c478bd9Sstevel@tonic-gate 2110*7c478bd9Sstevel@tonic-gate if (strcmp(ddi_node_name(pdip), "cmp") == 0) { 2111*7c478bd9Sstevel@tonic-gate return (1); 2112*7c478bd9Sstevel@tonic-gate } 2113*7c478bd9Sstevel@tonic-gate 2114*7c478bd9Sstevel@tonic-gate return (0); 2115*7c478bd9Sstevel@tonic-gate } 2116*7c478bd9Sstevel@tonic-gate 2117*7c478bd9Sstevel@tonic-gate /* 2118*7c478bd9Sstevel@tonic-gate * Returns the nodetype if dip is a top dip on the board of 2119*7c478bd9Sstevel@tonic-gate * interest or SBD_COMP_UNKNOWN otherwise 2120*7c478bd9Sstevel@tonic-gate */ 2121*7c478bd9Sstevel@tonic-gate static sbd_comp_type_t 2122*7c478bd9Sstevel@tonic-gate get_node_type(sbd_board_t *sbp, dev_info_t *dip, int *unitp) 2123*7c478bd9Sstevel@tonic-gate { 2124*7c478bd9Sstevel@tonic-gate int idx, unit; 2125*7c478bd9Sstevel@tonic-gate sbd_handle_t *hp; 2126*7c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 2127*7c478bd9Sstevel@tonic-gate char otype[OBP_MAXDRVNAME]; 2128*7c478bd9Sstevel@tonic-gate int otypelen; 2129*7c478bd9Sstevel@tonic-gate 2130*7c478bd9Sstevel@tonic-gate ASSERT(sbp); 2131*7c478bd9Sstevel@tonic-gate 2132*7c478bd9Sstevel@tonic-gate if (unitp) 2133*7c478bd9Sstevel@tonic-gate *unitp = -1; 2134*7c478bd9Sstevel@tonic-gate 2135*7c478bd9Sstevel@tonic-gate hp = MACHBD2HD(sbp); 2136*7c478bd9Sstevel@tonic-gate 2137*7c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 2138*7c478bd9Sstevel@tonic-gate if (sbdp_get_board_num(hdp, dip) != sbp->sb_num) { 2139*7c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 2140*7c478bd9Sstevel@tonic-gate return (SBD_COMP_UNKNOWN); 2141*7c478bd9Sstevel@tonic-gate } 2142*7c478bd9Sstevel@tonic-gate 2143*7c478bd9Sstevel@tonic-gate /* 2144*7c478bd9Sstevel@tonic-gate * sbdp_get_unit_num will return (-1) for cmp as there 2145*7c478bd9Sstevel@tonic-gate * is no "device_type" property associated with cmp. 2146*7c478bd9Sstevel@tonic-gate * Therefore we will just skip getting unit number for 2147*7c478bd9Sstevel@tonic-gate * cmp. Callers of this function need to check the 2148*7c478bd9Sstevel@tonic-gate * value set in unitp before using it to dereference 2149*7c478bd9Sstevel@tonic-gate * an array. 2150*7c478bd9Sstevel@tonic-gate */ 2151*7c478bd9Sstevel@tonic-gate if (strcmp(ddi_node_name(dip), "cmp") == 0) { 2152*7c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 2153*7c478bd9Sstevel@tonic-gate return (SBD_COMP_CMP); 2154*7c478bd9Sstevel@tonic-gate } 2155*7c478bd9Sstevel@tonic-gate 2156*7c478bd9Sstevel@tonic-gate otypelen = sizeof (otype); 2157*7c478bd9Sstevel@tonic-gate if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 2158*7c478bd9Sstevel@tonic-gate OBP_DEVICETYPE, (caddr_t)otype, &otypelen)) { 2159*7c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 2160*7c478bd9Sstevel@tonic-gate return (SBD_COMP_UNKNOWN); 2161*7c478bd9Sstevel@tonic-gate } 2162*7c478bd9Sstevel@tonic-gate 2163*7c478bd9Sstevel@tonic-gate idx = sbd_otype_to_idx(otype); 2164*7c478bd9Sstevel@tonic-gate 2165*7c478bd9Sstevel@tonic-gate if (SBD_COMP(idx) == SBD_COMP_UNKNOWN) { 2166*7c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 2167*7c478bd9Sstevel@tonic-gate return (SBD_COMP_UNKNOWN); 2168*7c478bd9Sstevel@tonic-gate } 2169*7c478bd9Sstevel@tonic-gate 2170*7c478bd9Sstevel@tonic-gate unit = sbdp_get_unit_num(hdp, dip); 2171*7c478bd9Sstevel@tonic-gate if (unit == -1) { 2172*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 2173*7c478bd9Sstevel@tonic-gate "get_node_type: %s unit fail %p", otype, (void *)dip); 2174*7c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 2175*7c478bd9Sstevel@tonic-gate return (SBD_COMP_UNKNOWN); 2176*7c478bd9Sstevel@tonic-gate } 2177*7c478bd9Sstevel@tonic-gate 2178*7c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 2179*7c478bd9Sstevel@tonic-gate 2180*7c478bd9Sstevel@tonic-gate if (unitp) 2181*7c478bd9Sstevel@tonic-gate *unitp = unit; 2182*7c478bd9Sstevel@tonic-gate 2183*7c478bd9Sstevel@tonic-gate return (SBD_COMP(idx)); 2184*7c478bd9Sstevel@tonic-gate } 2185*7c478bd9Sstevel@tonic-gate 2186*7c478bd9Sstevel@tonic-gate typedef struct { 2187*7c478bd9Sstevel@tonic-gate sbd_board_t *sbp; 2188*7c478bd9Sstevel@tonic-gate int nmc; 2189*7c478bd9Sstevel@tonic-gate int hold; 2190*7c478bd9Sstevel@tonic-gate } walk_tree_t; 2191*7c478bd9Sstevel@tonic-gate 2192*7c478bd9Sstevel@tonic-gate static int 2193*7c478bd9Sstevel@tonic-gate sbd_setup_devlists(dev_info_t *dip, void *arg) 2194*7c478bd9Sstevel@tonic-gate { 2195*7c478bd9Sstevel@tonic-gate walk_tree_t *wp; 2196*7c478bd9Sstevel@tonic-gate dev_info_t **devlist = NULL; 2197*7c478bd9Sstevel@tonic-gate char *pathname = NULL; 2198*7c478bd9Sstevel@tonic-gate sbd_mem_unit_t *mp; 2199*7c478bd9Sstevel@tonic-gate static fn_t f = "sbd_setup_devlists"; 2200*7c478bd9Sstevel@tonic-gate sbd_board_t *sbp; 2201*7c478bd9Sstevel@tonic-gate int unit; 2202*7c478bd9Sstevel@tonic-gate sbd_comp_type_t nodetype; 2203*7c478bd9Sstevel@tonic-gate 2204*7c478bd9Sstevel@tonic-gate ASSERT(dip); 2205*7c478bd9Sstevel@tonic-gate 2206*7c478bd9Sstevel@tonic-gate wp = (walk_tree_t *)arg; 2207*7c478bd9Sstevel@tonic-gate 2208*7c478bd9Sstevel@tonic-gate if (wp == NULL) { 2209*7c478bd9Sstevel@tonic-gate PR_ALL("%s:bad arg\n", f); 2210*7c478bd9Sstevel@tonic-gate return (DDI_WALK_TERMINATE); 2211*7c478bd9Sstevel@tonic-gate } 2212*7c478bd9Sstevel@tonic-gate 2213*7c478bd9Sstevel@tonic-gate sbp = wp->sbp; 2214*7c478bd9Sstevel@tonic-gate 2215*7c478bd9Sstevel@tonic-gate nodetype = get_node_type(sbp, dip, &unit); 2216*7c478bd9Sstevel@tonic-gate 2217*7c478bd9Sstevel@tonic-gate switch (nodetype) { 2218*7c478bd9Sstevel@tonic-gate 2219*7c478bd9Sstevel@tonic-gate case SBD_COMP_CPU: 2220*7c478bd9Sstevel@tonic-gate pathname = sbp->sb_cpupath[unit]; 2221*7c478bd9Sstevel@tonic-gate break; 2222*7c478bd9Sstevel@tonic-gate 2223*7c478bd9Sstevel@tonic-gate case SBD_COMP_MEM: 2224*7c478bd9Sstevel@tonic-gate pathname = sbp->sb_mempath[unit]; 2225*7c478bd9Sstevel@tonic-gate break; 2226*7c478bd9Sstevel@tonic-gate 2227*7c478bd9Sstevel@tonic-gate case SBD_COMP_IO: 2228*7c478bd9Sstevel@tonic-gate pathname = sbp->sb_iopath[unit]; 2229*7c478bd9Sstevel@tonic-gate break; 2230*7c478bd9Sstevel@tonic-gate 2231*7c478bd9Sstevel@tonic-gate case SBD_COMP_CMP: 2232*7c478bd9Sstevel@tonic-gate case SBD_COMP_UNKNOWN: 2233*7c478bd9Sstevel@tonic-gate /* 2234*7c478bd9Sstevel@tonic-gate * This dip is not of interest to us 2235*7c478bd9Sstevel@tonic-gate */ 2236*7c478bd9Sstevel@tonic-gate return (DDI_WALK_CONTINUE); 2237*7c478bd9Sstevel@tonic-gate 2238*7c478bd9Sstevel@tonic-gate default: 2239*7c478bd9Sstevel@tonic-gate ASSERT(0); 2240*7c478bd9Sstevel@tonic-gate return (DDI_WALK_CONTINUE); 2241*7c478bd9Sstevel@tonic-gate } 2242*7c478bd9Sstevel@tonic-gate 2243*7c478bd9Sstevel@tonic-gate /* 2244*7c478bd9Sstevel@tonic-gate * dip's parent is being held busy by ddi_walk_devs(), 2245*7c478bd9Sstevel@tonic-gate * so dip doesn't have to be held while calling ddi_pathname() 2246*7c478bd9Sstevel@tonic-gate */ 2247*7c478bd9Sstevel@tonic-gate if (pathname) { 2248*7c478bd9Sstevel@tonic-gate (void) ddi_pathname(dip, pathname); 2249*7c478bd9Sstevel@tonic-gate } 2250*7c478bd9Sstevel@tonic-gate 2251*7c478bd9Sstevel@tonic-gate devlist = sbp->sb_devlist[NIX(nodetype)]; 2252*7c478bd9Sstevel@tonic-gate 2253*7c478bd9Sstevel@tonic-gate /* 2254*7c478bd9Sstevel@tonic-gate * The branch rooted at dip should already be held, 2255*7c478bd9Sstevel@tonic-gate * unless we are dealing with a core of a CMP. 2256*7c478bd9Sstevel@tonic-gate */ 2257*7c478bd9Sstevel@tonic-gate ASSERT(sbd_is_cmp_child(dip) || e_ddi_branch_held(dip)); 2258*7c478bd9Sstevel@tonic-gate devlist[unit] = dip; 2259*7c478bd9Sstevel@tonic-gate 2260*7c478bd9Sstevel@tonic-gate /* 2261*7c478bd9Sstevel@tonic-gate * This test is required if multiple devices are considered 2262*7c478bd9Sstevel@tonic-gate * as one. This is the case for memory-controller nodes. 2263*7c478bd9Sstevel@tonic-gate */ 2264*7c478bd9Sstevel@tonic-gate if (!SBD_DEV_IS_PRESENT(sbp, nodetype, unit)) { 2265*7c478bd9Sstevel@tonic-gate sbp->sb_ndev++; 2266*7c478bd9Sstevel@tonic-gate SBD_DEV_SET_PRESENT(sbp, nodetype, unit); 2267*7c478bd9Sstevel@tonic-gate } 2268*7c478bd9Sstevel@tonic-gate 2269*7c478bd9Sstevel@tonic-gate if (nodetype == SBD_COMP_MEM) { 2270*7c478bd9Sstevel@tonic-gate mp = SBD_GET_BOARD_MEMUNIT(sbp, unit); 2271*7c478bd9Sstevel@tonic-gate ASSERT(wp->nmc < SBD_NUM_MC_PER_BOARD); 2272*7c478bd9Sstevel@tonic-gate mp->sbm_dip[wp->nmc++] = dip; 2273*7c478bd9Sstevel@tonic-gate } 2274*7c478bd9Sstevel@tonic-gate 2275*7c478bd9Sstevel@tonic-gate return (DDI_WALK_CONTINUE); 2276*7c478bd9Sstevel@tonic-gate } 2277*7c478bd9Sstevel@tonic-gate 2278*7c478bd9Sstevel@tonic-gate /* 2279*7c478bd9Sstevel@tonic-gate * This routine is used to construct the memory devlist. 2280*7c478bd9Sstevel@tonic-gate * In Starcat and Serengeti platforms, a system board can contain up to 2281*7c478bd9Sstevel@tonic-gate * four memory controllers (MC). The MCs have been programmed by POST for 2282*7c478bd9Sstevel@tonic-gate * optimum memory interleaving amongst their peers on the same board. 2283*7c478bd9Sstevel@tonic-gate * This DR driver does not support deinterleaving. Therefore, the smallest 2284*7c478bd9Sstevel@tonic-gate * unit of memory that can be manipulated by this driver is all of the 2285*7c478bd9Sstevel@tonic-gate * memory on a board. Because of this restriction, a board's memory devlist 2286*7c478bd9Sstevel@tonic-gate * is populated with only one of the four (possible) MC dnodes on that board. 2287*7c478bd9Sstevel@tonic-gate * Care must be taken to ensure that the selected MC dnode represents the 2288*7c478bd9Sstevel@tonic-gate * lowest physical address to which memory on the board will respond to. 2289*7c478bd9Sstevel@tonic-gate * This is required in order to preserve the semantics of 2290*7c478bd9Sstevel@tonic-gate * sbdp_get_base_physaddr() when applied to a MC dnode stored in the 2291*7c478bd9Sstevel@tonic-gate * memory devlist. 2292*7c478bd9Sstevel@tonic-gate */ 2293*7c478bd9Sstevel@tonic-gate static void 2294*7c478bd9Sstevel@tonic-gate sbd_init_mem_devlists(sbd_board_t *sbp) 2295*7c478bd9Sstevel@tonic-gate { 2296*7c478bd9Sstevel@tonic-gate dev_info_t **devlist; 2297*7c478bd9Sstevel@tonic-gate sbd_mem_unit_t *mp; 2298*7c478bd9Sstevel@tonic-gate dev_info_t *mc_dip; 2299*7c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 2300*7c478bd9Sstevel@tonic-gate uint64_t mc_pa, lowest_pa; 2301*7c478bd9Sstevel@tonic-gate int i; 2302*7c478bd9Sstevel@tonic-gate sbd_handle_t *hp = MACHBD2HD(sbp); 2303*7c478bd9Sstevel@tonic-gate 2304*7c478bd9Sstevel@tonic-gate devlist = sbp->sb_devlist[NIX(SBD_COMP_MEM)]; 2305*7c478bd9Sstevel@tonic-gate 2306*7c478bd9Sstevel@tonic-gate mp = SBD_GET_BOARD_MEMUNIT(sbp, 0); 2307*7c478bd9Sstevel@tonic-gate 2308*7c478bd9Sstevel@tonic-gate mc_dip = mp->sbm_dip[0]; 2309*7c478bd9Sstevel@tonic-gate if (mc_dip == NULL) 2310*7c478bd9Sstevel@tonic-gate return; /* No MC dips found for this board */ 2311*7c478bd9Sstevel@tonic-gate 2312*7c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 2313*7c478bd9Sstevel@tonic-gate 2314*7c478bd9Sstevel@tonic-gate if (sbdphw_get_base_physaddr(hdp, mc_dip, &mc_pa)) { 2315*7c478bd9Sstevel@tonic-gate /* TODO: log complaint about dnode */ 2316*7c478bd9Sstevel@tonic-gate 2317*7c478bd9Sstevel@tonic-gate pretend_no_mem: 2318*7c478bd9Sstevel@tonic-gate /* 2319*7c478bd9Sstevel@tonic-gate * We are here because sbdphw_get_base_physaddr() failed. 2320*7c478bd9Sstevel@tonic-gate * Although it is very unlikely to happen, it did. Lucky us. 2321*7c478bd9Sstevel@tonic-gate * Since we can no longer examine _all_ of the MCs on this 2322*7c478bd9Sstevel@tonic-gate * board to determine which one is programmed to the lowest 2323*7c478bd9Sstevel@tonic-gate * physical address, we cannot involve any of the MCs on 2324*7c478bd9Sstevel@tonic-gate * this board in DR operations. To ensure this, we pretend 2325*7c478bd9Sstevel@tonic-gate * that this board does not contain any memory. 2326*7c478bd9Sstevel@tonic-gate * 2327*7c478bd9Sstevel@tonic-gate * Paranoia: clear the dev_present mask. 2328*7c478bd9Sstevel@tonic-gate */ 2329*7c478bd9Sstevel@tonic-gate if (SBD_DEV_IS_PRESENT(sbp, SBD_COMP_MEM, 0)) { 2330*7c478bd9Sstevel@tonic-gate ASSERT(sbp->sb_ndev != 0); 2331*7c478bd9Sstevel@tonic-gate SBD_DEV_CLR_PRESENT(sbp, SBD_COMP_MEM, 0); 2332*7c478bd9Sstevel@tonic-gate sbp->sb_ndev--; 2333*7c478bd9Sstevel@tonic-gate } 2334*7c478bd9Sstevel@tonic-gate 2335*7c478bd9Sstevel@tonic-gate for (i = 0; i < SBD_NUM_MC_PER_BOARD; i++) { 2336*7c478bd9Sstevel@tonic-gate mp->sbm_dip[i] = NULL; 2337*7c478bd9Sstevel@tonic-gate } 2338*7c478bd9Sstevel@tonic-gate 2339*7c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 2340*7c478bd9Sstevel@tonic-gate return; 2341*7c478bd9Sstevel@tonic-gate } 2342*7c478bd9Sstevel@tonic-gate 2343*7c478bd9Sstevel@tonic-gate /* assume this one will win. */ 2344*7c478bd9Sstevel@tonic-gate devlist[0] = mc_dip; 2345*7c478bd9Sstevel@tonic-gate mp->sbm_cm.sbdev_dip = mc_dip; 2346*7c478bd9Sstevel@tonic-gate lowest_pa = mc_pa; 2347*7c478bd9Sstevel@tonic-gate 2348*7c478bd9Sstevel@tonic-gate /* 2349*7c478bd9Sstevel@tonic-gate * We know the base physical address of one of the MC devices. Now 2350*7c478bd9Sstevel@tonic-gate * we will enumerate through all of the remaining MC devices on 2351*7c478bd9Sstevel@tonic-gate * the board to find which of them is programmed to the lowest 2352*7c478bd9Sstevel@tonic-gate * physical address. 2353*7c478bd9Sstevel@tonic-gate */ 2354*7c478bd9Sstevel@tonic-gate for (i = 1; i < SBD_NUM_MC_PER_BOARD; i++) { 2355*7c478bd9Sstevel@tonic-gate mc_dip = mp->sbm_dip[i]; 2356*7c478bd9Sstevel@tonic-gate if (mc_dip == NULL) { 2357*7c478bd9Sstevel@tonic-gate break; 2358*7c478bd9Sstevel@tonic-gate } 2359*7c478bd9Sstevel@tonic-gate 2360*7c478bd9Sstevel@tonic-gate if (sbdphw_get_base_physaddr(hdp, mc_dip, &mc_pa)) { 2361*7c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "No mem on board %d unit %d", 2362*7c478bd9Sstevel@tonic-gate sbp->sb_num, i); 2363*7c478bd9Sstevel@tonic-gate break; 2364*7c478bd9Sstevel@tonic-gate } 2365*7c478bd9Sstevel@tonic-gate if (mc_pa < lowest_pa) { 2366*7c478bd9Sstevel@tonic-gate mp->sbm_cm.sbdev_dip = mc_dip; 2367*7c478bd9Sstevel@tonic-gate devlist[0] = mc_dip; 2368*7c478bd9Sstevel@tonic-gate lowest_pa = mc_pa; 2369*7c478bd9Sstevel@tonic-gate } 2370*7c478bd9Sstevel@tonic-gate } 2371*7c478bd9Sstevel@tonic-gate 2372*7c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 2373*7c478bd9Sstevel@tonic-gate } 2374*7c478bd9Sstevel@tonic-gate 2375*7c478bd9Sstevel@tonic-gate static int 2376*7c478bd9Sstevel@tonic-gate sbd_name_to_idx(char *name) 2377*7c478bd9Sstevel@tonic-gate { 2378*7c478bd9Sstevel@tonic-gate int idx; 2379*7c478bd9Sstevel@tonic-gate 2380*7c478bd9Sstevel@tonic-gate for (idx = 0; SBD_COMP(idx) != SBD_COMP_UNKNOWN; idx++) { 2381*7c478bd9Sstevel@tonic-gate if (strcmp(name, SBD_DEVNAME(idx)) == 0) { 2382*7c478bd9Sstevel@tonic-gate break; 2383*7c478bd9Sstevel@tonic-gate } 2384*7c478bd9Sstevel@tonic-gate } 2385*7c478bd9Sstevel@tonic-gate 2386*7c478bd9Sstevel@tonic-gate return (idx); 2387*7c478bd9Sstevel@tonic-gate } 2388*7c478bd9Sstevel@tonic-gate 2389*7c478bd9Sstevel@tonic-gate static int 2390*7c478bd9Sstevel@tonic-gate sbd_otype_to_idx(char *otype) 2391*7c478bd9Sstevel@tonic-gate { 2392*7c478bd9Sstevel@tonic-gate int idx; 2393*7c478bd9Sstevel@tonic-gate 2394*7c478bd9Sstevel@tonic-gate for (idx = 0; SBD_COMP(idx) != SBD_COMP_UNKNOWN; idx++) { 2395*7c478bd9Sstevel@tonic-gate 2396*7c478bd9Sstevel@tonic-gate if (strcmp(otype, SBD_OTYPE(idx)) == 0) { 2397*7c478bd9Sstevel@tonic-gate break; 2398*7c478bd9Sstevel@tonic-gate } 2399*7c478bd9Sstevel@tonic-gate } 2400*7c478bd9Sstevel@tonic-gate 2401*7c478bd9Sstevel@tonic-gate return (idx); 2402*7c478bd9Sstevel@tonic-gate } 2403*7c478bd9Sstevel@tonic-gate 2404*7c478bd9Sstevel@tonic-gate static int 2405*7c478bd9Sstevel@tonic-gate sbd_init_devlists(sbd_board_t *sbp) 2406*7c478bd9Sstevel@tonic-gate { 2407*7c478bd9Sstevel@tonic-gate int i; 2408*7c478bd9Sstevel@tonic-gate sbd_dev_unit_t *dp; 2409*7c478bd9Sstevel@tonic-gate sbd_mem_unit_t *mp; 2410*7c478bd9Sstevel@tonic-gate walk_tree_t *wp, walk = {0}; 2411*7c478bd9Sstevel@tonic-gate dev_info_t *pdip; 2412*7c478bd9Sstevel@tonic-gate static fn_t f = "sbd_init_devlists"; 2413*7c478bd9Sstevel@tonic-gate 2414*7c478bd9Sstevel@tonic-gate PR_ALL("%s (board = %d)...\n", f, sbp->sb_num); 2415*7c478bd9Sstevel@tonic-gate 2416*7c478bd9Sstevel@tonic-gate wp = &walk; 2417*7c478bd9Sstevel@tonic-gate 2418*7c478bd9Sstevel@tonic-gate SBD_DEVS_DISCONNECT(sbp, (uint_t)-1); 2419*7c478bd9Sstevel@tonic-gate 2420*7c478bd9Sstevel@tonic-gate /* 2421*7c478bd9Sstevel@tonic-gate * Clear out old entries, if any. 2422*7c478bd9Sstevel@tonic-gate */ 2423*7c478bd9Sstevel@tonic-gate 2424*7c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_MEM_UNITS_PER_BOARD; i++) { 2425*7c478bd9Sstevel@tonic-gate sbp->sb_devlist[NIX(SBD_COMP_MEM)][i] = NULL; 2426*7c478bd9Sstevel@tonic-gate dp = (sbd_dev_unit_t *)SBD_GET_BOARD_MEMUNIT(sbp, i); 2427*7c478bd9Sstevel@tonic-gate dp->u_common.sbdev_sbp = sbp; 2428*7c478bd9Sstevel@tonic-gate dp->u_common.sbdev_unum = i; 2429*7c478bd9Sstevel@tonic-gate dp->u_common.sbdev_type = SBD_COMP_MEM; 2430*7c478bd9Sstevel@tonic-gate } 2431*7c478bd9Sstevel@tonic-gate 2432*7c478bd9Sstevel@tonic-gate mp = SBD_GET_BOARD_MEMUNIT(sbp, 0); 2433*7c478bd9Sstevel@tonic-gate ASSERT(mp != NULL); 2434*7c478bd9Sstevel@tonic-gate for (i = 0; i < SBD_NUM_MC_PER_BOARD; i++) { 2435*7c478bd9Sstevel@tonic-gate mp->sbm_dip[i] = NULL; 2436*7c478bd9Sstevel@tonic-gate } 2437*7c478bd9Sstevel@tonic-gate 2438*7c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_CPU_UNITS_PER_BOARD; i++) { 2439*7c478bd9Sstevel@tonic-gate sbp->sb_devlist[NIX(SBD_COMP_CPU)][i] = NULL; 2440*7c478bd9Sstevel@tonic-gate dp = (sbd_dev_unit_t *)SBD_GET_BOARD_CPUUNIT(sbp, i); 2441*7c478bd9Sstevel@tonic-gate dp->u_common.sbdev_sbp = sbp; 2442*7c478bd9Sstevel@tonic-gate dp->u_common.sbdev_unum = i; 2443*7c478bd9Sstevel@tonic-gate dp->u_common.sbdev_type = SBD_COMP_CPU; 2444*7c478bd9Sstevel@tonic-gate } 2445*7c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_IO_UNITS_PER_BOARD; i++) { 2446*7c478bd9Sstevel@tonic-gate sbp->sb_devlist[NIX(SBD_COMP_IO)][i] = NULL; 2447*7c478bd9Sstevel@tonic-gate dp = (sbd_dev_unit_t *)SBD_GET_BOARD_IOUNIT(sbp, i); 2448*7c478bd9Sstevel@tonic-gate dp->u_common.sbdev_sbp = sbp; 2449*7c478bd9Sstevel@tonic-gate dp->u_common.sbdev_unum = i; 2450*7c478bd9Sstevel@tonic-gate dp->u_common.sbdev_type = SBD_COMP_IO; 2451*7c478bd9Sstevel@tonic-gate } 2452*7c478bd9Sstevel@tonic-gate 2453*7c478bd9Sstevel@tonic-gate wp->sbp = sbp; 2454*7c478bd9Sstevel@tonic-gate wp->nmc = 0; 2455*7c478bd9Sstevel@tonic-gate sbp->sb_ndev = 0; 2456*7c478bd9Sstevel@tonic-gate 2457*7c478bd9Sstevel@tonic-gate /* 2458*7c478bd9Sstevel@tonic-gate * ddi_walk_devs() requires that topdip's parent be held. 2459*7c478bd9Sstevel@tonic-gate */ 2460*7c478bd9Sstevel@tonic-gate pdip = ddi_get_parent(sbp->sb_topdip); 2461*7c478bd9Sstevel@tonic-gate if (pdip) { 2462*7c478bd9Sstevel@tonic-gate ndi_hold_devi(pdip); 2463*7c478bd9Sstevel@tonic-gate ndi_devi_enter(pdip, &i); 2464*7c478bd9Sstevel@tonic-gate } 2465*7c478bd9Sstevel@tonic-gate ddi_walk_devs(sbp->sb_topdip, sbd_setup_devlists, (void *) wp); 2466*7c478bd9Sstevel@tonic-gate if (pdip) { 2467*7c478bd9Sstevel@tonic-gate ndi_devi_exit(pdip, i); 2468*7c478bd9Sstevel@tonic-gate ndi_rele_devi(pdip); 2469*7c478bd9Sstevel@tonic-gate } 2470*7c478bd9Sstevel@tonic-gate 2471*7c478bd9Sstevel@tonic-gate /* 2472*7c478bd9Sstevel@tonic-gate * There is no point checking all the components if there 2473*7c478bd9Sstevel@tonic-gate * are no devices. 2474*7c478bd9Sstevel@tonic-gate */ 2475*7c478bd9Sstevel@tonic-gate if (sbp->sb_ndev == 0) { 2476*7c478bd9Sstevel@tonic-gate sbp->sb_memaccess_ok = 0; 2477*7c478bd9Sstevel@tonic-gate return (sbp->sb_ndev); 2478*7c478bd9Sstevel@tonic-gate } 2479*7c478bd9Sstevel@tonic-gate 2480*7c478bd9Sstevel@tonic-gate /* 2481*7c478bd9Sstevel@tonic-gate * Initialize cpu sections before calling sbd_init_mem_devlists 2482*7c478bd9Sstevel@tonic-gate * which will access the mmus. 2483*7c478bd9Sstevel@tonic-gate */ 2484*7c478bd9Sstevel@tonic-gate sbp->sb_memaccess_ok = 1; 2485*7c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_CPU_UNITS_PER_BOARD; i++) { 2486*7c478bd9Sstevel@tonic-gate if (SBD_DEV_IS_PRESENT(sbp, SBD_COMP_CPU, i)) { 2487*7c478bd9Sstevel@tonic-gate sbd_init_cpu_unit(sbp, i); 2488*7c478bd9Sstevel@tonic-gate if (sbd_connect_cpu(sbp, i)) { 2489*7c478bd9Sstevel@tonic-gate SBD_SET_ERR(HD2MACHERR(MACHBD2HD(sbp)), 2490*7c478bd9Sstevel@tonic-gate ESBD_CPUSTART); 2491*7c478bd9Sstevel@tonic-gate } 2492*7c478bd9Sstevel@tonic-gate 2493*7c478bd9Sstevel@tonic-gate } 2494*7c478bd9Sstevel@tonic-gate } 2495*7c478bd9Sstevel@tonic-gate 2496*7c478bd9Sstevel@tonic-gate if (sbp->sb_memaccess_ok) { 2497*7c478bd9Sstevel@tonic-gate sbd_init_mem_devlists(sbp); 2498*7c478bd9Sstevel@tonic-gate } else { 2499*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "unable to access memory on board %d", 2500*7c478bd9Sstevel@tonic-gate sbp->sb_num); 2501*7c478bd9Sstevel@tonic-gate } 2502*7c478bd9Sstevel@tonic-gate 2503*7c478bd9Sstevel@tonic-gate return (sbp->sb_ndev); 2504*7c478bd9Sstevel@tonic-gate } 2505*7c478bd9Sstevel@tonic-gate 2506*7c478bd9Sstevel@tonic-gate static void 2507*7c478bd9Sstevel@tonic-gate sbd_init_cpu_unit(sbd_board_t *sbp, int unit) 2508*7c478bd9Sstevel@tonic-gate { 2509*7c478bd9Sstevel@tonic-gate sbd_istate_t new_state; 2510*7c478bd9Sstevel@tonic-gate sbd_cpu_unit_t *cp; 2511*7c478bd9Sstevel@tonic-gate int cpuid; 2512*7c478bd9Sstevel@tonic-gate dev_info_t *dip; 2513*7c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 2514*7c478bd9Sstevel@tonic-gate sbd_handle_t *hp = MACHBD2HD(sbp); 2515*7c478bd9Sstevel@tonic-gate extern kmutex_t cpu_lock; 2516*7c478bd9Sstevel@tonic-gate 2517*7c478bd9Sstevel@tonic-gate if (SBD_DEV_IS_ATTACHED(sbp, SBD_COMP_CPU, unit)) { 2518*7c478bd9Sstevel@tonic-gate new_state = SBD_STATE_CONFIGURED; 2519*7c478bd9Sstevel@tonic-gate } else if (SBD_DEV_IS_PRESENT(sbp, SBD_COMP_CPU, unit)) { 2520*7c478bd9Sstevel@tonic-gate new_state = SBD_STATE_CONNECTED; 2521*7c478bd9Sstevel@tonic-gate } else { 2522*7c478bd9Sstevel@tonic-gate new_state = SBD_STATE_EMPTY; 2523*7c478bd9Sstevel@tonic-gate } 2524*7c478bd9Sstevel@tonic-gate 2525*7c478bd9Sstevel@tonic-gate dip = sbp->sb_devlist[NIX(SBD_COMP_CPU)][unit]; 2526*7c478bd9Sstevel@tonic-gate 2527*7c478bd9Sstevel@tonic-gate cp = SBD_GET_BOARD_CPUUNIT(sbp, unit); 2528*7c478bd9Sstevel@tonic-gate 2529*7c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 2530*7c478bd9Sstevel@tonic-gate 2531*7c478bd9Sstevel@tonic-gate cpuid = sbdp_get_cpuid(hdp, dip); 2532*7c478bd9Sstevel@tonic-gate 2533*7c478bd9Sstevel@tonic-gate cp->sbc_cpu_id = cpuid; 2534*7c478bd9Sstevel@tonic-gate 2535*7c478bd9Sstevel@tonic-gate if (&sbdp_cpu_get_impl) 2536*7c478bd9Sstevel@tonic-gate cp->sbc_cpu_impl = sbdp_cpu_get_impl(hdp, dip); 2537*7c478bd9Sstevel@tonic-gate else 2538*7c478bd9Sstevel@tonic-gate cp->sbc_cpu_impl = -1; 2539*7c478bd9Sstevel@tonic-gate 2540*7c478bd9Sstevel@tonic-gate mutex_enter(&cpu_lock); 2541*7c478bd9Sstevel@tonic-gate if ((cpuid >= 0) && cpu[cpuid]) 2542*7c478bd9Sstevel@tonic-gate cp->sbc_cpu_flags = cpu[cpuid]->cpu_flags; 2543*7c478bd9Sstevel@tonic-gate else 2544*7c478bd9Sstevel@tonic-gate cp->sbc_cpu_flags = CPU_OFFLINE | CPU_POWEROFF; 2545*7c478bd9Sstevel@tonic-gate mutex_exit(&cpu_lock); 2546*7c478bd9Sstevel@tonic-gate 2547*7c478bd9Sstevel@tonic-gate sbd_cpu_set_prop(cp, dip); 2548*7c478bd9Sstevel@tonic-gate 2549*7c478bd9Sstevel@tonic-gate cp->sbc_cm.sbdev_cond = sbd_get_comp_cond(dip); 2550*7c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 2551*7c478bd9Sstevel@tonic-gate 2552*7c478bd9Sstevel@tonic-gate /* 2553*7c478bd9Sstevel@tonic-gate * Any changes to the cpu should be performed above 2554*7c478bd9Sstevel@tonic-gate * this call to ensure the cpu is fully initialized 2555*7c478bd9Sstevel@tonic-gate * before transitioning to the new state. 2556*7c478bd9Sstevel@tonic-gate */ 2557*7c478bd9Sstevel@tonic-gate SBD_DEVICE_TRANSITION(sbp, SBD_COMP_CPU, unit, new_state); 2558*7c478bd9Sstevel@tonic-gate } 2559*7c478bd9Sstevel@tonic-gate 2560*7c478bd9Sstevel@tonic-gate /* 2561*7c478bd9Sstevel@tonic-gate * Only do work if called to operate on an entire board 2562*7c478bd9Sstevel@tonic-gate * which doesn't already have components present. 2563*7c478bd9Sstevel@tonic-gate */ 2564*7c478bd9Sstevel@tonic-gate static void 2565*7c478bd9Sstevel@tonic-gate sbd_connect(sbd_handle_t *hp) 2566*7c478bd9Sstevel@tonic-gate { 2567*7c478bd9Sstevel@tonic-gate sbd_board_t *sbp; 2568*7c478bd9Sstevel@tonic-gate sbderror_t *ep; 2569*7c478bd9Sstevel@tonic-gate static fn_t f = "sbd_connect"; 2570*7c478bd9Sstevel@tonic-gate 2571*7c478bd9Sstevel@tonic-gate sbp = SBDH2BD(hp->h_sbd); 2572*7c478bd9Sstevel@tonic-gate 2573*7c478bd9Sstevel@tonic-gate PR_ALL("%s board %d\n", f, sbp->sb_num); 2574*7c478bd9Sstevel@tonic-gate 2575*7c478bd9Sstevel@tonic-gate ep = HD2MACHERR(hp); 2576*7c478bd9Sstevel@tonic-gate 2577*7c478bd9Sstevel@tonic-gate if (SBD_DEVS_PRESENT(sbp)) { 2578*7c478bd9Sstevel@tonic-gate /* 2579*7c478bd9Sstevel@tonic-gate * Board already has devices present. 2580*7c478bd9Sstevel@tonic-gate */ 2581*7c478bd9Sstevel@tonic-gate PR_ALL("%s: devices already present (0x%x)\n", 2582*7c478bd9Sstevel@tonic-gate f, SBD_DEVS_PRESENT(sbp)); 2583*7c478bd9Sstevel@tonic-gate SBD_SET_ERRNO(ep, EINVAL); 2584*7c478bd9Sstevel@tonic-gate return; 2585*7c478bd9Sstevel@tonic-gate } 2586*7c478bd9Sstevel@tonic-gate 2587*7c478bd9Sstevel@tonic-gate if (sbd_init_devlists(sbp) == 0) { 2588*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "%s: no devices present on board %d", 2589*7c478bd9Sstevel@tonic-gate f, sbp->sb_num); 2590*7c478bd9Sstevel@tonic-gate SBD_SET_ERR(ep, ESBD_NODEV); 2591*7c478bd9Sstevel@tonic-gate return; 2592*7c478bd9Sstevel@tonic-gate } else { 2593*7c478bd9Sstevel@tonic-gate int i; 2594*7c478bd9Sstevel@tonic-gate 2595*7c478bd9Sstevel@tonic-gate /* 2596*7c478bd9Sstevel@tonic-gate * Initialize mem-unit section of board structure. 2597*7c478bd9Sstevel@tonic-gate */ 2598*7c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_MEM_UNITS_PER_BOARD; i++) 2599*7c478bd9Sstevel@tonic-gate if (SBD_DEV_IS_PRESENT(sbp, SBD_COMP_MEM, i)) 2600*7c478bd9Sstevel@tonic-gate sbd_init_mem_unit(sbp, i, SBD_HD2ERR(hp)); 2601*7c478bd9Sstevel@tonic-gate 2602*7c478bd9Sstevel@tonic-gate /* 2603*7c478bd9Sstevel@tonic-gate * Initialize sb_io sections. 2604*7c478bd9Sstevel@tonic-gate */ 2605*7c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_IO_UNITS_PER_BOARD; i++) 2606*7c478bd9Sstevel@tonic-gate if (SBD_DEV_IS_PRESENT(sbp, SBD_COMP_IO, i)) 2607*7c478bd9Sstevel@tonic-gate sbd_init_io_unit(sbp, i); 2608*7c478bd9Sstevel@tonic-gate 2609*7c478bd9Sstevel@tonic-gate SBD_BOARD_TRANSITION(sbp, SBD_STATE_CONNECTED); 2610*7c478bd9Sstevel@tonic-gate sbp->sb_rstate = SBD_STAT_CONNECTED; 2611*7c478bd9Sstevel@tonic-gate sbp->sb_ostate = SBD_STAT_UNCONFIGURED; 2612*7c478bd9Sstevel@tonic-gate (void) drv_getparm(TIME, (void *)&sbp->sb_time); 2613*7c478bd9Sstevel@tonic-gate SBD_INJECT_ERR(SBD_CONNECT_BOARD_PSEUDO_ERR, hp->h_err, EIO, 2614*7c478bd9Sstevel@tonic-gate ESBD_INTERNAL, NULL); 2615*7c478bd9Sstevel@tonic-gate } 2616*7c478bd9Sstevel@tonic-gate } 2617*7c478bd9Sstevel@tonic-gate 2618*7c478bd9Sstevel@tonic-gate static int 2619*7c478bd9Sstevel@tonic-gate sbd_disconnect(sbd_handle_t *hp) 2620*7c478bd9Sstevel@tonic-gate { 2621*7c478bd9Sstevel@tonic-gate int i; 2622*7c478bd9Sstevel@tonic-gate sbd_devset_t devset; 2623*7c478bd9Sstevel@tonic-gate sbd_board_t *sbp; 2624*7c478bd9Sstevel@tonic-gate static fn_t f = "sbd_disconnect it"; 2625*7c478bd9Sstevel@tonic-gate 2626*7c478bd9Sstevel@tonic-gate PR_ALL("%s ...\n", f); 2627*7c478bd9Sstevel@tonic-gate 2628*7c478bd9Sstevel@tonic-gate sbp = SBDH2BD(hp->h_sbd); 2629*7c478bd9Sstevel@tonic-gate 2630*7c478bd9Sstevel@tonic-gate /* 2631*7c478bd9Sstevel@tonic-gate * Only devices which are present, but 2632*7c478bd9Sstevel@tonic-gate * unattached can be disconnected. 2633*7c478bd9Sstevel@tonic-gate */ 2634*7c478bd9Sstevel@tonic-gate devset = HD2MACHHD(hp)->sh_devset & SBD_DEVS_PRESENT(sbp) & 2635*7c478bd9Sstevel@tonic-gate SBD_DEVS_UNATTACHED(sbp); 2636*7c478bd9Sstevel@tonic-gate 2637*7c478bd9Sstevel@tonic-gate ASSERT((SBD_DEVS_ATTACHED(sbp) & devset) == 0); 2638*7c478bd9Sstevel@tonic-gate 2639*7c478bd9Sstevel@tonic-gate /* 2640*7c478bd9Sstevel@tonic-gate * Update per-device state transitions. 2641*7c478bd9Sstevel@tonic-gate */ 2642*7c478bd9Sstevel@tonic-gate 2643*7c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_MEM_UNITS_PER_BOARD; i++) 2644*7c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devset, SBD_COMP_MEM, i)) { 2645*7c478bd9Sstevel@tonic-gate if (sbd_disconnect_mem(hp, i) == 0) { 2646*7c478bd9Sstevel@tonic-gate SBD_DEVICE_TRANSITION(sbp, SBD_COMP_MEM, i, 2647*7c478bd9Sstevel@tonic-gate SBD_STATE_EMPTY); 2648*7c478bd9Sstevel@tonic-gate SBD_DEV_CLR_PRESENT(sbp, SBD_COMP_MEM, i); 2649*7c478bd9Sstevel@tonic-gate } 2650*7c478bd9Sstevel@tonic-gate } 2651*7c478bd9Sstevel@tonic-gate 2652*7c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_CPU_UNITS_PER_BOARD; i++) 2653*7c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devset, SBD_COMP_CPU, i)) { 2654*7c478bd9Sstevel@tonic-gate if (sbd_disconnect_cpu(hp, i) == 0) { 2655*7c478bd9Sstevel@tonic-gate SBD_DEVICE_TRANSITION(sbp, SBD_COMP_CPU, i, 2656*7c478bd9Sstevel@tonic-gate SBD_STATE_EMPTY); 2657*7c478bd9Sstevel@tonic-gate SBD_DEV_CLR_PRESENT(sbp, SBD_COMP_CPU, i); 2658*7c478bd9Sstevel@tonic-gate } 2659*7c478bd9Sstevel@tonic-gate } 2660*7c478bd9Sstevel@tonic-gate 2661*7c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_IO_UNITS_PER_BOARD; i++) 2662*7c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devset, SBD_COMP_IO, i)) { 2663*7c478bd9Sstevel@tonic-gate if (sbd_disconnect_io(hp, i) == 0) { 2664*7c478bd9Sstevel@tonic-gate SBD_DEVICE_TRANSITION(sbp, SBD_COMP_IO, i, 2665*7c478bd9Sstevel@tonic-gate SBD_STATE_EMPTY); 2666*7c478bd9Sstevel@tonic-gate SBD_DEV_CLR_PRESENT(sbp, SBD_COMP_IO, i); 2667*7c478bd9Sstevel@tonic-gate } 2668*7c478bd9Sstevel@tonic-gate } 2669*7c478bd9Sstevel@tonic-gate 2670*7c478bd9Sstevel@tonic-gate /* 2671*7c478bd9Sstevel@tonic-gate * Once all the components on a board have been disconnect 2672*7c478bd9Sstevel@tonic-gate * the board's state can transition to disconnected and 2673*7c478bd9Sstevel@tonic-gate * we can allow the deprobe to take place. 2674*7c478bd9Sstevel@tonic-gate */ 2675*7c478bd9Sstevel@tonic-gate if (SBD_DEVS_PRESENT(sbp) == 0) { 2676*7c478bd9Sstevel@tonic-gate SBD_BOARD_TRANSITION(sbp, SBD_STATE_OCCUPIED); 2677*7c478bd9Sstevel@tonic-gate sbp->sb_rstate = SBD_STAT_DISCONNECTED; 2678*7c478bd9Sstevel@tonic-gate sbp->sb_ostate = SBD_STAT_UNCONFIGURED; 2679*7c478bd9Sstevel@tonic-gate (void) drv_getparm(TIME, (void *)&sbp->sb_time); 2680*7c478bd9Sstevel@tonic-gate SBD_INJECT_ERR(SBD_DISCONNECT_BOARD_PSEUDO_ERR, hp->h_err, EIO, 2681*7c478bd9Sstevel@tonic-gate ESBD_INTERNAL, NULL); 2682*7c478bd9Sstevel@tonic-gate return (0); 2683*7c478bd9Sstevel@tonic-gate } else { 2684*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "%s: could not disconnect devices on board %d", 2685*7c478bd9Sstevel@tonic-gate f, sbp->sb_num); 2686*7c478bd9Sstevel@tonic-gate return (-1); 2687*7c478bd9Sstevel@tonic-gate } 2688*7c478bd9Sstevel@tonic-gate } 2689*7c478bd9Sstevel@tonic-gate 2690*7c478bd9Sstevel@tonic-gate static void 2691*7c478bd9Sstevel@tonic-gate sbd_test_board(sbd_handle_t *hp) 2692*7c478bd9Sstevel@tonic-gate { 2693*7c478bd9Sstevel@tonic-gate sbd_board_t *sbp; 2694*7c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 2695*7c478bd9Sstevel@tonic-gate 2696*7c478bd9Sstevel@tonic-gate sbp = SBDH2BD(hp->h_sbd); 2697*7c478bd9Sstevel@tonic-gate 2698*7c478bd9Sstevel@tonic-gate PR_ALL("sbd_test_board: board %d\n", sbp->sb_num); 2699*7c478bd9Sstevel@tonic-gate 2700*7c478bd9Sstevel@tonic-gate 2701*7c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 2702*7c478bd9Sstevel@tonic-gate 2703*7c478bd9Sstevel@tonic-gate if (sbdp_test_board(hdp, &hp->h_opts) != 0) { 2704*7c478bd9Sstevel@tonic-gate sbderror_t *ep = SBD_HD2ERR(hp); 2705*7c478bd9Sstevel@tonic-gate 2706*7c478bd9Sstevel@tonic-gate SBD_GET_PERR(hdp->h_err, ep); 2707*7c478bd9Sstevel@tonic-gate } 2708*7c478bd9Sstevel@tonic-gate 2709*7c478bd9Sstevel@tonic-gate SBD_INJECT_ERR(SBD_TEST_BOARD_PSEUDO_ERR, hp->h_err, EIO, 2710*7c478bd9Sstevel@tonic-gate ESBD_INTERNAL, NULL); 2711*7c478bd9Sstevel@tonic-gate 2712*7c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 2713*7c478bd9Sstevel@tonic-gate } 2714*7c478bd9Sstevel@tonic-gate 2715*7c478bd9Sstevel@tonic-gate static void 2716*7c478bd9Sstevel@tonic-gate sbd_assign_board(sbd_handle_t *hp) 2717*7c478bd9Sstevel@tonic-gate { 2718*7c478bd9Sstevel@tonic-gate sbd_board_t *sbp; 2719*7c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 2720*7c478bd9Sstevel@tonic-gate 2721*7c478bd9Sstevel@tonic-gate sbp = SBDH2BD(hp->h_sbd); 2722*7c478bd9Sstevel@tonic-gate 2723*7c478bd9Sstevel@tonic-gate PR_ALL("sbd_assign_board: board %d\n", sbp->sb_num); 2724*7c478bd9Sstevel@tonic-gate 2725*7c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 2726*7c478bd9Sstevel@tonic-gate 2727*7c478bd9Sstevel@tonic-gate if (sbdp_assign_board(hdp) != 0) { 2728*7c478bd9Sstevel@tonic-gate sbderror_t *ep = SBD_HD2ERR(hp); 2729*7c478bd9Sstevel@tonic-gate 2730*7c478bd9Sstevel@tonic-gate SBD_GET_PERR(hdp->h_err, ep); 2731*7c478bd9Sstevel@tonic-gate } 2732*7c478bd9Sstevel@tonic-gate 2733*7c478bd9Sstevel@tonic-gate SBD_INJECT_ERR(SBD_ASSIGN_BOARD_PSEUDO_ERR, hp->h_err, EIO, 2734*7c478bd9Sstevel@tonic-gate ESBD_INTERNAL, NULL); 2735*7c478bd9Sstevel@tonic-gate 2736*7c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 2737*7c478bd9Sstevel@tonic-gate } 2738*7c478bd9Sstevel@tonic-gate 2739*7c478bd9Sstevel@tonic-gate static void 2740*7c478bd9Sstevel@tonic-gate sbd_unassign_board(sbd_handle_t *hp) 2741*7c478bd9Sstevel@tonic-gate { 2742*7c478bd9Sstevel@tonic-gate sbd_board_t *sbp; 2743*7c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 2744*7c478bd9Sstevel@tonic-gate 2745*7c478bd9Sstevel@tonic-gate sbp = SBDH2BD(hp->h_sbd); 2746*7c478bd9Sstevel@tonic-gate 2747*7c478bd9Sstevel@tonic-gate PR_ALL("sbd_unassign_board: board %d\n", sbp->sb_num); 2748*7c478bd9Sstevel@tonic-gate 2749*7c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 2750*7c478bd9Sstevel@tonic-gate 2751*7c478bd9Sstevel@tonic-gate if (sbdp_unassign_board(hdp) != 0) { 2752*7c478bd9Sstevel@tonic-gate sbderror_t *ep = SBD_HD2ERR(hp); 2753*7c478bd9Sstevel@tonic-gate 2754*7c478bd9Sstevel@tonic-gate SBD_GET_PERR(hdp->h_err, ep); 2755*7c478bd9Sstevel@tonic-gate } 2756*7c478bd9Sstevel@tonic-gate 2757*7c478bd9Sstevel@tonic-gate SBD_INJECT_ERR(SBD_ASSIGN_BOARD_PSEUDO_ERR, hp->h_err, EIO, 2758*7c478bd9Sstevel@tonic-gate ESBD_INTERNAL, NULL); 2759*7c478bd9Sstevel@tonic-gate 2760*7c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 2761*7c478bd9Sstevel@tonic-gate } 2762*7c478bd9Sstevel@tonic-gate 2763*7c478bd9Sstevel@tonic-gate static void 2764*7c478bd9Sstevel@tonic-gate sbd_poweron_board(sbd_handle_t *hp) 2765*7c478bd9Sstevel@tonic-gate { 2766*7c478bd9Sstevel@tonic-gate sbd_board_t *sbp; 2767*7c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 2768*7c478bd9Sstevel@tonic-gate 2769*7c478bd9Sstevel@tonic-gate sbp = SBDH2BD(hp->h_sbd); 2770*7c478bd9Sstevel@tonic-gate 2771*7c478bd9Sstevel@tonic-gate PR_ALL("sbd_poweron_board: %d\n", sbp->sb_num); 2772*7c478bd9Sstevel@tonic-gate 2773*7c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 2774*7c478bd9Sstevel@tonic-gate 2775*7c478bd9Sstevel@tonic-gate if (sbdp_poweron_board(hdp) != 0) { 2776*7c478bd9Sstevel@tonic-gate sbderror_t *ep = SBD_HD2ERR(hp); 2777*7c478bd9Sstevel@tonic-gate 2778*7c478bd9Sstevel@tonic-gate SBD_GET_PERR(hdp->h_err, ep); 2779*7c478bd9Sstevel@tonic-gate } 2780*7c478bd9Sstevel@tonic-gate 2781*7c478bd9Sstevel@tonic-gate SBD_INJECT_ERR(SBD_POWERON_BOARD_PSEUDO_ERR, hp->h_err, EIO, 2782*7c478bd9Sstevel@tonic-gate ESBD_INTERNAL, NULL); 2783*7c478bd9Sstevel@tonic-gate 2784*7c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 2785*7c478bd9Sstevel@tonic-gate } 2786*7c478bd9Sstevel@tonic-gate 2787*7c478bd9Sstevel@tonic-gate static void 2788*7c478bd9Sstevel@tonic-gate sbd_poweroff_board(sbd_handle_t *hp) 2789*7c478bd9Sstevel@tonic-gate { 2790*7c478bd9Sstevel@tonic-gate sbd_board_t *sbp; 2791*7c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 2792*7c478bd9Sstevel@tonic-gate 2793*7c478bd9Sstevel@tonic-gate sbp = SBDH2BD(hp->h_sbd); 2794*7c478bd9Sstevel@tonic-gate 2795*7c478bd9Sstevel@tonic-gate PR_ALL("sbd_poweroff_board: %d\n", sbp->sb_num); 2796*7c478bd9Sstevel@tonic-gate 2797*7c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 2798*7c478bd9Sstevel@tonic-gate 2799*7c478bd9Sstevel@tonic-gate if (sbdp_poweroff_board(hdp) != 0) { 2800*7c478bd9Sstevel@tonic-gate sbderror_t *ep = SBD_HD2ERR(hp); 2801*7c478bd9Sstevel@tonic-gate 2802*7c478bd9Sstevel@tonic-gate SBD_GET_PERR(hdp->h_err, ep); 2803*7c478bd9Sstevel@tonic-gate } 2804*7c478bd9Sstevel@tonic-gate 2805*7c478bd9Sstevel@tonic-gate SBD_INJECT_ERR(SBD_POWEROFF_BOARD_PSEUDO_ERR, hp->h_err, EIO, 2806*7c478bd9Sstevel@tonic-gate ESBD_INTERNAL, NULL); 2807*7c478bd9Sstevel@tonic-gate 2808*7c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 2809*7c478bd9Sstevel@tonic-gate } 2810*7c478bd9Sstevel@tonic-gate 2811*7c478bd9Sstevel@tonic-gate 2812*7c478bd9Sstevel@tonic-gate /* 2813*7c478bd9Sstevel@tonic-gate * Return a list of the dip's of devices that are 2814*7c478bd9Sstevel@tonic-gate * either present and attached, or present only but 2815*7c478bd9Sstevel@tonic-gate * not yet attached for the given board. 2816*7c478bd9Sstevel@tonic-gate */ 2817*7c478bd9Sstevel@tonic-gate sbd_devlist_t * 2818*7c478bd9Sstevel@tonic-gate sbd_get_devlist(sbd_handle_t *hp, sbd_board_t *sbp, sbd_comp_type_t nodetype, 2819*7c478bd9Sstevel@tonic-gate int max_units, uint_t uset, int *count, int present_only) 2820*7c478bd9Sstevel@tonic-gate { 2821*7c478bd9Sstevel@tonic-gate int i, ix; 2822*7c478bd9Sstevel@tonic-gate sbd_devlist_t *ret_devlist; 2823*7c478bd9Sstevel@tonic-gate dev_info_t **devlist; 2824*7c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 2825*7c478bd9Sstevel@tonic-gate 2826*7c478bd9Sstevel@tonic-gate *count = 0; 2827*7c478bd9Sstevel@tonic-gate ret_devlist = GETSTRUCT(sbd_devlist_t, max_units); 2828*7c478bd9Sstevel@tonic-gate devlist = sbp->sb_devlist[NIX(nodetype)]; 2829*7c478bd9Sstevel@tonic-gate /* 2830*7c478bd9Sstevel@tonic-gate * Turn into binary value since we're going 2831*7c478bd9Sstevel@tonic-gate * to be using XOR for a comparison. 2832*7c478bd9Sstevel@tonic-gate * if (present_only) then 2833*7c478bd9Sstevel@tonic-gate * dev must be PRESENT, but NOT ATTACHED. 2834*7c478bd9Sstevel@tonic-gate * else 2835*7c478bd9Sstevel@tonic-gate * dev must be PRESENT AND ATTACHED. 2836*7c478bd9Sstevel@tonic-gate * endif 2837*7c478bd9Sstevel@tonic-gate */ 2838*7c478bd9Sstevel@tonic-gate if (present_only) 2839*7c478bd9Sstevel@tonic-gate present_only = 1; 2840*7c478bd9Sstevel@tonic-gate 2841*7c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 2842*7c478bd9Sstevel@tonic-gate 2843*7c478bd9Sstevel@tonic-gate for (i = ix = 0; (i < max_units) && uset; i++) { 2844*7c478bd9Sstevel@tonic-gate int ut, is_present, is_attached; 2845*7c478bd9Sstevel@tonic-gate dev_info_t *dip; 2846*7c478bd9Sstevel@tonic-gate sbderror_t *ep = SBD_HD2ERR(hp); 2847*7c478bd9Sstevel@tonic-gate int nunits, distance, j; 2848*7c478bd9Sstevel@tonic-gate 2849*7c478bd9Sstevel@tonic-gate /* 2850*7c478bd9Sstevel@tonic-gate * For CMPs, we would like to perform DR operation on 2851*7c478bd9Sstevel@tonic-gate * all the cores before moving onto the next chip. 2852*7c478bd9Sstevel@tonic-gate * Therefore, when constructing the devlist, we process 2853*7c478bd9Sstevel@tonic-gate * all the cores together. 2854*7c478bd9Sstevel@tonic-gate */ 2855*7c478bd9Sstevel@tonic-gate if (nodetype == SBD_COMP_CPU) { 2856*7c478bd9Sstevel@tonic-gate /* 2857*7c478bd9Sstevel@tonic-gate * Number of units to process in the inner loop 2858*7c478bd9Sstevel@tonic-gate */ 2859*7c478bd9Sstevel@tonic-gate nunits = MAX_CORES_PER_CMP; 2860*7c478bd9Sstevel@tonic-gate /* 2861*7c478bd9Sstevel@tonic-gate * The distance between the units in the 2862*7c478bd9Sstevel@tonic-gate * board's sb_devlist structure. 2863*7c478bd9Sstevel@tonic-gate */ 2864*7c478bd9Sstevel@tonic-gate distance = MAX_CMP_UNITS_PER_BOARD; 2865*7c478bd9Sstevel@tonic-gate } else { 2866*7c478bd9Sstevel@tonic-gate nunits = 1; 2867*7c478bd9Sstevel@tonic-gate distance = 0; 2868*7c478bd9Sstevel@tonic-gate } 2869*7c478bd9Sstevel@tonic-gate 2870*7c478bd9Sstevel@tonic-gate for (j = 0; j < nunits; j++) { 2871*7c478bd9Sstevel@tonic-gate if ((dip = devlist[i + j * distance]) == NULL) 2872*7c478bd9Sstevel@tonic-gate continue; 2873*7c478bd9Sstevel@tonic-gate 2874*7c478bd9Sstevel@tonic-gate ut = sbdp_get_unit_num(hdp, dip); 2875*7c478bd9Sstevel@tonic-gate 2876*7c478bd9Sstevel@tonic-gate if (ut == -1) { 2877*7c478bd9Sstevel@tonic-gate SBD_GET_PERR(hdp->h_err, ep); 2878*7c478bd9Sstevel@tonic-gate PR_ALL("sbd_get_devlist bad unit %d" 2879*7c478bd9Sstevel@tonic-gate " code %d errno %d", 2880*7c478bd9Sstevel@tonic-gate i, ep->e_code, ep->e_errno); 2881*7c478bd9Sstevel@tonic-gate } 2882*7c478bd9Sstevel@tonic-gate 2883*7c478bd9Sstevel@tonic-gate if ((uset & (1 << ut)) == 0) 2884*7c478bd9Sstevel@tonic-gate continue; 2885*7c478bd9Sstevel@tonic-gate uset &= ~(1 << ut); 2886*7c478bd9Sstevel@tonic-gate is_present = SBD_DEV_IS_PRESENT(sbp, nodetype, ut) ? 2887*7c478bd9Sstevel@tonic-gate 1 : 0; 2888*7c478bd9Sstevel@tonic-gate is_attached = SBD_DEV_IS_ATTACHED(sbp, nodetype, ut) ? 2889*7c478bd9Sstevel@tonic-gate 1 : 0; 2890*7c478bd9Sstevel@tonic-gate 2891*7c478bd9Sstevel@tonic-gate if (is_present && (present_only ^ is_attached)) { 2892*7c478bd9Sstevel@tonic-gate ret_devlist[ix].dv_dip = dip; 2893*7c478bd9Sstevel@tonic-gate sbd_init_err(&ret_devlist[ix].dv_error); 2894*7c478bd9Sstevel@tonic-gate ix++; 2895*7c478bd9Sstevel@tonic-gate } 2896*7c478bd9Sstevel@tonic-gate } 2897*7c478bd9Sstevel@tonic-gate } 2898*7c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 2899*7c478bd9Sstevel@tonic-gate 2900*7c478bd9Sstevel@tonic-gate if ((*count = ix) == 0) { 2901*7c478bd9Sstevel@tonic-gate FREESTRUCT(ret_devlist, sbd_devlist_t, max_units); 2902*7c478bd9Sstevel@tonic-gate ret_devlist = NULL; 2903*7c478bd9Sstevel@tonic-gate } 2904*7c478bd9Sstevel@tonic-gate 2905*7c478bd9Sstevel@tonic-gate return (ret_devlist); 2906*7c478bd9Sstevel@tonic-gate } 2907*7c478bd9Sstevel@tonic-gate 2908*7c478bd9Sstevel@tonic-gate static sbd_devlist_t * 2909*7c478bd9Sstevel@tonic-gate sbd_get_attach_devlist(sbd_handle_t *hp, int32_t *devnump, int32_t pass) 2910*7c478bd9Sstevel@tonic-gate { 2911*7c478bd9Sstevel@tonic-gate sbd_board_t *sbp; 2912*7c478bd9Sstevel@tonic-gate uint_t uset; 2913*7c478bd9Sstevel@tonic-gate sbd_devset_t devset; 2914*7c478bd9Sstevel@tonic-gate sbd_devlist_t *attach_devlist; 2915*7c478bd9Sstevel@tonic-gate static int next_pass = 1; 2916*7c478bd9Sstevel@tonic-gate static fn_t f = "sbd_get_attach_devlist"; 2917*7c478bd9Sstevel@tonic-gate 2918*7c478bd9Sstevel@tonic-gate PR_ALL("%s (pass = %d)...\n", f, pass); 2919*7c478bd9Sstevel@tonic-gate 2920*7c478bd9Sstevel@tonic-gate sbp = SBDH2BD(hp->h_sbd); 2921*7c478bd9Sstevel@tonic-gate devset = HD2MACHHD(hp)->sh_devset; 2922*7c478bd9Sstevel@tonic-gate 2923*7c478bd9Sstevel@tonic-gate *devnump = 0; 2924*7c478bd9Sstevel@tonic-gate attach_devlist = NULL; 2925*7c478bd9Sstevel@tonic-gate 2926*7c478bd9Sstevel@tonic-gate /* 2927*7c478bd9Sstevel@tonic-gate * We switch on next_pass for the cases where a board 2928*7c478bd9Sstevel@tonic-gate * does not contain a particular type of component. 2929*7c478bd9Sstevel@tonic-gate * In these situations we don't want to return NULL 2930*7c478bd9Sstevel@tonic-gate * prematurely. We need to check other devices and 2931*7c478bd9Sstevel@tonic-gate * we don't want to check the same type multiple times. 2932*7c478bd9Sstevel@tonic-gate * For example, if there were no cpus, then on pass 1 2933*7c478bd9Sstevel@tonic-gate * we would drop through and return the memory nodes. 2934*7c478bd9Sstevel@tonic-gate * However, on pass 2 we would switch back to the memory 2935*7c478bd9Sstevel@tonic-gate * nodes thereby returning them twice! Using next_pass 2936*7c478bd9Sstevel@tonic-gate * forces us down to the end (or next item). 2937*7c478bd9Sstevel@tonic-gate */ 2938*7c478bd9Sstevel@tonic-gate if (pass == 1) 2939*7c478bd9Sstevel@tonic-gate next_pass = 1; 2940*7c478bd9Sstevel@tonic-gate 2941*7c478bd9Sstevel@tonic-gate switch (next_pass) { 2942*7c478bd9Sstevel@tonic-gate case 1: 2943*7c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devset, SBD_COMP_CPU, DEVSET_ANYUNIT)) { 2944*7c478bd9Sstevel@tonic-gate uset = DEVSET_GET_UNITSET(devset, SBD_COMP_CPU); 2945*7c478bd9Sstevel@tonic-gate 2946*7c478bd9Sstevel@tonic-gate attach_devlist = sbd_get_devlist(hp, sbp, SBD_COMP_CPU, 2947*7c478bd9Sstevel@tonic-gate MAX_CPU_UNITS_PER_BOARD, 2948*7c478bd9Sstevel@tonic-gate uset, devnump, 1); 2949*7c478bd9Sstevel@tonic-gate 2950*7c478bd9Sstevel@tonic-gate DEVSET_DEL(devset, SBD_COMP_CPU, DEVSET_ANYUNIT); 2951*7c478bd9Sstevel@tonic-gate if (!devset || attach_devlist) { 2952*7c478bd9Sstevel@tonic-gate next_pass = 2; 2953*7c478bd9Sstevel@tonic-gate return (attach_devlist); 2954*7c478bd9Sstevel@tonic-gate } 2955*7c478bd9Sstevel@tonic-gate /* 2956*7c478bd9Sstevel@tonic-gate * If the caller is interested in the entire 2957*7c478bd9Sstevel@tonic-gate * board, but there aren't any cpus, then just 2958*7c478bd9Sstevel@tonic-gate * fall through to check for the next component. 2959*7c478bd9Sstevel@tonic-gate */ 2960*7c478bd9Sstevel@tonic-gate } 2961*7c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 2962*7c478bd9Sstevel@tonic-gate 2963*7c478bd9Sstevel@tonic-gate case 2: 2964*7c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devset, SBD_COMP_MEM, DEVSET_ANYUNIT)) { 2965*7c478bd9Sstevel@tonic-gate uset = DEVSET_GET_UNITSET(devset, SBD_COMP_MEM); 2966*7c478bd9Sstevel@tonic-gate 2967*7c478bd9Sstevel@tonic-gate attach_devlist = sbd_get_devlist(hp, sbp, SBD_COMP_MEM, 2968*7c478bd9Sstevel@tonic-gate MAX_MEM_UNITS_PER_BOARD, 2969*7c478bd9Sstevel@tonic-gate uset, devnump, 1); 2970*7c478bd9Sstevel@tonic-gate 2971*7c478bd9Sstevel@tonic-gate DEVSET_DEL(devset, SBD_COMP_MEM, DEVSET_ANYUNIT); 2972*7c478bd9Sstevel@tonic-gate if (!devset || attach_devlist) { 2973*7c478bd9Sstevel@tonic-gate next_pass = 3; 2974*7c478bd9Sstevel@tonic-gate return (attach_devlist); 2975*7c478bd9Sstevel@tonic-gate } 2976*7c478bd9Sstevel@tonic-gate /* 2977*7c478bd9Sstevel@tonic-gate * If the caller is interested in the entire 2978*7c478bd9Sstevel@tonic-gate * board, but there isn't any memory, then 2979*7c478bd9Sstevel@tonic-gate * just fall through to next component. 2980*7c478bd9Sstevel@tonic-gate */ 2981*7c478bd9Sstevel@tonic-gate } 2982*7c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 2983*7c478bd9Sstevel@tonic-gate 2984*7c478bd9Sstevel@tonic-gate 2985*7c478bd9Sstevel@tonic-gate case 3: 2986*7c478bd9Sstevel@tonic-gate next_pass = -1; 2987*7c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devset, SBD_COMP_IO, DEVSET_ANYUNIT)) { 2988*7c478bd9Sstevel@tonic-gate uset = DEVSET_GET_UNITSET(devset, SBD_COMP_IO); 2989*7c478bd9Sstevel@tonic-gate 2990*7c478bd9Sstevel@tonic-gate attach_devlist = sbd_get_devlist(hp, sbp, SBD_COMP_IO, 2991*7c478bd9Sstevel@tonic-gate MAX_IO_UNITS_PER_BOARD, 2992*7c478bd9Sstevel@tonic-gate uset, devnump, 1); 2993*7c478bd9Sstevel@tonic-gate 2994*7c478bd9Sstevel@tonic-gate DEVSET_DEL(devset, SBD_COMP_IO, DEVSET_ANYUNIT); 2995*7c478bd9Sstevel@tonic-gate if (!devset || attach_devlist) { 2996*7c478bd9Sstevel@tonic-gate next_pass = 4; 2997*7c478bd9Sstevel@tonic-gate return (attach_devlist); 2998*7c478bd9Sstevel@tonic-gate } 2999*7c478bd9Sstevel@tonic-gate } 3000*7c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 3001*7c478bd9Sstevel@tonic-gate 3002*7c478bd9Sstevel@tonic-gate default: 3003*7c478bd9Sstevel@tonic-gate *devnump = 0; 3004*7c478bd9Sstevel@tonic-gate return (NULL); 3005*7c478bd9Sstevel@tonic-gate } 3006*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 3007*7c478bd9Sstevel@tonic-gate } 3008*7c478bd9Sstevel@tonic-gate 3009*7c478bd9Sstevel@tonic-gate static int 3010*7c478bd9Sstevel@tonic-gate sbd_pre_attach_devlist(sbd_handle_t *hp, sbd_devlist_t *devlist, 3011*7c478bd9Sstevel@tonic-gate int32_t devnum) 3012*7c478bd9Sstevel@tonic-gate { 3013*7c478bd9Sstevel@tonic-gate int max_units = 0, rv = 0; 3014*7c478bd9Sstevel@tonic-gate sbd_comp_type_t nodetype; 3015*7c478bd9Sstevel@tonic-gate static fn_t f = "sbd_pre_attach_devlist"; 3016*7c478bd9Sstevel@tonic-gate 3017*7c478bd9Sstevel@tonic-gate /* 3018*7c478bd9Sstevel@tonic-gate * In this driver, all entries in a devlist[] are 3019*7c478bd9Sstevel@tonic-gate * of the same nodetype. 3020*7c478bd9Sstevel@tonic-gate */ 3021*7c478bd9Sstevel@tonic-gate nodetype = sbd_get_devtype(hp, devlist->dv_dip); 3022*7c478bd9Sstevel@tonic-gate 3023*7c478bd9Sstevel@tonic-gate PR_ALL("%s (nt = %s(%d), num = %d)...\n", 3024*7c478bd9Sstevel@tonic-gate f, sbd_ct_str[(int)nodetype], (int)nodetype, devnum); 3025*7c478bd9Sstevel@tonic-gate 3026*7c478bd9Sstevel@tonic-gate switch (nodetype) { 3027*7c478bd9Sstevel@tonic-gate 3028*7c478bd9Sstevel@tonic-gate case SBD_COMP_MEM: 3029*7c478bd9Sstevel@tonic-gate max_units = MAX_MEM_UNITS_PER_BOARD; 3030*7c478bd9Sstevel@tonic-gate rv = sbd_pre_attach_mem(hp, devlist, devnum); 3031*7c478bd9Sstevel@tonic-gate break; 3032*7c478bd9Sstevel@tonic-gate 3033*7c478bd9Sstevel@tonic-gate case SBD_COMP_CPU: 3034*7c478bd9Sstevel@tonic-gate max_units = MAX_CPU_UNITS_PER_BOARD; 3035*7c478bd9Sstevel@tonic-gate rv = sbd_pre_attach_cpu(hp, devlist, devnum); 3036*7c478bd9Sstevel@tonic-gate break; 3037*7c478bd9Sstevel@tonic-gate 3038*7c478bd9Sstevel@tonic-gate case SBD_COMP_IO: 3039*7c478bd9Sstevel@tonic-gate max_units = MAX_IO_UNITS_PER_BOARD; 3040*7c478bd9Sstevel@tonic-gate break; 3041*7c478bd9Sstevel@tonic-gate 3042*7c478bd9Sstevel@tonic-gate default: 3043*7c478bd9Sstevel@tonic-gate rv = -1; 3044*7c478bd9Sstevel@tonic-gate break; 3045*7c478bd9Sstevel@tonic-gate } 3046*7c478bd9Sstevel@tonic-gate 3047*7c478bd9Sstevel@tonic-gate if (rv && max_units) { 3048*7c478bd9Sstevel@tonic-gate int i; 3049*7c478bd9Sstevel@tonic-gate /* 3050*7c478bd9Sstevel@tonic-gate * Need to clean up devlist 3051*7c478bd9Sstevel@tonic-gate * if pre-op is going to fail. 3052*7c478bd9Sstevel@tonic-gate */ 3053*7c478bd9Sstevel@tonic-gate for (i = 0; i < max_units; i++) { 3054*7c478bd9Sstevel@tonic-gate if (SBD_GET_ERRSTR(&devlist[i].dv_error)) { 3055*7c478bd9Sstevel@tonic-gate SBD_FREE_ERR(&devlist[i].dv_error); 3056*7c478bd9Sstevel@tonic-gate } else { 3057*7c478bd9Sstevel@tonic-gate break; 3058*7c478bd9Sstevel@tonic-gate } 3059*7c478bd9Sstevel@tonic-gate } 3060*7c478bd9Sstevel@tonic-gate FREESTRUCT(devlist, sbd_devlist_t, max_units); 3061*7c478bd9Sstevel@tonic-gate } 3062*7c478bd9Sstevel@tonic-gate 3063*7c478bd9Sstevel@tonic-gate /* 3064*7c478bd9Sstevel@tonic-gate * If an error occurred, return "continue" 3065*7c478bd9Sstevel@tonic-gate * indication so that we can continue attaching 3066*7c478bd9Sstevel@tonic-gate * as much as possible. 3067*7c478bd9Sstevel@tonic-gate */ 3068*7c478bd9Sstevel@tonic-gate return (rv ? -1 : 0); 3069*7c478bd9Sstevel@tonic-gate } 3070*7c478bd9Sstevel@tonic-gate 3071*7c478bd9Sstevel@tonic-gate static int 3072*7c478bd9Sstevel@tonic-gate sbd_post_attach_devlist(sbd_handle_t *hp, sbd_devlist_t *devlist, 3073*7c478bd9Sstevel@tonic-gate int32_t devnum) 3074*7c478bd9Sstevel@tonic-gate { 3075*7c478bd9Sstevel@tonic-gate int i, max_units = 0, rv = 0; 3076*7c478bd9Sstevel@tonic-gate sbd_devset_t devs_unattached, devs_present; 3077*7c478bd9Sstevel@tonic-gate sbd_comp_type_t nodetype; 3078*7c478bd9Sstevel@tonic-gate sbd_board_t *sbp = SBDH2BD(hp->h_sbd); 3079*7c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 3080*7c478bd9Sstevel@tonic-gate static fn_t f = "sbd_post_attach_devlist"; 3081*7c478bd9Sstevel@tonic-gate 3082*7c478bd9Sstevel@tonic-gate sbp = SBDH2BD(hp->h_sbd); 3083*7c478bd9Sstevel@tonic-gate nodetype = sbd_get_devtype(hp, devlist->dv_dip); 3084*7c478bd9Sstevel@tonic-gate 3085*7c478bd9Sstevel@tonic-gate PR_ALL("%s (nt = %s(%d), num = %d)...\n", 3086*7c478bd9Sstevel@tonic-gate f, sbd_ct_str[(int)nodetype], (int)nodetype, devnum); 3087*7c478bd9Sstevel@tonic-gate 3088*7c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 3089*7c478bd9Sstevel@tonic-gate 3090*7c478bd9Sstevel@tonic-gate /* 3091*7c478bd9Sstevel@tonic-gate * Need to free up devlist[] created earlier in 3092*7c478bd9Sstevel@tonic-gate * sbd_get_attach_devlist(). 3093*7c478bd9Sstevel@tonic-gate */ 3094*7c478bd9Sstevel@tonic-gate switch (nodetype) { 3095*7c478bd9Sstevel@tonic-gate case SBD_COMP_CPU: 3096*7c478bd9Sstevel@tonic-gate max_units = MAX_CPU_UNITS_PER_BOARD; 3097*7c478bd9Sstevel@tonic-gate rv = sbd_post_attach_cpu(hp, devlist, devnum); 3098*7c478bd9Sstevel@tonic-gate break; 3099*7c478bd9Sstevel@tonic-gate 3100*7c478bd9Sstevel@tonic-gate 3101*7c478bd9Sstevel@tonic-gate case SBD_COMP_MEM: 3102*7c478bd9Sstevel@tonic-gate max_units = MAX_MEM_UNITS_PER_BOARD; 3103*7c478bd9Sstevel@tonic-gate 3104*7c478bd9Sstevel@tonic-gate rv = sbd_post_attach_mem(hp, devlist, devnum); 3105*7c478bd9Sstevel@tonic-gate break; 3106*7c478bd9Sstevel@tonic-gate 3107*7c478bd9Sstevel@tonic-gate case SBD_COMP_IO: 3108*7c478bd9Sstevel@tonic-gate max_units = MAX_IO_UNITS_PER_BOARD; 3109*7c478bd9Sstevel@tonic-gate break; 3110*7c478bd9Sstevel@tonic-gate 3111*7c478bd9Sstevel@tonic-gate default: 3112*7c478bd9Sstevel@tonic-gate rv = -1; 3113*7c478bd9Sstevel@tonic-gate break; 3114*7c478bd9Sstevel@tonic-gate } 3115*7c478bd9Sstevel@tonic-gate 3116*7c478bd9Sstevel@tonic-gate 3117*7c478bd9Sstevel@tonic-gate for (i = 0; i < devnum; i++) { 3118*7c478bd9Sstevel@tonic-gate int unit; 3119*7c478bd9Sstevel@tonic-gate dev_info_t *dip; 3120*7c478bd9Sstevel@tonic-gate sbderror_t *ep; 3121*7c478bd9Sstevel@tonic-gate 3122*7c478bd9Sstevel@tonic-gate ep = &devlist[i].dv_error; 3123*7c478bd9Sstevel@tonic-gate 3124*7c478bd9Sstevel@tonic-gate if (sbd_set_err_in_hdl(hp, ep) == 0) 3125*7c478bd9Sstevel@tonic-gate continue; 3126*7c478bd9Sstevel@tonic-gate 3127*7c478bd9Sstevel@tonic-gate dip = devlist[i].dv_dip; 3128*7c478bd9Sstevel@tonic-gate nodetype = sbd_get_devtype(hp, dip); 3129*7c478bd9Sstevel@tonic-gate unit = sbdp_get_unit_num(hdp, dip); 3130*7c478bd9Sstevel@tonic-gate 3131*7c478bd9Sstevel@tonic-gate if (unit == -1) { 3132*7c478bd9Sstevel@tonic-gate SBD_GET_PERR(hdp->h_err, ep); 3133*7c478bd9Sstevel@tonic-gate continue; 3134*7c478bd9Sstevel@tonic-gate } 3135*7c478bd9Sstevel@tonic-gate 3136*7c478bd9Sstevel@tonic-gate unit = sbd_check_unit_attached(sbp, dip, unit, nodetype, ep); 3137*7c478bd9Sstevel@tonic-gate 3138*7c478bd9Sstevel@tonic-gate if (unit == -1) { 3139*7c478bd9Sstevel@tonic-gate PR_ALL("%s: ERROR (nt=%s, b=%d, u=%d) not attached\n", 3140*7c478bd9Sstevel@tonic-gate f, sbd_ct_str[(int)nodetype], sbp->sb_num, i); 3141*7c478bd9Sstevel@tonic-gate continue; 3142*7c478bd9Sstevel@tonic-gate } 3143*7c478bd9Sstevel@tonic-gate 3144*7c478bd9Sstevel@tonic-gate SBD_DEV_SET_ATTACHED(sbp, nodetype, unit); 3145*7c478bd9Sstevel@tonic-gate SBD_DEVICE_TRANSITION(sbp, nodetype, unit, 3146*7c478bd9Sstevel@tonic-gate SBD_STATE_CONFIGURED); 3147*7c478bd9Sstevel@tonic-gate } 3148*7c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 3149*7c478bd9Sstevel@tonic-gate 3150*7c478bd9Sstevel@tonic-gate if (rv) { 3151*7c478bd9Sstevel@tonic-gate PR_ALL("%s: errno %d, ecode %d during attach\n", 3152*7c478bd9Sstevel@tonic-gate f, SBD_GET_ERRNO(SBD_HD2ERR(hp)), 3153*7c478bd9Sstevel@tonic-gate SBD_GET_ERR(HD2MACHERR(hp))); 3154*7c478bd9Sstevel@tonic-gate } 3155*7c478bd9Sstevel@tonic-gate 3156*7c478bd9Sstevel@tonic-gate devs_present = SBD_DEVS_PRESENT(sbp); 3157*7c478bd9Sstevel@tonic-gate devs_unattached = SBD_DEVS_UNATTACHED(sbp); 3158*7c478bd9Sstevel@tonic-gate 3159*7c478bd9Sstevel@tonic-gate switch (SBD_BOARD_STATE(sbp)) { 3160*7c478bd9Sstevel@tonic-gate case SBD_STATE_CONNECTED: 3161*7c478bd9Sstevel@tonic-gate case SBD_STATE_UNCONFIGURED: 3162*7c478bd9Sstevel@tonic-gate ASSERT(devs_present); 3163*7c478bd9Sstevel@tonic-gate 3164*7c478bd9Sstevel@tonic-gate if (devs_unattached == 0) { 3165*7c478bd9Sstevel@tonic-gate /* 3166*7c478bd9Sstevel@tonic-gate * All devices finally attached. 3167*7c478bd9Sstevel@tonic-gate */ 3168*7c478bd9Sstevel@tonic-gate SBD_BOARD_TRANSITION(sbp, SBD_STATE_CONFIGURED); 3169*7c478bd9Sstevel@tonic-gate sbp->sb_rstate = SBD_STAT_CONNECTED; 3170*7c478bd9Sstevel@tonic-gate sbp->sb_ostate = SBD_STAT_CONFIGURED; 3171*7c478bd9Sstevel@tonic-gate } else if (devs_present != devs_unattached) { 3172*7c478bd9Sstevel@tonic-gate /* 3173*7c478bd9Sstevel@tonic-gate * Only some devices are fully attached. 3174*7c478bd9Sstevel@tonic-gate */ 3175*7c478bd9Sstevel@tonic-gate SBD_BOARD_TRANSITION(sbp, SBD_STATE_PARTIAL); 3176*7c478bd9Sstevel@tonic-gate sbp->sb_rstate = SBD_STAT_CONNECTED; 3177*7c478bd9Sstevel@tonic-gate sbp->sb_ostate = SBD_STAT_UNCONFIGURED; 3178*7c478bd9Sstevel@tonic-gate } 3179*7c478bd9Sstevel@tonic-gate (void) drv_getparm(TIME, (void *)&sbp->sb_time); 3180*7c478bd9Sstevel@tonic-gate break; 3181*7c478bd9Sstevel@tonic-gate 3182*7c478bd9Sstevel@tonic-gate case SBD_STATE_PARTIAL: 3183*7c478bd9Sstevel@tonic-gate ASSERT(devs_present); 3184*7c478bd9Sstevel@tonic-gate /* 3185*7c478bd9Sstevel@tonic-gate * All devices finally attached. 3186*7c478bd9Sstevel@tonic-gate */ 3187*7c478bd9Sstevel@tonic-gate if (devs_unattached == 0) { 3188*7c478bd9Sstevel@tonic-gate SBD_BOARD_TRANSITION(sbp, SBD_STATE_CONFIGURED); 3189*7c478bd9Sstevel@tonic-gate sbp->sb_rstate = SBD_STAT_CONNECTED; 3190*7c478bd9Sstevel@tonic-gate sbp->sb_ostate = SBD_STAT_CONFIGURED; 3191*7c478bd9Sstevel@tonic-gate (void) drv_getparm(TIME, (void *)&sbp->sb_time); 3192*7c478bd9Sstevel@tonic-gate } 3193*7c478bd9Sstevel@tonic-gate break; 3194*7c478bd9Sstevel@tonic-gate 3195*7c478bd9Sstevel@tonic-gate default: 3196*7c478bd9Sstevel@tonic-gate break; 3197*7c478bd9Sstevel@tonic-gate } 3198*7c478bd9Sstevel@tonic-gate 3199*7c478bd9Sstevel@tonic-gate if (max_units && devlist) { 3200*7c478bd9Sstevel@tonic-gate int i; 3201*7c478bd9Sstevel@tonic-gate 3202*7c478bd9Sstevel@tonic-gate for (i = 0; i < max_units; i++) { 3203*7c478bd9Sstevel@tonic-gate if (SBD_GET_ERRSTR(&devlist[i].dv_error)) { 3204*7c478bd9Sstevel@tonic-gate SBD_FREE_ERR(&devlist[i].dv_error); 3205*7c478bd9Sstevel@tonic-gate } else { 3206*7c478bd9Sstevel@tonic-gate break; 3207*7c478bd9Sstevel@tonic-gate } 3208*7c478bd9Sstevel@tonic-gate } 3209*7c478bd9Sstevel@tonic-gate FREESTRUCT(devlist, sbd_devlist_t, max_units); 3210*7c478bd9Sstevel@tonic-gate } 3211*7c478bd9Sstevel@tonic-gate 3212*7c478bd9Sstevel@tonic-gate /* 3213*7c478bd9Sstevel@tonic-gate * Our policy is to attach all components that are 3214*7c478bd9Sstevel@tonic-gate * possible, thus we always return "success" on the 3215*7c478bd9Sstevel@tonic-gate * pre and post operations. 3216*7c478bd9Sstevel@tonic-gate */ 3217*7c478bd9Sstevel@tonic-gate return (0); 3218*7c478bd9Sstevel@tonic-gate } 3219*7c478bd9Sstevel@tonic-gate 3220*7c478bd9Sstevel@tonic-gate /* 3221*7c478bd9Sstevel@tonic-gate * We only need to "release" cpu and memory devices. 3222*7c478bd9Sstevel@tonic-gate */ 3223*7c478bd9Sstevel@tonic-gate static sbd_devlist_t * 3224*7c478bd9Sstevel@tonic-gate sbd_get_release_devlist(sbd_handle_t *hp, int32_t *devnump, int32_t pass) 3225*7c478bd9Sstevel@tonic-gate { 3226*7c478bd9Sstevel@tonic-gate sbd_board_t *sbp; 3227*7c478bd9Sstevel@tonic-gate uint_t uset; 3228*7c478bd9Sstevel@tonic-gate sbd_devset_t devset; 3229*7c478bd9Sstevel@tonic-gate sbd_devlist_t *release_devlist; 3230*7c478bd9Sstevel@tonic-gate static int next_pass = 1; 3231*7c478bd9Sstevel@tonic-gate static fn_t f = "sbd_get_release_devlist"; 3232*7c478bd9Sstevel@tonic-gate 3233*7c478bd9Sstevel@tonic-gate PR_ALL("%s (pass = %d)...\n", f, pass); 3234*7c478bd9Sstevel@tonic-gate 3235*7c478bd9Sstevel@tonic-gate sbp = SBDH2BD(hp->h_sbd); 3236*7c478bd9Sstevel@tonic-gate devset = HD2MACHHD(hp)->sh_devset; 3237*7c478bd9Sstevel@tonic-gate 3238*7c478bd9Sstevel@tonic-gate *devnump = 0; 3239*7c478bd9Sstevel@tonic-gate release_devlist = NULL; 3240*7c478bd9Sstevel@tonic-gate 3241*7c478bd9Sstevel@tonic-gate /* 3242*7c478bd9Sstevel@tonic-gate * We switch on next_pass for the cases where a board 3243*7c478bd9Sstevel@tonic-gate * does not contain a particular type of component. 3244*7c478bd9Sstevel@tonic-gate * In these situations we don't want to return NULL 3245*7c478bd9Sstevel@tonic-gate * prematurely. We need to check other devices and 3246*7c478bd9Sstevel@tonic-gate * we don't want to check the same type multiple times. 3247*7c478bd9Sstevel@tonic-gate * For example, if there were no cpus, then on pass 1 3248*7c478bd9Sstevel@tonic-gate * we would drop through and return the memory nodes. 3249*7c478bd9Sstevel@tonic-gate * However, on pass 2 we would switch back to the memory 3250*7c478bd9Sstevel@tonic-gate * nodes thereby returning them twice! Using next_pass 3251*7c478bd9Sstevel@tonic-gate * forces us down to the end (or next item). 3252*7c478bd9Sstevel@tonic-gate */ 3253*7c478bd9Sstevel@tonic-gate if (pass == 1) 3254*7c478bd9Sstevel@tonic-gate next_pass = 1; 3255*7c478bd9Sstevel@tonic-gate 3256*7c478bd9Sstevel@tonic-gate switch (next_pass) { 3257*7c478bd9Sstevel@tonic-gate case 1: 3258*7c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devset, SBD_COMP_MEM, DEVSET_ANYUNIT)) { 3259*7c478bd9Sstevel@tonic-gate uset = DEVSET_GET_UNITSET(devset, SBD_COMP_MEM); 3260*7c478bd9Sstevel@tonic-gate 3261*7c478bd9Sstevel@tonic-gate release_devlist = sbd_get_devlist(hp, sbp, 3262*7c478bd9Sstevel@tonic-gate SBD_COMP_MEM, 3263*7c478bd9Sstevel@tonic-gate MAX_MEM_UNITS_PER_BOARD, 3264*7c478bd9Sstevel@tonic-gate uset, devnump, 0); 3265*7c478bd9Sstevel@tonic-gate 3266*7c478bd9Sstevel@tonic-gate DEVSET_DEL(devset, SBD_COMP_MEM, DEVSET_ANYUNIT); 3267*7c478bd9Sstevel@tonic-gate if (!devset || release_devlist) { 3268*7c478bd9Sstevel@tonic-gate next_pass = 2; 3269*7c478bd9Sstevel@tonic-gate return (release_devlist); 3270*7c478bd9Sstevel@tonic-gate } 3271*7c478bd9Sstevel@tonic-gate /* 3272*7c478bd9Sstevel@tonic-gate * If the caller is interested in the entire 3273*7c478bd9Sstevel@tonic-gate * board, but there isn't any memory, then 3274*7c478bd9Sstevel@tonic-gate * just fall through to next component. 3275*7c478bd9Sstevel@tonic-gate */ 3276*7c478bd9Sstevel@tonic-gate } 3277*7c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 3278*7c478bd9Sstevel@tonic-gate 3279*7c478bd9Sstevel@tonic-gate 3280*7c478bd9Sstevel@tonic-gate case 2: 3281*7c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devset, SBD_COMP_CPU, DEVSET_ANYUNIT)) { 3282*7c478bd9Sstevel@tonic-gate uset = DEVSET_GET_UNITSET(devset, SBD_COMP_CPU); 3283*7c478bd9Sstevel@tonic-gate 3284*7c478bd9Sstevel@tonic-gate release_devlist = sbd_get_devlist(hp, sbp, 3285*7c478bd9Sstevel@tonic-gate SBD_COMP_CPU, 3286*7c478bd9Sstevel@tonic-gate MAX_CPU_UNITS_PER_BOARD, 3287*7c478bd9Sstevel@tonic-gate uset, devnump, 0); 3288*7c478bd9Sstevel@tonic-gate 3289*7c478bd9Sstevel@tonic-gate DEVSET_DEL(devset, SBD_COMP_CPU, DEVSET_ANYUNIT); 3290*7c478bd9Sstevel@tonic-gate if (!devset || release_devlist) { 3291*7c478bd9Sstevel@tonic-gate next_pass = 3; 3292*7c478bd9Sstevel@tonic-gate return (release_devlist); 3293*7c478bd9Sstevel@tonic-gate } 3294*7c478bd9Sstevel@tonic-gate /* 3295*7c478bd9Sstevel@tonic-gate * If the caller is interested in the entire 3296*7c478bd9Sstevel@tonic-gate * board, but there aren't any cpus, then just 3297*7c478bd9Sstevel@tonic-gate * fall through to check for the next component. 3298*7c478bd9Sstevel@tonic-gate */ 3299*7c478bd9Sstevel@tonic-gate } 3300*7c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 3301*7c478bd9Sstevel@tonic-gate 3302*7c478bd9Sstevel@tonic-gate 3303*7c478bd9Sstevel@tonic-gate case 3: 3304*7c478bd9Sstevel@tonic-gate next_pass = -1; 3305*7c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devset, SBD_COMP_IO, DEVSET_ANYUNIT)) { 3306*7c478bd9Sstevel@tonic-gate uset = DEVSET_GET_UNITSET(devset, SBD_COMP_IO); 3307*7c478bd9Sstevel@tonic-gate 3308*7c478bd9Sstevel@tonic-gate release_devlist = sbd_get_devlist(hp, sbp, 3309*7c478bd9Sstevel@tonic-gate SBD_COMP_IO, 3310*7c478bd9Sstevel@tonic-gate MAX_IO_UNITS_PER_BOARD, 3311*7c478bd9Sstevel@tonic-gate uset, devnump, 0); 3312*7c478bd9Sstevel@tonic-gate 3313*7c478bd9Sstevel@tonic-gate DEVSET_DEL(devset, SBD_COMP_IO, DEVSET_ANYUNIT); 3314*7c478bd9Sstevel@tonic-gate if (!devset || release_devlist) { 3315*7c478bd9Sstevel@tonic-gate next_pass = 4; 3316*7c478bd9Sstevel@tonic-gate return (release_devlist); 3317*7c478bd9Sstevel@tonic-gate } 3318*7c478bd9Sstevel@tonic-gate } 3319*7c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 3320*7c478bd9Sstevel@tonic-gate 3321*7c478bd9Sstevel@tonic-gate default: 3322*7c478bd9Sstevel@tonic-gate *devnump = 0; 3323*7c478bd9Sstevel@tonic-gate return (NULL); 3324*7c478bd9Sstevel@tonic-gate } 3325*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 3326*7c478bd9Sstevel@tonic-gate } 3327*7c478bd9Sstevel@tonic-gate 3328*7c478bd9Sstevel@tonic-gate static int 3329*7c478bd9Sstevel@tonic-gate sbd_pre_release_devlist(sbd_handle_t *hp, sbd_devlist_t *devlist, 3330*7c478bd9Sstevel@tonic-gate int32_t devnum) 3331*7c478bd9Sstevel@tonic-gate { 3332*7c478bd9Sstevel@tonic-gate int max_units = 0, rv = 0; 3333*7c478bd9Sstevel@tonic-gate sbd_comp_type_t nodetype; 3334*7c478bd9Sstevel@tonic-gate static fn_t f = "sbd_pre_release_devlist"; 3335*7c478bd9Sstevel@tonic-gate 3336*7c478bd9Sstevel@tonic-gate nodetype = sbd_get_devtype(hp, devlist->dv_dip); 3337*7c478bd9Sstevel@tonic-gate 3338*7c478bd9Sstevel@tonic-gate PR_ALL("%s (nt = %s(%d), num = %d)...\n", 3339*7c478bd9Sstevel@tonic-gate f, sbd_ct_str[(int)nodetype], (int)nodetype, devnum); 3340*7c478bd9Sstevel@tonic-gate 3341*7c478bd9Sstevel@tonic-gate switch (nodetype) { 3342*7c478bd9Sstevel@tonic-gate case SBD_COMP_CPU: { 3343*7c478bd9Sstevel@tonic-gate int i, mem_present = 0; 3344*7c478bd9Sstevel@tonic-gate sbd_board_t *sbp = SBDH2BD(hp->h_sbd); 3345*7c478bd9Sstevel@tonic-gate sbd_devset_t devset; 3346*7c478bd9Sstevel@tonic-gate sbd_priv_handle_t *shp = HD2MACHHD(hp); 3347*7c478bd9Sstevel@tonic-gate 3348*7c478bd9Sstevel@tonic-gate max_units = MAX_CPU_UNITS_PER_BOARD; 3349*7c478bd9Sstevel@tonic-gate 3350*7c478bd9Sstevel@tonic-gate devset = shp->sh_orig_devset; 3351*7c478bd9Sstevel@tonic-gate 3352*7c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_MEM_UNITS_PER_BOARD; i++) { 3353*7c478bd9Sstevel@tonic-gate /* 3354*7c478bd9Sstevel@tonic-gate * if client also requested to unconfigure memory 3355*7c478bd9Sstevel@tonic-gate * the we allow the operation. Therefore 3356*7c478bd9Sstevel@tonic-gate * we need to warranty that memory gets unconfig 3357*7c478bd9Sstevel@tonic-gate * before cpus 3358*7c478bd9Sstevel@tonic-gate */ 3359*7c478bd9Sstevel@tonic-gate 3360*7c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devset, SBD_COMP_MEM, i)) { 3361*7c478bd9Sstevel@tonic-gate continue; 3362*7c478bd9Sstevel@tonic-gate } 3363*7c478bd9Sstevel@tonic-gate if (SBD_DEV_IS_ATTACHED(sbp, SBD_COMP_MEM, i)) { 3364*7c478bd9Sstevel@tonic-gate mem_present = 1; 3365*7c478bd9Sstevel@tonic-gate break; 3366*7c478bd9Sstevel@tonic-gate } 3367*7c478bd9Sstevel@tonic-gate } 3368*7c478bd9Sstevel@tonic-gate if (mem_present) { 3369*7c478bd9Sstevel@tonic-gate sbderror_t *ep = SBD_HD2ERR(hp); 3370*7c478bd9Sstevel@tonic-gate SBD_SET_ERR(ep, ESBD_MEMONLINE); 3371*7c478bd9Sstevel@tonic-gate SBD_SET_ERRSTR(ep, sbp->sb_mempath[i]); 3372*7c478bd9Sstevel@tonic-gate rv = -1; 3373*7c478bd9Sstevel@tonic-gate } else { 3374*7c478bd9Sstevel@tonic-gate rv = sbd_pre_release_cpu(hp, devlist, devnum); 3375*7c478bd9Sstevel@tonic-gate } 3376*7c478bd9Sstevel@tonic-gate 3377*7c478bd9Sstevel@tonic-gate break; 3378*7c478bd9Sstevel@tonic-gate 3379*7c478bd9Sstevel@tonic-gate } 3380*7c478bd9Sstevel@tonic-gate case SBD_COMP_MEM: 3381*7c478bd9Sstevel@tonic-gate max_units = MAX_MEM_UNITS_PER_BOARD; 3382*7c478bd9Sstevel@tonic-gate rv = sbd_pre_release_mem(hp, devlist, devnum); 3383*7c478bd9Sstevel@tonic-gate break; 3384*7c478bd9Sstevel@tonic-gate 3385*7c478bd9Sstevel@tonic-gate 3386*7c478bd9Sstevel@tonic-gate case SBD_COMP_IO: 3387*7c478bd9Sstevel@tonic-gate max_units = MAX_IO_UNITS_PER_BOARD; 3388*7c478bd9Sstevel@tonic-gate rv = sbd_pre_release_io(hp, devlist, devnum); 3389*7c478bd9Sstevel@tonic-gate break; 3390*7c478bd9Sstevel@tonic-gate 3391*7c478bd9Sstevel@tonic-gate default: 3392*7c478bd9Sstevel@tonic-gate rv = -1; 3393*7c478bd9Sstevel@tonic-gate break; 3394*7c478bd9Sstevel@tonic-gate } 3395*7c478bd9Sstevel@tonic-gate 3396*7c478bd9Sstevel@tonic-gate if (rv && max_units) { 3397*7c478bd9Sstevel@tonic-gate int i; 3398*7c478bd9Sstevel@tonic-gate 3399*7c478bd9Sstevel@tonic-gate /* 3400*7c478bd9Sstevel@tonic-gate * the individual pre_release component routines should 3401*7c478bd9Sstevel@tonic-gate * have set the error in the handle. No need to set it 3402*7c478bd9Sstevel@tonic-gate * here 3403*7c478bd9Sstevel@tonic-gate * 3404*7c478bd9Sstevel@tonic-gate * Need to clean up dynamically allocated devlist 3405*7c478bd9Sstevel@tonic-gate * if pre-op is going to fail. 3406*7c478bd9Sstevel@tonic-gate */ 3407*7c478bd9Sstevel@tonic-gate for (i = 0; i < max_units; i++) { 3408*7c478bd9Sstevel@tonic-gate if (SBD_GET_ERRSTR(&devlist[i].dv_error)) { 3409*7c478bd9Sstevel@tonic-gate SBD_FREE_ERR(&devlist[i].dv_error); 3410*7c478bd9Sstevel@tonic-gate } else { 3411*7c478bd9Sstevel@tonic-gate break; 3412*7c478bd9Sstevel@tonic-gate } 3413*7c478bd9Sstevel@tonic-gate } 3414*7c478bd9Sstevel@tonic-gate FREESTRUCT(devlist, sbd_devlist_t, max_units); 3415*7c478bd9Sstevel@tonic-gate } 3416*7c478bd9Sstevel@tonic-gate 3417*7c478bd9Sstevel@tonic-gate return (rv ? -1 : 0); 3418*7c478bd9Sstevel@tonic-gate } 3419*7c478bd9Sstevel@tonic-gate 3420*7c478bd9Sstevel@tonic-gate static int 3421*7c478bd9Sstevel@tonic-gate sbd_post_release_devlist(sbd_handle_t *hp, sbd_devlist_t *devlist, 3422*7c478bd9Sstevel@tonic-gate int32_t devnum) 3423*7c478bd9Sstevel@tonic-gate { 3424*7c478bd9Sstevel@tonic-gate int i, max_units = 0; 3425*7c478bd9Sstevel@tonic-gate sbd_comp_type_t nodetype; 3426*7c478bd9Sstevel@tonic-gate sbd_board_t *sbp = SBDH2BD(hp->h_sbd); 3427*7c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 3428*7c478bd9Sstevel@tonic-gate sbd_error_t *spe; 3429*7c478bd9Sstevel@tonic-gate static fn_t f = "sbd_post_release_devlist"; 3430*7c478bd9Sstevel@tonic-gate 3431*7c478bd9Sstevel@tonic-gate nodetype = sbd_get_devtype(hp, devlist->dv_dip); 3432*7c478bd9Sstevel@tonic-gate ASSERT(nodetype >= SBD_COMP_CPU && nodetype <= SBD_COMP_IO); 3433*7c478bd9Sstevel@tonic-gate 3434*7c478bd9Sstevel@tonic-gate PR_ALL("%s (nt = %s(%d), num = %d)...\n", 3435*7c478bd9Sstevel@tonic-gate f, sbd_ct_str[(int)nodetype], (int)nodetype, devnum); 3436*7c478bd9Sstevel@tonic-gate 3437*7c478bd9Sstevel@tonic-gate /* 3438*7c478bd9Sstevel@tonic-gate * Need to free up devlist[] created earlier in 3439*7c478bd9Sstevel@tonic-gate * sbd_get_release_devlist(). 3440*7c478bd9Sstevel@tonic-gate */ 3441*7c478bd9Sstevel@tonic-gate switch (nodetype) { 3442*7c478bd9Sstevel@tonic-gate case SBD_COMP_CPU: 3443*7c478bd9Sstevel@tonic-gate max_units = MAX_CPU_UNITS_PER_BOARD; 3444*7c478bd9Sstevel@tonic-gate break; 3445*7c478bd9Sstevel@tonic-gate 3446*7c478bd9Sstevel@tonic-gate case SBD_COMP_MEM: 3447*7c478bd9Sstevel@tonic-gate max_units = MAX_MEM_UNITS_PER_BOARD; 3448*7c478bd9Sstevel@tonic-gate break; 3449*7c478bd9Sstevel@tonic-gate 3450*7c478bd9Sstevel@tonic-gate case SBD_COMP_IO: 3451*7c478bd9Sstevel@tonic-gate /* 3452*7c478bd9Sstevel@tonic-gate * Need to check if specific I/O is referenced and 3453*7c478bd9Sstevel@tonic-gate * fail post-op. 3454*7c478bd9Sstevel@tonic-gate */ 3455*7c478bd9Sstevel@tonic-gate 3456*7c478bd9Sstevel@tonic-gate if (sbd_check_io_refs(hp, devlist, devnum) > 0) { 3457*7c478bd9Sstevel@tonic-gate PR_IO("%s: error - I/O devices ref'd\n", f); 3458*7c478bd9Sstevel@tonic-gate } 3459*7c478bd9Sstevel@tonic-gate 3460*7c478bd9Sstevel@tonic-gate max_units = MAX_IO_UNITS_PER_BOARD; 3461*7c478bd9Sstevel@tonic-gate break; 3462*7c478bd9Sstevel@tonic-gate 3463*7c478bd9Sstevel@tonic-gate default: 3464*7c478bd9Sstevel@tonic-gate { 3465*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "%s: invalid nodetype (%d)", 3466*7c478bd9Sstevel@tonic-gate f, (int)nodetype); 3467*7c478bd9Sstevel@tonic-gate SBD_SET_ERR(HD2MACHERR(hp), ESBD_INVAL); 3468*7c478bd9Sstevel@tonic-gate } 3469*7c478bd9Sstevel@tonic-gate break; 3470*7c478bd9Sstevel@tonic-gate } 3471*7c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 3472*7c478bd9Sstevel@tonic-gate spe = hdp->h_err; 3473*7c478bd9Sstevel@tonic-gate 3474*7c478bd9Sstevel@tonic-gate for (i = 0; i < devnum; i++) { 3475*7c478bd9Sstevel@tonic-gate int unit; 3476*7c478bd9Sstevel@tonic-gate sbderror_t *ep; 3477*7c478bd9Sstevel@tonic-gate 3478*7c478bd9Sstevel@tonic-gate ep = &devlist[i].dv_error; 3479*7c478bd9Sstevel@tonic-gate 3480*7c478bd9Sstevel@tonic-gate if (sbd_set_err_in_hdl(hp, ep) == 0) { 3481*7c478bd9Sstevel@tonic-gate continue; 3482*7c478bd9Sstevel@tonic-gate } 3483*7c478bd9Sstevel@tonic-gate 3484*7c478bd9Sstevel@tonic-gate unit = sbdp_get_unit_num(hdp, devlist[i].dv_dip); 3485*7c478bd9Sstevel@tonic-gate if (unit == -1) { 3486*7c478bd9Sstevel@tonic-gate SBD_GET_PERR(hdp->h_err, SBD_HD2ERR(hp)); 3487*7c478bd9Sstevel@tonic-gate PR_ALL("%s bad unit num: %d code %d", 3488*7c478bd9Sstevel@tonic-gate f, unit, spe->e_code); 3489*7c478bd9Sstevel@tonic-gate continue; 3490*7c478bd9Sstevel@tonic-gate } 3491*7c478bd9Sstevel@tonic-gate } 3492*7c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 3493*7c478bd9Sstevel@tonic-gate 3494*7c478bd9Sstevel@tonic-gate if (SBD_GET_ERRNO(SBD_HD2ERR(hp))) { 3495*7c478bd9Sstevel@tonic-gate PR_ALL("%s: errno %d, ecode %d during release\n", 3496*7c478bd9Sstevel@tonic-gate f, SBD_GET_ERRNO(SBD_HD2ERR(hp)), 3497*7c478bd9Sstevel@tonic-gate SBD_GET_ERR(SBD_HD2ERR(hp))); 3498*7c478bd9Sstevel@tonic-gate } 3499*7c478bd9Sstevel@tonic-gate 3500*7c478bd9Sstevel@tonic-gate if (max_units && devlist) { 3501*7c478bd9Sstevel@tonic-gate int i; 3502*7c478bd9Sstevel@tonic-gate 3503*7c478bd9Sstevel@tonic-gate for (i = 0; i < max_units; i++) { 3504*7c478bd9Sstevel@tonic-gate if (SBD_GET_ERRSTR(&devlist[i].dv_error)) { 3505*7c478bd9Sstevel@tonic-gate SBD_FREE_ERR(&devlist[i].dv_error); 3506*7c478bd9Sstevel@tonic-gate } else { 3507*7c478bd9Sstevel@tonic-gate break; 3508*7c478bd9Sstevel@tonic-gate } 3509*7c478bd9Sstevel@tonic-gate } 3510*7c478bd9Sstevel@tonic-gate FREESTRUCT(devlist, sbd_devlist_t, max_units); 3511*7c478bd9Sstevel@tonic-gate } 3512*7c478bd9Sstevel@tonic-gate 3513*7c478bd9Sstevel@tonic-gate return (SBD_GET_ERRNO(SBD_HD2ERR(hp)) ? -1 : 0); 3514*7c478bd9Sstevel@tonic-gate } 3515*7c478bd9Sstevel@tonic-gate 3516*7c478bd9Sstevel@tonic-gate static void 3517*7c478bd9Sstevel@tonic-gate sbd_release_dev_done(sbd_board_t *sbp, sbd_comp_type_t nodetype, int unit) 3518*7c478bd9Sstevel@tonic-gate { 3519*7c478bd9Sstevel@tonic-gate SBD_DEV_SET_UNREFERENCED(sbp, nodetype, unit); 3520*7c478bd9Sstevel@tonic-gate SBD_DEVICE_TRANSITION(sbp, nodetype, unit, SBD_STATE_UNREFERENCED); 3521*7c478bd9Sstevel@tonic-gate } 3522*7c478bd9Sstevel@tonic-gate 3523*7c478bd9Sstevel@tonic-gate static void 3524*7c478bd9Sstevel@tonic-gate sbd_release_done(sbd_handle_t *hp, sbd_comp_type_t nodetype, dev_info_t *dip) 3525*7c478bd9Sstevel@tonic-gate { 3526*7c478bd9Sstevel@tonic-gate int unit; 3527*7c478bd9Sstevel@tonic-gate sbd_board_t *sbp = SBDH2BD(hp->h_sbd); 3528*7c478bd9Sstevel@tonic-gate sbderror_t *ep; 3529*7c478bd9Sstevel@tonic-gate static fn_t f = "sbd_release_done"; 3530*7c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 3531*7c478bd9Sstevel@tonic-gate 3532*7c478bd9Sstevel@tonic-gate PR_ALL("%s...\n", f); 3533*7c478bd9Sstevel@tonic-gate 3534*7c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 3535*7c478bd9Sstevel@tonic-gate ep = SBD_HD2ERR(hp); 3536*7c478bd9Sstevel@tonic-gate 3537*7c478bd9Sstevel@tonic-gate if ((unit = sbdp_get_unit_num(hdp, dip)) < 0) { 3538*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 3539*7c478bd9Sstevel@tonic-gate "sbd:%s: unable to get unit for dip (0x%p)", 3540*7c478bd9Sstevel@tonic-gate f, (void *)dip); 3541*7c478bd9Sstevel@tonic-gate SBD_GET_PERR(hdp->h_err, ep); 3542*7c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 3543*7c478bd9Sstevel@tonic-gate return; 3544*7c478bd9Sstevel@tonic-gate } 3545*7c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 3546*7c478bd9Sstevel@tonic-gate 3547*7c478bd9Sstevel@tonic-gate /* 3548*7c478bd9Sstevel@tonic-gate * Transfer the device which just completed its release 3549*7c478bd9Sstevel@tonic-gate * to the UNREFERENCED state. 3550*7c478bd9Sstevel@tonic-gate */ 3551*7c478bd9Sstevel@tonic-gate switch (nodetype) { 3552*7c478bd9Sstevel@tonic-gate 3553*7c478bd9Sstevel@tonic-gate case SBD_COMP_MEM: 3554*7c478bd9Sstevel@tonic-gate sbd_release_mem_done((void *)hp, unit); 3555*7c478bd9Sstevel@tonic-gate break; 3556*7c478bd9Sstevel@tonic-gate 3557*7c478bd9Sstevel@tonic-gate default: 3558*7c478bd9Sstevel@tonic-gate sbd_release_dev_done(sbp, nodetype, unit); 3559*7c478bd9Sstevel@tonic-gate break; 3560*7c478bd9Sstevel@tonic-gate } 3561*7c478bd9Sstevel@tonic-gate 3562*7c478bd9Sstevel@tonic-gate /* 3563*7c478bd9Sstevel@tonic-gate * If the entire board was released and all components 3564*7c478bd9Sstevel@tonic-gate * unreferenced then transfer it to the UNREFERENCED state. 3565*7c478bd9Sstevel@tonic-gate */ 3566*7c478bd9Sstevel@tonic-gate if (SBD_DEVS_RELEASED(sbp) == SBD_DEVS_UNREFERENCED(sbp)) { 3567*7c478bd9Sstevel@tonic-gate SBD_BOARD_TRANSITION(sbp, SBD_STATE_UNREFERENCED); 3568*7c478bd9Sstevel@tonic-gate (void) drv_getparm(TIME, (void *)&sbp->sb_time); 3569*7c478bd9Sstevel@tonic-gate } 3570*7c478bd9Sstevel@tonic-gate } 3571*7c478bd9Sstevel@tonic-gate 3572*7c478bd9Sstevel@tonic-gate static sbd_devlist_t * 3573*7c478bd9Sstevel@tonic-gate sbd_get_detach_devlist(sbd_handle_t *hp, int32_t *devnump, int32_t pass) 3574*7c478bd9Sstevel@tonic-gate { 3575*7c478bd9Sstevel@tonic-gate sbd_board_t *sbp; 3576*7c478bd9Sstevel@tonic-gate uint_t uset; 3577*7c478bd9Sstevel@tonic-gate sbd_devset_t devset; 3578*7c478bd9Sstevel@tonic-gate sbd_devlist_t *detach_devlist; 3579*7c478bd9Sstevel@tonic-gate static int next_pass = 1; 3580*7c478bd9Sstevel@tonic-gate static fn_t f = "sbd_get_detach_devlist"; 3581*7c478bd9Sstevel@tonic-gate 3582*7c478bd9Sstevel@tonic-gate PR_ALL("%s (pass = %d)...\n", f, pass); 3583*7c478bd9Sstevel@tonic-gate 3584*7c478bd9Sstevel@tonic-gate sbp = SBDH2BD(hp->h_sbd); 3585*7c478bd9Sstevel@tonic-gate devset = HD2MACHHD(hp)->sh_devset; 3586*7c478bd9Sstevel@tonic-gate 3587*7c478bd9Sstevel@tonic-gate *devnump = 0; 3588*7c478bd9Sstevel@tonic-gate detach_devlist = NULL; 3589*7c478bd9Sstevel@tonic-gate 3590*7c478bd9Sstevel@tonic-gate /* 3591*7c478bd9Sstevel@tonic-gate * We switch on next_pass for the cases where a board 3592*7c478bd9Sstevel@tonic-gate * does not contain a particular type of component. 3593*7c478bd9Sstevel@tonic-gate * In these situations we don't want to return NULL 3594*7c478bd9Sstevel@tonic-gate * prematurely. We need to check other devices and 3595*7c478bd9Sstevel@tonic-gate * we don't want to check the same type multiple times. 3596*7c478bd9Sstevel@tonic-gate * For example, if there were no cpus, then on pass 1 3597*7c478bd9Sstevel@tonic-gate * we would drop through and return the memory nodes. 3598*7c478bd9Sstevel@tonic-gate * However, on pass 2 we would switch back to the memory 3599*7c478bd9Sstevel@tonic-gate * nodes thereby returning them twice! Using next_pass 3600*7c478bd9Sstevel@tonic-gate * forces us down to the end (or next item). 3601*7c478bd9Sstevel@tonic-gate */ 3602*7c478bd9Sstevel@tonic-gate if (pass == 1) 3603*7c478bd9Sstevel@tonic-gate next_pass = 1; 3604*7c478bd9Sstevel@tonic-gate 3605*7c478bd9Sstevel@tonic-gate switch (next_pass) { 3606*7c478bd9Sstevel@tonic-gate case 1: 3607*7c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devset, SBD_COMP_MEM, DEVSET_ANYUNIT)) { 3608*7c478bd9Sstevel@tonic-gate uset = DEVSET_GET_UNITSET(devset, SBD_COMP_MEM); 3609*7c478bd9Sstevel@tonic-gate 3610*7c478bd9Sstevel@tonic-gate detach_devlist = sbd_get_devlist(hp, sbp, 3611*7c478bd9Sstevel@tonic-gate SBD_COMP_MEM, 3612*7c478bd9Sstevel@tonic-gate MAX_MEM_UNITS_PER_BOARD, 3613*7c478bd9Sstevel@tonic-gate uset, devnump, 0); 3614*7c478bd9Sstevel@tonic-gate 3615*7c478bd9Sstevel@tonic-gate DEVSET_DEL(devset, SBD_COMP_MEM, DEVSET_ANYUNIT); 3616*7c478bd9Sstevel@tonic-gate if (!devset || detach_devlist) { 3617*7c478bd9Sstevel@tonic-gate next_pass = 2; 3618*7c478bd9Sstevel@tonic-gate return (detach_devlist); 3619*7c478bd9Sstevel@tonic-gate } 3620*7c478bd9Sstevel@tonic-gate /* 3621*7c478bd9Sstevel@tonic-gate * If the caller is interested in the entire 3622*7c478bd9Sstevel@tonic-gate * board, but there isn't any memory, then 3623*7c478bd9Sstevel@tonic-gate * just fall through to next component. 3624*7c478bd9Sstevel@tonic-gate */ 3625*7c478bd9Sstevel@tonic-gate } 3626*7c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 3627*7c478bd9Sstevel@tonic-gate 3628*7c478bd9Sstevel@tonic-gate case 2: 3629*7c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devset, SBD_COMP_CPU, DEVSET_ANYUNIT)) { 3630*7c478bd9Sstevel@tonic-gate uset = DEVSET_GET_UNITSET(devset, SBD_COMP_CPU); 3631*7c478bd9Sstevel@tonic-gate 3632*7c478bd9Sstevel@tonic-gate detach_devlist = sbd_get_devlist(hp, sbp, 3633*7c478bd9Sstevel@tonic-gate SBD_COMP_CPU, 3634*7c478bd9Sstevel@tonic-gate MAX_CPU_UNITS_PER_BOARD, 3635*7c478bd9Sstevel@tonic-gate uset, devnump, 0); 3636*7c478bd9Sstevel@tonic-gate 3637*7c478bd9Sstevel@tonic-gate DEVSET_DEL(devset, SBD_COMP_CPU, DEVSET_ANYUNIT); 3638*7c478bd9Sstevel@tonic-gate if (!devset || detach_devlist) { 3639*7c478bd9Sstevel@tonic-gate next_pass = 2; 3640*7c478bd9Sstevel@tonic-gate return (detach_devlist); 3641*7c478bd9Sstevel@tonic-gate } 3642*7c478bd9Sstevel@tonic-gate /* 3643*7c478bd9Sstevel@tonic-gate * If the caller is interested in the entire 3644*7c478bd9Sstevel@tonic-gate * board, but there aren't any cpus, then just 3645*7c478bd9Sstevel@tonic-gate * fall through to check for the next component. 3646*7c478bd9Sstevel@tonic-gate */ 3647*7c478bd9Sstevel@tonic-gate } 3648*7c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 3649*7c478bd9Sstevel@tonic-gate 3650*7c478bd9Sstevel@tonic-gate case 3: 3651*7c478bd9Sstevel@tonic-gate next_pass = -1; 3652*7c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devset, SBD_COMP_IO, DEVSET_ANYUNIT)) { 3653*7c478bd9Sstevel@tonic-gate uset = DEVSET_GET_UNITSET(devset, SBD_COMP_IO); 3654*7c478bd9Sstevel@tonic-gate 3655*7c478bd9Sstevel@tonic-gate detach_devlist = sbd_get_devlist(hp, sbp, 3656*7c478bd9Sstevel@tonic-gate SBD_COMP_IO, 3657*7c478bd9Sstevel@tonic-gate MAX_IO_UNITS_PER_BOARD, 3658*7c478bd9Sstevel@tonic-gate uset, devnump, 0); 3659*7c478bd9Sstevel@tonic-gate 3660*7c478bd9Sstevel@tonic-gate DEVSET_DEL(devset, SBD_COMP_IO, DEVSET_ANYUNIT); 3661*7c478bd9Sstevel@tonic-gate if (!devset || detach_devlist) { 3662*7c478bd9Sstevel@tonic-gate next_pass = 4; 3663*7c478bd9Sstevel@tonic-gate return (detach_devlist); 3664*7c478bd9Sstevel@tonic-gate } 3665*7c478bd9Sstevel@tonic-gate } 3666*7c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 3667*7c478bd9Sstevel@tonic-gate 3668*7c478bd9Sstevel@tonic-gate default: 3669*7c478bd9Sstevel@tonic-gate *devnump = 0; 3670*7c478bd9Sstevel@tonic-gate return (NULL); 3671*7c478bd9Sstevel@tonic-gate } 3672*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 3673*7c478bd9Sstevel@tonic-gate } 3674*7c478bd9Sstevel@tonic-gate 3675*7c478bd9Sstevel@tonic-gate static int 3676*7c478bd9Sstevel@tonic-gate sbd_pre_detach_devlist(sbd_handle_t *hp, sbd_devlist_t *devlist, 3677*7c478bd9Sstevel@tonic-gate int32_t devnum) 3678*7c478bd9Sstevel@tonic-gate { 3679*7c478bd9Sstevel@tonic-gate int rv = 0; 3680*7c478bd9Sstevel@tonic-gate sbd_comp_type_t nodetype; 3681*7c478bd9Sstevel@tonic-gate static fn_t f = "sbd_pre_detach_devlist"; 3682*7c478bd9Sstevel@tonic-gate 3683*7c478bd9Sstevel@tonic-gate nodetype = sbd_get_devtype(hp, devlist->dv_dip); 3684*7c478bd9Sstevel@tonic-gate 3685*7c478bd9Sstevel@tonic-gate PR_ALL("%s (nt = %s(%d), num = %d)...\n", 3686*7c478bd9Sstevel@tonic-gate f, sbd_ct_str[(int)nodetype], (int)nodetype, devnum); 3687*7c478bd9Sstevel@tonic-gate 3688*7c478bd9Sstevel@tonic-gate switch (nodetype) { 3689*7c478bd9Sstevel@tonic-gate case SBD_COMP_CPU: 3690*7c478bd9Sstevel@tonic-gate rv = sbd_pre_detach_cpu(hp, devlist, devnum); 3691*7c478bd9Sstevel@tonic-gate break; 3692*7c478bd9Sstevel@tonic-gate 3693*7c478bd9Sstevel@tonic-gate case SBD_COMP_MEM: 3694*7c478bd9Sstevel@tonic-gate rv = sbd_pre_detach_mem(hp, devlist, devnum); 3695*7c478bd9Sstevel@tonic-gate break; 3696*7c478bd9Sstevel@tonic-gate 3697*7c478bd9Sstevel@tonic-gate case SBD_COMP_IO: 3698*7c478bd9Sstevel@tonic-gate rv = sbd_pre_detach_io(hp, devlist, devnum); 3699*7c478bd9Sstevel@tonic-gate break; 3700*7c478bd9Sstevel@tonic-gate 3701*7c478bd9Sstevel@tonic-gate default: 3702*7c478bd9Sstevel@tonic-gate rv = -1; 3703*7c478bd9Sstevel@tonic-gate break; 3704*7c478bd9Sstevel@tonic-gate } 3705*7c478bd9Sstevel@tonic-gate 3706*7c478bd9Sstevel@tonic-gate /* 3707*7c478bd9Sstevel@tonic-gate * We want to continue attempting to detach 3708*7c478bd9Sstevel@tonic-gate * other components. 3709*7c478bd9Sstevel@tonic-gate */ 3710*7c478bd9Sstevel@tonic-gate return (rv); 3711*7c478bd9Sstevel@tonic-gate } 3712*7c478bd9Sstevel@tonic-gate 3713*7c478bd9Sstevel@tonic-gate static int 3714*7c478bd9Sstevel@tonic-gate sbd_post_detach_devlist(sbd_handle_t *hp, sbd_devlist_t *devlist, 3715*7c478bd9Sstevel@tonic-gate int32_t devnum) 3716*7c478bd9Sstevel@tonic-gate { 3717*7c478bd9Sstevel@tonic-gate int i, max_units = 0, rv = 0; 3718*7c478bd9Sstevel@tonic-gate sbd_comp_type_t nodetype; 3719*7c478bd9Sstevel@tonic-gate sbd_board_t *sbp; 3720*7c478bd9Sstevel@tonic-gate sbd_istate_t bstate; 3721*7c478bd9Sstevel@tonic-gate static fn_t f = "sbd_post_detach_devlist"; 3722*7c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 3723*7c478bd9Sstevel@tonic-gate 3724*7c478bd9Sstevel@tonic-gate sbp = SBDH2BD(hp->h_sbd); 3725*7c478bd9Sstevel@tonic-gate nodetype = sbd_get_devtype(hp, devlist->dv_dip); 3726*7c478bd9Sstevel@tonic-gate 3727*7c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 3728*7c478bd9Sstevel@tonic-gate 3729*7c478bd9Sstevel@tonic-gate PR_ALL("%s (nt = %s(%d), num = %d)...\n", 3730*7c478bd9Sstevel@tonic-gate f, sbd_ct_str[(int)nodetype], (int)nodetype, devnum); 3731*7c478bd9Sstevel@tonic-gate 3732*7c478bd9Sstevel@tonic-gate /* 3733*7c478bd9Sstevel@tonic-gate * Need to free up devlist[] created earlier in 3734*7c478bd9Sstevel@tonic-gate * sbd_get_detach_devlist(). 3735*7c478bd9Sstevel@tonic-gate */ 3736*7c478bd9Sstevel@tonic-gate switch (nodetype) { 3737*7c478bd9Sstevel@tonic-gate case SBD_COMP_CPU: 3738*7c478bd9Sstevel@tonic-gate max_units = MAX_CPU_UNITS_PER_BOARD; 3739*7c478bd9Sstevel@tonic-gate rv = sbd_post_detach_cpu(hp, devlist, devnum); 3740*7c478bd9Sstevel@tonic-gate break; 3741*7c478bd9Sstevel@tonic-gate 3742*7c478bd9Sstevel@tonic-gate case SBD_COMP_MEM: 3743*7c478bd9Sstevel@tonic-gate max_units = MAX_MEM_UNITS_PER_BOARD; 3744*7c478bd9Sstevel@tonic-gate rv = sbd_post_detach_mem(hp, devlist, devnum); 3745*7c478bd9Sstevel@tonic-gate break; 3746*7c478bd9Sstevel@tonic-gate 3747*7c478bd9Sstevel@tonic-gate case SBD_COMP_IO: 3748*7c478bd9Sstevel@tonic-gate max_units = MAX_IO_UNITS_PER_BOARD; 3749*7c478bd9Sstevel@tonic-gate rv = sbd_post_detach_io(hp, devlist, devnum); 3750*7c478bd9Sstevel@tonic-gate break; 3751*7c478bd9Sstevel@tonic-gate 3752*7c478bd9Sstevel@tonic-gate default: 3753*7c478bd9Sstevel@tonic-gate rv = -1; 3754*7c478bd9Sstevel@tonic-gate break; 3755*7c478bd9Sstevel@tonic-gate } 3756*7c478bd9Sstevel@tonic-gate 3757*7c478bd9Sstevel@tonic-gate 3758*7c478bd9Sstevel@tonic-gate for (i = 0; i < devnum; i++) { 3759*7c478bd9Sstevel@tonic-gate int unit; 3760*7c478bd9Sstevel@tonic-gate sbderror_t *ep; 3761*7c478bd9Sstevel@tonic-gate dev_info_t *dip; 3762*7c478bd9Sstevel@tonic-gate 3763*7c478bd9Sstevel@tonic-gate ep = &devlist[i].dv_error; 3764*7c478bd9Sstevel@tonic-gate 3765*7c478bd9Sstevel@tonic-gate if (sbd_set_err_in_hdl(hp, ep) == 0) 3766*7c478bd9Sstevel@tonic-gate continue; 3767*7c478bd9Sstevel@tonic-gate 3768*7c478bd9Sstevel@tonic-gate dip = devlist[i].dv_dip; 3769*7c478bd9Sstevel@tonic-gate unit = sbdp_get_unit_num(hdp, dip); 3770*7c478bd9Sstevel@tonic-gate if (unit == -1) { 3771*7c478bd9Sstevel@tonic-gate if (hp->h_flags & SBD_IOCTL_FLAG_FORCE) 3772*7c478bd9Sstevel@tonic-gate continue; 3773*7c478bd9Sstevel@tonic-gate else { 3774*7c478bd9Sstevel@tonic-gate SBD_GET_PERR(hdp->h_err, ep); 3775*7c478bd9Sstevel@tonic-gate break; 3776*7c478bd9Sstevel@tonic-gate } 3777*7c478bd9Sstevel@tonic-gate } 3778*7c478bd9Sstevel@tonic-gate nodetype = sbd_get_devtype(hp, dip); 3779*7c478bd9Sstevel@tonic-gate 3780*7c478bd9Sstevel@tonic-gate if (sbd_check_unit_attached(sbp, dip, unit, nodetype, 3781*7c478bd9Sstevel@tonic-gate ep) >= 0) { 3782*7c478bd9Sstevel@tonic-gate /* 3783*7c478bd9Sstevel@tonic-gate * Device is still attached probably due 3784*7c478bd9Sstevel@tonic-gate * to an error. Need to keep track of it. 3785*7c478bd9Sstevel@tonic-gate */ 3786*7c478bd9Sstevel@tonic-gate PR_ALL("%s: ERROR (nt=%s, b=%d, u=%d) not detached\n", 3787*7c478bd9Sstevel@tonic-gate f, sbd_ct_str[(int)nodetype], sbp->sb_num, 3788*7c478bd9Sstevel@tonic-gate unit); 3789*7c478bd9Sstevel@tonic-gate continue; 3790*7c478bd9Sstevel@tonic-gate } 3791*7c478bd9Sstevel@tonic-gate 3792*7c478bd9Sstevel@tonic-gate SBD_DEV_CLR_ATTACHED(sbp, nodetype, unit); 3793*7c478bd9Sstevel@tonic-gate SBD_DEV_CLR_RELEASED(sbp, nodetype, unit); 3794*7c478bd9Sstevel@tonic-gate SBD_DEV_CLR_UNREFERENCED(sbp, nodetype, unit); 3795*7c478bd9Sstevel@tonic-gate SBD_DEVICE_TRANSITION(sbp, nodetype, unit, 3796*7c478bd9Sstevel@tonic-gate SBD_STATE_UNCONFIGURED); 3797*7c478bd9Sstevel@tonic-gate } 3798*7c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 3799*7c478bd9Sstevel@tonic-gate 3800*7c478bd9Sstevel@tonic-gate bstate = SBD_BOARD_STATE(sbp); 3801*7c478bd9Sstevel@tonic-gate if (bstate != SBD_STATE_UNCONFIGURED) { 3802*7c478bd9Sstevel@tonic-gate if (SBD_DEVS_PRESENT(sbp) == SBD_DEVS_UNATTACHED(sbp)) { 3803*7c478bd9Sstevel@tonic-gate /* 3804*7c478bd9Sstevel@tonic-gate * All devices are finally detached. 3805*7c478bd9Sstevel@tonic-gate */ 3806*7c478bd9Sstevel@tonic-gate SBD_BOARD_TRANSITION(sbp, SBD_STATE_UNCONFIGURED); 3807*7c478bd9Sstevel@tonic-gate } else if ((SBD_BOARD_STATE(sbp) != SBD_STATE_PARTIAL) && 3808*7c478bd9Sstevel@tonic-gate SBD_DEVS_ATTACHED(sbp)) { 3809*7c478bd9Sstevel@tonic-gate /* 3810*7c478bd9Sstevel@tonic-gate * Some devices remain attached. 3811*7c478bd9Sstevel@tonic-gate */ 3812*7c478bd9Sstevel@tonic-gate SBD_BOARD_TRANSITION(sbp, SBD_STATE_PARTIAL); 3813*7c478bd9Sstevel@tonic-gate } 3814*7c478bd9Sstevel@tonic-gate } 3815*7c478bd9Sstevel@tonic-gate 3816*7c478bd9Sstevel@tonic-gate if (rv) { 3817*7c478bd9Sstevel@tonic-gate PR_ALL("%s: errno %d, ecode %d during detach\n", 3818*7c478bd9Sstevel@tonic-gate f, SBD_GET_ERRNO(SBD_HD2ERR(hp)), 3819*7c478bd9Sstevel@tonic-gate SBD_GET_ERR(HD2MACHERR(hp))); 3820*7c478bd9Sstevel@tonic-gate } 3821*7c478bd9Sstevel@tonic-gate 3822*7c478bd9Sstevel@tonic-gate if (max_units && devlist) { 3823*7c478bd9Sstevel@tonic-gate int i; 3824*7c478bd9Sstevel@tonic-gate 3825*7c478bd9Sstevel@tonic-gate for (i = 0; i < max_units; i++) { 3826*7c478bd9Sstevel@tonic-gate if (SBD_GET_ERRSTR(&devlist[i].dv_error)) { 3827*7c478bd9Sstevel@tonic-gate SBD_FREE_ERR(&devlist[i].dv_error); 3828*7c478bd9Sstevel@tonic-gate } else { 3829*7c478bd9Sstevel@tonic-gate break; 3830*7c478bd9Sstevel@tonic-gate } 3831*7c478bd9Sstevel@tonic-gate } 3832*7c478bd9Sstevel@tonic-gate FREESTRUCT(devlist, sbd_devlist_t, max_units); 3833*7c478bd9Sstevel@tonic-gate } 3834*7c478bd9Sstevel@tonic-gate 3835*7c478bd9Sstevel@tonic-gate return (SBD_GET_ERRNO(SBD_HD2ERR(hp)) ? -1 : 0); 3836*7c478bd9Sstevel@tonic-gate } 3837*7c478bd9Sstevel@tonic-gate 3838*7c478bd9Sstevel@tonic-gate /* 3839*7c478bd9Sstevel@tonic-gate * Return the unit number of the respective dip if 3840*7c478bd9Sstevel@tonic-gate * it's found to be attached. 3841*7c478bd9Sstevel@tonic-gate */ 3842*7c478bd9Sstevel@tonic-gate static int 3843*7c478bd9Sstevel@tonic-gate sbd_check_unit_attached(sbd_board_t *sbp, dev_info_t *dip, int unit, 3844*7c478bd9Sstevel@tonic-gate sbd_comp_type_t nodetype, sbderror_t *ep) 3845*7c478bd9Sstevel@tonic-gate { 3846*7c478bd9Sstevel@tonic-gate int rv = -1; 3847*7c478bd9Sstevel@tonic-gate processorid_t cpuid; 3848*7c478bd9Sstevel@tonic-gate uint64_t basepa, endpa; 3849*7c478bd9Sstevel@tonic-gate struct memlist *ml; 3850*7c478bd9Sstevel@tonic-gate extern struct memlist *phys_install; 3851*7c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 3852*7c478bd9Sstevel@tonic-gate sbd_handle_t *hp = MACHBD2HD(sbp); 3853*7c478bd9Sstevel@tonic-gate static fn_t f = "sbd_check_unit_attached"; 3854*7c478bd9Sstevel@tonic-gate 3855*7c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 3856*7c478bd9Sstevel@tonic-gate 3857*7c478bd9Sstevel@tonic-gate switch (nodetype) { 3858*7c478bd9Sstevel@tonic-gate 3859*7c478bd9Sstevel@tonic-gate case SBD_COMP_CPU: 3860*7c478bd9Sstevel@tonic-gate cpuid = sbdp_get_cpuid(hdp, dip); 3861*7c478bd9Sstevel@tonic-gate if (cpuid < 0) { 3862*7c478bd9Sstevel@tonic-gate break; 3863*7c478bd9Sstevel@tonic-gate } 3864*7c478bd9Sstevel@tonic-gate mutex_enter(&cpu_lock); 3865*7c478bd9Sstevel@tonic-gate if (cpu_get(cpuid) != NULL) 3866*7c478bd9Sstevel@tonic-gate rv = unit; 3867*7c478bd9Sstevel@tonic-gate mutex_exit(&cpu_lock); 3868*7c478bd9Sstevel@tonic-gate break; 3869*7c478bd9Sstevel@tonic-gate 3870*7c478bd9Sstevel@tonic-gate case SBD_COMP_MEM: 3871*7c478bd9Sstevel@tonic-gate if (sbdphw_get_base_physaddr(hdp, dip, &basepa)) { 3872*7c478bd9Sstevel@tonic-gate break; 3873*7c478bd9Sstevel@tonic-gate } 3874*7c478bd9Sstevel@tonic-gate if (sbdp_get_mem_alignment(hdp, dip, &endpa)) { 3875*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "%s sbdp_get_mem_alignment fail", f); 3876*7c478bd9Sstevel@tonic-gate break; 3877*7c478bd9Sstevel@tonic-gate } 3878*7c478bd9Sstevel@tonic-gate 3879*7c478bd9Sstevel@tonic-gate basepa &= ~(endpa - 1); 3880*7c478bd9Sstevel@tonic-gate endpa += basepa; 3881*7c478bd9Sstevel@tonic-gate /* 3882*7c478bd9Sstevel@tonic-gate * Check if base address is in phys_install. 3883*7c478bd9Sstevel@tonic-gate */ 3884*7c478bd9Sstevel@tonic-gate memlist_read_lock(); 3885*7c478bd9Sstevel@tonic-gate for (ml = phys_install; ml; ml = ml->next) 3886*7c478bd9Sstevel@tonic-gate if ((endpa <= ml->address) || 3887*7c478bd9Sstevel@tonic-gate (basepa >= (ml->address + ml->size))) 3888*7c478bd9Sstevel@tonic-gate continue; 3889*7c478bd9Sstevel@tonic-gate else 3890*7c478bd9Sstevel@tonic-gate break; 3891*7c478bd9Sstevel@tonic-gate memlist_read_unlock(); 3892*7c478bd9Sstevel@tonic-gate if (ml != NULL) 3893*7c478bd9Sstevel@tonic-gate rv = unit; 3894*7c478bd9Sstevel@tonic-gate break; 3895*7c478bd9Sstevel@tonic-gate 3896*7c478bd9Sstevel@tonic-gate case SBD_COMP_IO: 3897*7c478bd9Sstevel@tonic-gate { 3898*7c478bd9Sstevel@tonic-gate dev_info_t *tdip, *pdip; 3899*7c478bd9Sstevel@tonic-gate 3900*7c478bd9Sstevel@tonic-gate tdip = dip; 3901*7c478bd9Sstevel@tonic-gate 3902*7c478bd9Sstevel@tonic-gate /* 3903*7c478bd9Sstevel@tonic-gate * ddi_walk_devs() requires that topdip's parent be held. 3904*7c478bd9Sstevel@tonic-gate */ 3905*7c478bd9Sstevel@tonic-gate pdip = ddi_get_parent(sbp->sb_topdip); 3906*7c478bd9Sstevel@tonic-gate if (pdip) { 3907*7c478bd9Sstevel@tonic-gate ndi_hold_devi(pdip); 3908*7c478bd9Sstevel@tonic-gate ndi_devi_enter(pdip, &rv); 3909*7c478bd9Sstevel@tonic-gate } 3910*7c478bd9Sstevel@tonic-gate ddi_walk_devs(sbp->sb_topdip, sbd_check_io_attached, 3911*7c478bd9Sstevel@tonic-gate (void *)&tdip); 3912*7c478bd9Sstevel@tonic-gate if (pdip) { 3913*7c478bd9Sstevel@tonic-gate ndi_devi_exit(pdip, rv); 3914*7c478bd9Sstevel@tonic-gate ndi_rele_devi(pdip); 3915*7c478bd9Sstevel@tonic-gate } 3916*7c478bd9Sstevel@tonic-gate 3917*7c478bd9Sstevel@tonic-gate if (tdip == NULL) 3918*7c478bd9Sstevel@tonic-gate rv = unit; 3919*7c478bd9Sstevel@tonic-gate else 3920*7c478bd9Sstevel@tonic-gate rv = -1; 3921*7c478bd9Sstevel@tonic-gate break; 3922*7c478bd9Sstevel@tonic-gate } 3923*7c478bd9Sstevel@tonic-gate 3924*7c478bd9Sstevel@tonic-gate default: 3925*7c478bd9Sstevel@tonic-gate PR_ALL("%s: unexpected nodetype(%d) for dip 0x%p\n", 3926*7c478bd9Sstevel@tonic-gate f, nodetype, (void *)dip); 3927*7c478bd9Sstevel@tonic-gate rv = -1; 3928*7c478bd9Sstevel@tonic-gate break; 3929*7c478bd9Sstevel@tonic-gate } 3930*7c478bd9Sstevel@tonic-gate 3931*7c478bd9Sstevel@tonic-gate /* 3932*7c478bd9Sstevel@tonic-gate * Save the error that sbdp sent us and report it 3933*7c478bd9Sstevel@tonic-gate */ 3934*7c478bd9Sstevel@tonic-gate if (rv == -1) 3935*7c478bd9Sstevel@tonic-gate SBD_GET_PERR(hdp->h_err, ep); 3936*7c478bd9Sstevel@tonic-gate 3937*7c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 3938*7c478bd9Sstevel@tonic-gate 3939*7c478bd9Sstevel@tonic-gate return (rv); 3940*7c478bd9Sstevel@tonic-gate } 3941*7c478bd9Sstevel@tonic-gate 3942*7c478bd9Sstevel@tonic-gate /* 3943*7c478bd9Sstevel@tonic-gate * Return memhandle, if in fact, this memunit is the owner of 3944*7c478bd9Sstevel@tonic-gate * a scheduled memory delete. 3945*7c478bd9Sstevel@tonic-gate */ 3946*7c478bd9Sstevel@tonic-gate int 3947*7c478bd9Sstevel@tonic-gate sbd_get_memhandle(sbd_handle_t *hp, dev_info_t *dip, memhandle_t *mhp) 3948*7c478bd9Sstevel@tonic-gate { 3949*7c478bd9Sstevel@tonic-gate sbd_board_t *sbp = SBDH2BD(hp->h_sbd); 3950*7c478bd9Sstevel@tonic-gate sbd_mem_unit_t *mp; 3951*7c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 3952*7c478bd9Sstevel@tonic-gate int unit; 3953*7c478bd9Sstevel@tonic-gate static fn_t f = "sbd_get_memhandle"; 3954*7c478bd9Sstevel@tonic-gate 3955*7c478bd9Sstevel@tonic-gate PR_MEM("%s...\n", f); 3956*7c478bd9Sstevel@tonic-gate 3957*7c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 3958*7c478bd9Sstevel@tonic-gate 3959*7c478bd9Sstevel@tonic-gate unit = sbdp_get_unit_num(hdp, dip); 3960*7c478bd9Sstevel@tonic-gate if (unit == -1) { 3961*7c478bd9Sstevel@tonic-gate SBD_GET_PERR(hdp->h_err, SBD_HD2ERR(hp)); 3962*7c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 3963*7c478bd9Sstevel@tonic-gate return (-1); 3964*7c478bd9Sstevel@tonic-gate } 3965*7c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 3966*7c478bd9Sstevel@tonic-gate 3967*7c478bd9Sstevel@tonic-gate mp = SBD_GET_BOARD_MEMUNIT(sbp, unit); 3968*7c478bd9Sstevel@tonic-gate 3969*7c478bd9Sstevel@tonic-gate if (mp->sbm_flags & SBD_MFLAG_RELOWNER) { 3970*7c478bd9Sstevel@tonic-gate *mhp = mp->sbm_memhandle; 3971*7c478bd9Sstevel@tonic-gate return (0); 3972*7c478bd9Sstevel@tonic-gate } else { 3973*7c478bd9Sstevel@tonic-gate SBD_SET_ERR(SBD_HD2ERR(hp), ESBD_INTERNAL); 3974*7c478bd9Sstevel@tonic-gate SBD_SET_ERRSTR(SBD_HD2ERR(hp), sbp->sb_mempath[unit]); 3975*7c478bd9Sstevel@tonic-gate return (-1); 3976*7c478bd9Sstevel@tonic-gate } 3977*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 3978*7c478bd9Sstevel@tonic-gate } 3979*7c478bd9Sstevel@tonic-gate 3980*7c478bd9Sstevel@tonic-gate 3981*7c478bd9Sstevel@tonic-gate static int 3982*7c478bd9Sstevel@tonic-gate sbd_cpu_cnt(sbd_handle_t *hp, sbd_devset_t devset) 3983*7c478bd9Sstevel@tonic-gate { 3984*7c478bd9Sstevel@tonic-gate int c, cix; 3985*7c478bd9Sstevel@tonic-gate sbd_board_t *sbp; 3986*7c478bd9Sstevel@tonic-gate 3987*7c478bd9Sstevel@tonic-gate sbp = SBDH2BD(hp->h_sbd); 3988*7c478bd9Sstevel@tonic-gate 3989*7c478bd9Sstevel@tonic-gate /* 3990*7c478bd9Sstevel@tonic-gate * Only look for requested devices that are actually present. 3991*7c478bd9Sstevel@tonic-gate */ 3992*7c478bd9Sstevel@tonic-gate devset &= SBD_DEVS_PRESENT(sbp); 3993*7c478bd9Sstevel@tonic-gate 3994*7c478bd9Sstevel@tonic-gate for (c = cix = 0; c < MAX_CMP_UNITS_PER_BOARD; c++) { 3995*7c478bd9Sstevel@tonic-gate /* 3996*7c478bd9Sstevel@tonic-gate * Index for core 1 , if exists. 3997*7c478bd9Sstevel@tonic-gate * With the current implementation it is 3998*7c478bd9Sstevel@tonic-gate * MAX_CMP_UNITS_PER_BOARD off from core 0. 3999*7c478bd9Sstevel@tonic-gate * The calculation will need to change if 4000*7c478bd9Sstevel@tonic-gate * the assumption is no longer true. 4001*7c478bd9Sstevel@tonic-gate */ 4002*7c478bd9Sstevel@tonic-gate int c1 = c + MAX_CMP_UNITS_PER_BOARD; 4003*7c478bd9Sstevel@tonic-gate 4004*7c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devset, SBD_COMP_CMP, c) == 0) { 4005*7c478bd9Sstevel@tonic-gate continue; 4006*7c478bd9Sstevel@tonic-gate } 4007*7c478bd9Sstevel@tonic-gate 4008*7c478bd9Sstevel@tonic-gate /* 4009*7c478bd9Sstevel@tonic-gate * Check to see if the dip(s) exist for this chip 4010*7c478bd9Sstevel@tonic-gate */ 4011*7c478bd9Sstevel@tonic-gate if ((sbp->sb_devlist[NIX(SBD_COMP_CMP)][c] == NULL) && 4012*7c478bd9Sstevel@tonic-gate (sbp->sb_devlist[NIX(SBD_COMP_CMP)][c1] == NULL)) 4013*7c478bd9Sstevel@tonic-gate continue; 4014*7c478bd9Sstevel@tonic-gate 4015*7c478bd9Sstevel@tonic-gate cix++; 4016*7c478bd9Sstevel@tonic-gate } 4017*7c478bd9Sstevel@tonic-gate 4018*7c478bd9Sstevel@tonic-gate return (cix); 4019*7c478bd9Sstevel@tonic-gate } 4020*7c478bd9Sstevel@tonic-gate 4021*7c478bd9Sstevel@tonic-gate static int 4022*7c478bd9Sstevel@tonic-gate sbd_mem_cnt(sbd_handle_t *hp, sbd_devset_t devset) 4023*7c478bd9Sstevel@tonic-gate { 4024*7c478bd9Sstevel@tonic-gate int i, ix; 4025*7c478bd9Sstevel@tonic-gate sbd_board_t *sbp = SBDH2BD(hp->h_sbd); 4026*7c478bd9Sstevel@tonic-gate 4027*7c478bd9Sstevel@tonic-gate /* 4028*7c478bd9Sstevel@tonic-gate * Only look for requested devices that are actually present. 4029*7c478bd9Sstevel@tonic-gate */ 4030*7c478bd9Sstevel@tonic-gate devset &= SBD_DEVS_PRESENT(sbp); 4031*7c478bd9Sstevel@tonic-gate 4032*7c478bd9Sstevel@tonic-gate for (i = ix = 0; i < MAX_MEM_UNITS_PER_BOARD; i++) { 4033*7c478bd9Sstevel@tonic-gate dev_info_t *dip; 4034*7c478bd9Sstevel@tonic-gate 4035*7c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devset, SBD_COMP_MEM, i) == 0) { 4036*7c478bd9Sstevel@tonic-gate continue; 4037*7c478bd9Sstevel@tonic-gate } 4038*7c478bd9Sstevel@tonic-gate 4039*7c478bd9Sstevel@tonic-gate dip = sbp->sb_devlist[NIX(SBD_COMP_MEM)][i]; 4040*7c478bd9Sstevel@tonic-gate if (dip == NULL) 4041*7c478bd9Sstevel@tonic-gate continue; 4042*7c478bd9Sstevel@tonic-gate 4043*7c478bd9Sstevel@tonic-gate ix++; 4044*7c478bd9Sstevel@tonic-gate } 4045*7c478bd9Sstevel@tonic-gate 4046*7c478bd9Sstevel@tonic-gate return (ix); 4047*7c478bd9Sstevel@tonic-gate } 4048*7c478bd9Sstevel@tonic-gate 4049*7c478bd9Sstevel@tonic-gate /* 4050*7c478bd9Sstevel@tonic-gate * NOTE: This routine is only partially smart about multiple 4051*7c478bd9Sstevel@tonic-gate * mem-units. Need to make mem-status structure smart 4052*7c478bd9Sstevel@tonic-gate * about them also. 4053*7c478bd9Sstevel@tonic-gate */ 4054*7c478bd9Sstevel@tonic-gate static int 4055*7c478bd9Sstevel@tonic-gate sbd_mem_status(sbd_handle_t *hp, sbd_devset_t devset, sbd_dev_stat_t *dsp) 4056*7c478bd9Sstevel@tonic-gate { 4057*7c478bd9Sstevel@tonic-gate int m, mix, rv; 4058*7c478bd9Sstevel@tonic-gate memdelstat_t mdst; 4059*7c478bd9Sstevel@tonic-gate memquery_t mq; 4060*7c478bd9Sstevel@tonic-gate sbd_board_t *sbp; 4061*7c478bd9Sstevel@tonic-gate sbd_mem_unit_t *mp; 4062*7c478bd9Sstevel@tonic-gate sbd_mem_stat_t *msp; 4063*7c478bd9Sstevel@tonic-gate extern int kcage_on; 4064*7c478bd9Sstevel@tonic-gate int i; 4065*7c478bd9Sstevel@tonic-gate static fn_t f = "sbd_mem_status"; 4066*7c478bd9Sstevel@tonic-gate 4067*7c478bd9Sstevel@tonic-gate sbp = SBDH2BD(hp->h_sbd); 4068*7c478bd9Sstevel@tonic-gate 4069*7c478bd9Sstevel@tonic-gate /* 4070*7c478bd9Sstevel@tonic-gate * Check the present devset and access the dip with 4071*7c478bd9Sstevel@tonic-gate * status lock held to protect agains a concurrent 4072*7c478bd9Sstevel@tonic-gate * unconfigure or disconnect thread. 4073*7c478bd9Sstevel@tonic-gate */ 4074*7c478bd9Sstevel@tonic-gate mutex_enter(&sbp->sb_slock); 4075*7c478bd9Sstevel@tonic-gate 4076*7c478bd9Sstevel@tonic-gate /* 4077*7c478bd9Sstevel@tonic-gate * Only look for requested devices that are actually present. 4078*7c478bd9Sstevel@tonic-gate */ 4079*7c478bd9Sstevel@tonic-gate devset &= SBD_DEVS_PRESENT(sbp); 4080*7c478bd9Sstevel@tonic-gate 4081*7c478bd9Sstevel@tonic-gate for (m = mix = 0; m < MAX_MEM_UNITS_PER_BOARD; m++) { 4082*7c478bd9Sstevel@tonic-gate dev_info_t *dip; 4083*7c478bd9Sstevel@tonic-gate 4084*7c478bd9Sstevel@tonic-gate 4085*7c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devset, SBD_COMP_MEM, m) == 0) 4086*7c478bd9Sstevel@tonic-gate continue; 4087*7c478bd9Sstevel@tonic-gate 4088*7c478bd9Sstevel@tonic-gate /* 4089*7c478bd9Sstevel@tonic-gate * Check to make sure the memory unit is in a state 4090*7c478bd9Sstevel@tonic-gate * where its fully initialized. 4091*7c478bd9Sstevel@tonic-gate */ 4092*7c478bd9Sstevel@tonic-gate if (SBD_DEVICE_STATE(sbp, SBD_COMP_MEM, m) == SBD_STATE_EMPTY) 4093*7c478bd9Sstevel@tonic-gate continue; 4094*7c478bd9Sstevel@tonic-gate 4095*7c478bd9Sstevel@tonic-gate dip = sbp->sb_devlist[NIX(SBD_COMP_MEM)][m]; 4096*7c478bd9Sstevel@tonic-gate if (dip == NULL) 4097*7c478bd9Sstevel@tonic-gate continue; 4098*7c478bd9Sstevel@tonic-gate 4099*7c478bd9Sstevel@tonic-gate mp = SBD_GET_BOARD_MEMUNIT(sbp, m); 4100*7c478bd9Sstevel@tonic-gate 4101*7c478bd9Sstevel@tonic-gate msp = &dsp->d_mem; 4102*7c478bd9Sstevel@tonic-gate 4103*7c478bd9Sstevel@tonic-gate bzero((caddr_t)msp, sizeof (*msp)); 4104*7c478bd9Sstevel@tonic-gate msp->ms_type = SBD_COMP_MEM; 4105*7c478bd9Sstevel@tonic-gate 4106*7c478bd9Sstevel@tonic-gate /* 4107*7c478bd9Sstevel@tonic-gate * The plugin expects -1 for the mem unit 4108*7c478bd9Sstevel@tonic-gate */ 4109*7c478bd9Sstevel@tonic-gate msp->ms_cm.c_id.c_unit = -1; 4110*7c478bd9Sstevel@tonic-gate 4111*7c478bd9Sstevel@tonic-gate /* 4112*7c478bd9Sstevel@tonic-gate * Get the memory name from what sbdp gave us 4113*7c478bd9Sstevel@tonic-gate */ 4114*7c478bd9Sstevel@tonic-gate for (i = 0; SBD_COMP(i) != SBD_COMP_UNKNOWN; i++) { 4115*7c478bd9Sstevel@tonic-gate if (SBD_COMP(i) == SBD_COMP_MEM) { 4116*7c478bd9Sstevel@tonic-gate (void) strcpy(msp->ms_name, SBD_DEVNAME(i)); 4117*7c478bd9Sstevel@tonic-gate } 4118*7c478bd9Sstevel@tonic-gate } 4119*7c478bd9Sstevel@tonic-gate msp->ms_cm.c_cond = mp->sbm_cm.sbdev_cond; 4120*7c478bd9Sstevel@tonic-gate msp->ms_cm.c_busy = mp->sbm_cm.sbdev_busy; 4121*7c478bd9Sstevel@tonic-gate msp->ms_cm.c_time = mp->sbm_cm.sbdev_time; 4122*7c478bd9Sstevel@tonic-gate 4123*7c478bd9Sstevel@tonic-gate /* XXX revisit this after memory conversion */ 4124*7c478bd9Sstevel@tonic-gate msp->ms_ostate = ostate_cvt(SBD_DEVICE_STATE( 4125*7c478bd9Sstevel@tonic-gate sbp, SBD_COMP_MEM, m)); 4126*7c478bd9Sstevel@tonic-gate 4127*7c478bd9Sstevel@tonic-gate msp->ms_basepfn = mp->sbm_basepfn; 4128*7c478bd9Sstevel@tonic-gate msp->ms_pageslost = mp->sbm_pageslost; 4129*7c478bd9Sstevel@tonic-gate msp->ms_cage_enabled = kcage_on; 4130*7c478bd9Sstevel@tonic-gate msp->ms_interleave = mp->sbm_interleave; 4131*7c478bd9Sstevel@tonic-gate 4132*7c478bd9Sstevel@tonic-gate if (mp->sbm_flags & SBD_MFLAG_RELOWNER) 4133*7c478bd9Sstevel@tonic-gate rv = kphysm_del_status(mp->sbm_memhandle, &mdst); 4134*7c478bd9Sstevel@tonic-gate else 4135*7c478bd9Sstevel@tonic-gate rv = KPHYSM_EHANDLE; /* force 'if' to fail */ 4136*7c478bd9Sstevel@tonic-gate 4137*7c478bd9Sstevel@tonic-gate if (rv == KPHYSM_OK) { 4138*7c478bd9Sstevel@tonic-gate msp->ms_totpages += mdst.phys_pages; 4139*7c478bd9Sstevel@tonic-gate 4140*7c478bd9Sstevel@tonic-gate /* 4141*7c478bd9Sstevel@tonic-gate * Any pages above managed is "free", 4142*7c478bd9Sstevel@tonic-gate * i.e. it's collected. 4143*7c478bd9Sstevel@tonic-gate */ 4144*7c478bd9Sstevel@tonic-gate msp->ms_detpages += (uint_t)(mdst.collected + 4145*7c478bd9Sstevel@tonic-gate mdst.phys_pages - 4146*7c478bd9Sstevel@tonic-gate mdst.managed); 4147*7c478bd9Sstevel@tonic-gate } else { 4148*7c478bd9Sstevel@tonic-gate msp->ms_totpages += (uint_t)mp->sbm_npages; 4149*7c478bd9Sstevel@tonic-gate 4150*7c478bd9Sstevel@tonic-gate /* 4151*7c478bd9Sstevel@tonic-gate * If we're UNREFERENCED or UNCONFIGURED, 4152*7c478bd9Sstevel@tonic-gate * then the number of detached pages is 4153*7c478bd9Sstevel@tonic-gate * however many pages are on the board. 4154*7c478bd9Sstevel@tonic-gate * I.e. detached = not in use by OS. 4155*7c478bd9Sstevel@tonic-gate */ 4156*7c478bd9Sstevel@tonic-gate switch (msp->ms_cm.c_ostate) { 4157*7c478bd9Sstevel@tonic-gate /* 4158*7c478bd9Sstevel@tonic-gate * changed to use cfgadm states 4159*7c478bd9Sstevel@tonic-gate * 4160*7c478bd9Sstevel@tonic-gate * was: 4161*7c478bd9Sstevel@tonic-gate * case SFDR_STATE_UNREFERENCED: 4162*7c478bd9Sstevel@tonic-gate * case SFDR_STATE_UNCONFIGURED: 4163*7c478bd9Sstevel@tonic-gate */ 4164*7c478bd9Sstevel@tonic-gate case SBD_STAT_UNCONFIGURED: 4165*7c478bd9Sstevel@tonic-gate msp->ms_detpages = msp->ms_totpages; 4166*7c478bd9Sstevel@tonic-gate break; 4167*7c478bd9Sstevel@tonic-gate 4168*7c478bd9Sstevel@tonic-gate default: 4169*7c478bd9Sstevel@tonic-gate break; 4170*7c478bd9Sstevel@tonic-gate } 4171*7c478bd9Sstevel@tonic-gate } 4172*7c478bd9Sstevel@tonic-gate 4173*7c478bd9Sstevel@tonic-gate rv = kphysm_del_span_query(mp->sbm_basepfn, 4174*7c478bd9Sstevel@tonic-gate mp->sbm_npages, &mq); 4175*7c478bd9Sstevel@tonic-gate if (rv == KPHYSM_OK) { 4176*7c478bd9Sstevel@tonic-gate msp->ms_managed_pages = mq.managed; 4177*7c478bd9Sstevel@tonic-gate msp->ms_noreloc_pages = mq.nonrelocatable; 4178*7c478bd9Sstevel@tonic-gate msp->ms_noreloc_first = mq.first_nonrelocatable; 4179*7c478bd9Sstevel@tonic-gate msp->ms_noreloc_last = mq.last_nonrelocatable; 4180*7c478bd9Sstevel@tonic-gate msp->ms_cm.c_sflags = 0; 4181*7c478bd9Sstevel@tonic-gate if (mq.nonrelocatable) { 4182*7c478bd9Sstevel@tonic-gate SBD_SET_SUSPEND(SBD_CMD_UNCONFIGURE, 4183*7c478bd9Sstevel@tonic-gate dsp->ds_suspend); 4184*7c478bd9Sstevel@tonic-gate } 4185*7c478bd9Sstevel@tonic-gate } else { 4186*7c478bd9Sstevel@tonic-gate PR_MEM("%s: kphysm_del_span_query() = %d\n", f, rv); 4187*7c478bd9Sstevel@tonic-gate } 4188*7c478bd9Sstevel@tonic-gate 4189*7c478bd9Sstevel@tonic-gate mix++; 4190*7c478bd9Sstevel@tonic-gate dsp++; 4191*7c478bd9Sstevel@tonic-gate } 4192*7c478bd9Sstevel@tonic-gate 4193*7c478bd9Sstevel@tonic-gate mutex_exit(&sbp->sb_slock); 4194*7c478bd9Sstevel@tonic-gate 4195*7c478bd9Sstevel@tonic-gate return (mix); 4196*7c478bd9Sstevel@tonic-gate } 4197*7c478bd9Sstevel@tonic-gate 4198*7c478bd9Sstevel@tonic-gate static void 4199*7c478bd9Sstevel@tonic-gate sbd_cancel(sbd_handle_t *hp) 4200*7c478bd9Sstevel@tonic-gate { 4201*7c478bd9Sstevel@tonic-gate int i; 4202*7c478bd9Sstevel@tonic-gate sbd_devset_t devset; 4203*7c478bd9Sstevel@tonic-gate sbd_board_t *sbp = SBDH2BD(hp->h_sbd); 4204*7c478bd9Sstevel@tonic-gate static fn_t f = "sbd_cancel"; 4205*7c478bd9Sstevel@tonic-gate int rv; 4206*7c478bd9Sstevel@tonic-gate 4207*7c478bd9Sstevel@tonic-gate PR_ALL("%s...\n", f); 4208*7c478bd9Sstevel@tonic-gate 4209*7c478bd9Sstevel@tonic-gate /* 4210*7c478bd9Sstevel@tonic-gate * Only devices which have been "released" are 4211*7c478bd9Sstevel@tonic-gate * subject to cancellation. 4212*7c478bd9Sstevel@tonic-gate */ 4213*7c478bd9Sstevel@tonic-gate devset = HD2MACHHD(hp)->sh_devset & SBD_DEVS_UNREFERENCED(sbp); 4214*7c478bd9Sstevel@tonic-gate 4215*7c478bd9Sstevel@tonic-gate /* 4216*7c478bd9Sstevel@tonic-gate * Nothing to do for CPUs or IO other than change back 4217*7c478bd9Sstevel@tonic-gate * their state. 4218*7c478bd9Sstevel@tonic-gate */ 4219*7c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_CPU_UNITS_PER_BOARD; i++) { 4220*7c478bd9Sstevel@tonic-gate if (!DEVSET_IN_SET(devset, SBD_COMP_CPU, i)) 4221*7c478bd9Sstevel@tonic-gate continue; 4222*7c478bd9Sstevel@tonic-gate if (sbd_cancel_cpu(hp, i) != SBD_CPUERR_FATAL) { 4223*7c478bd9Sstevel@tonic-gate SBD_DEVICE_TRANSITION(sbp, SBD_COMP_CPU, i, 4224*7c478bd9Sstevel@tonic-gate SBD_STATE_CONFIGURED); 4225*7c478bd9Sstevel@tonic-gate } else { 4226*7c478bd9Sstevel@tonic-gate SBD_DEVICE_TRANSITION(sbp, SBD_COMP_CPU, i, 4227*7c478bd9Sstevel@tonic-gate SBD_STATE_FATAL); 4228*7c478bd9Sstevel@tonic-gate } 4229*7c478bd9Sstevel@tonic-gate } 4230*7c478bd9Sstevel@tonic-gate 4231*7c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_IO_UNITS_PER_BOARD; i++) { 4232*7c478bd9Sstevel@tonic-gate if (!DEVSET_IN_SET(devset, SBD_COMP_IO, i)) 4233*7c478bd9Sstevel@tonic-gate continue; 4234*7c478bd9Sstevel@tonic-gate SBD_DEVICE_TRANSITION(sbp, SBD_COMP_IO, i, 4235*7c478bd9Sstevel@tonic-gate SBD_STATE_CONFIGURED); 4236*7c478bd9Sstevel@tonic-gate } 4237*7c478bd9Sstevel@tonic-gate 4238*7c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_MEM_UNITS_PER_BOARD; i++) { 4239*7c478bd9Sstevel@tonic-gate if (!DEVSET_IN_SET(devset, SBD_COMP_MEM, i)) 4240*7c478bd9Sstevel@tonic-gate continue; 4241*7c478bd9Sstevel@tonic-gate if ((rv = sbd_cancel_mem(hp, i)) == 0) { 4242*7c478bd9Sstevel@tonic-gate SBD_DEVICE_TRANSITION(sbp, SBD_COMP_MEM, i, 4243*7c478bd9Sstevel@tonic-gate SBD_STATE_CONFIGURED); 4244*7c478bd9Sstevel@tonic-gate } else if (rv == -1) { 4245*7c478bd9Sstevel@tonic-gate SBD_DEVICE_TRANSITION(sbp, SBD_COMP_MEM, i, 4246*7c478bd9Sstevel@tonic-gate SBD_STATE_FATAL); 4247*7c478bd9Sstevel@tonic-gate } 4248*7c478bd9Sstevel@tonic-gate } 4249*7c478bd9Sstevel@tonic-gate 4250*7c478bd9Sstevel@tonic-gate PR_ALL("%s: unreleasing devset (0x%x)\n", f, (uint_t)devset); 4251*7c478bd9Sstevel@tonic-gate 4252*7c478bd9Sstevel@tonic-gate SBD_DEVS_CANCEL(sbp, devset); 4253*7c478bd9Sstevel@tonic-gate 4254*7c478bd9Sstevel@tonic-gate if (SBD_DEVS_UNREFERENCED(sbp) == 0) { 4255*7c478bd9Sstevel@tonic-gate sbd_istate_t new_state; 4256*7c478bd9Sstevel@tonic-gate /* 4257*7c478bd9Sstevel@tonic-gate * If the board no longer has any released devices 4258*7c478bd9Sstevel@tonic-gate * than transfer it back to the CONFIG/PARTIAL state. 4259*7c478bd9Sstevel@tonic-gate */ 4260*7c478bd9Sstevel@tonic-gate if (SBD_DEVS_ATTACHED(sbp) == SBD_DEVS_PRESENT(sbp)) 4261*7c478bd9Sstevel@tonic-gate new_state = SBD_STATE_CONFIGURED; 4262*7c478bd9Sstevel@tonic-gate else 4263*7c478bd9Sstevel@tonic-gate new_state = SBD_STATE_PARTIAL; 4264*7c478bd9Sstevel@tonic-gate if (SBD_BOARD_STATE(sbp) != new_state) { 4265*7c478bd9Sstevel@tonic-gate SBD_BOARD_TRANSITION(sbp, new_state); 4266*7c478bd9Sstevel@tonic-gate } 4267*7c478bd9Sstevel@tonic-gate sbp->sb_ostate = SBD_STAT_CONFIGURED; 4268*7c478bd9Sstevel@tonic-gate (void) drv_getparm(TIME, (void *)&sbp->sb_time); 4269*7c478bd9Sstevel@tonic-gate } 4270*7c478bd9Sstevel@tonic-gate } 4271*7c478bd9Sstevel@tonic-gate 4272*7c478bd9Sstevel@tonic-gate static void 4273*7c478bd9Sstevel@tonic-gate sbd_get_ncm(sbd_handle_t *hp) 4274*7c478bd9Sstevel@tonic-gate { 4275*7c478bd9Sstevel@tonic-gate sbd_devset_t devset; 4276*7c478bd9Sstevel@tonic-gate sbd_priv_handle_t *shp = HD2MACHHD(hp); 4277*7c478bd9Sstevel@tonic-gate sbd_cmd_t *cmdp = (sbd_cmd_t *)hp->h_iap; 4278*7c478bd9Sstevel@tonic-gate int error; 4279*7c478bd9Sstevel@tonic-gate 4280*7c478bd9Sstevel@tonic-gate /* pre_op restricted the devices to those selected by the ioctl */ 4281*7c478bd9Sstevel@tonic-gate devset = shp->sh_devset; 4282*7c478bd9Sstevel@tonic-gate 4283*7c478bd9Sstevel@tonic-gate cmdp->cmd_getncm.g_ncm = sbd_cpu_cnt(hp, devset) 4284*7c478bd9Sstevel@tonic-gate + sbd_io_cnt(hp, devset) + sbd_mem_cnt(hp, devset); 4285*7c478bd9Sstevel@tonic-gate 4286*7c478bd9Sstevel@tonic-gate error = sbd_copyout_ioarg(hp->h_mode, hp->h_cmd, cmdp, 4287*7c478bd9Sstevel@tonic-gate (sbd_ioctl_arg_t *)shp->sh_arg); 4288*7c478bd9Sstevel@tonic-gate 4289*7c478bd9Sstevel@tonic-gate if (error != 0) 4290*7c478bd9Sstevel@tonic-gate SBD_SET_ERRNO(SBD_HD2ERR(hp), error); 4291*7c478bd9Sstevel@tonic-gate } 4292*7c478bd9Sstevel@tonic-gate 4293*7c478bd9Sstevel@tonic-gate static void 4294*7c478bd9Sstevel@tonic-gate sbd_status(sbd_handle_t *hp) 4295*7c478bd9Sstevel@tonic-gate { 4296*7c478bd9Sstevel@tonic-gate int nstat, mode, ncm, sz, cksz; 4297*7c478bd9Sstevel@tonic-gate sbd_priv_handle_t *shp = HD2MACHHD(hp); 4298*7c478bd9Sstevel@tonic-gate sbd_devset_t devset; 4299*7c478bd9Sstevel@tonic-gate sbd_board_t *sbp = SBDH2BD(hp->h_sbd); 4300*7c478bd9Sstevel@tonic-gate sbd_stat_t *dstatp; 4301*7c478bd9Sstevel@tonic-gate sbd_cmd_t *cmdp = (sbd_cmd_t *)hp->h_iap; 4302*7c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 4303*7c478bd9Sstevel@tonic-gate sbd_dev_stat_t *devstatp; 4304*7c478bd9Sstevel@tonic-gate 4305*7c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 4306*7c478bd9Sstevel@tonic-gate int sz32; 4307*7c478bd9Sstevel@tonic-gate sbd_stat32_t *dstat32p; 4308*7c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */ 4309*7c478bd9Sstevel@tonic-gate 4310*7c478bd9Sstevel@tonic-gate static fn_t f = "sbd_status"; 4311*7c478bd9Sstevel@tonic-gate 4312*7c478bd9Sstevel@tonic-gate mode = hp->h_mode; 4313*7c478bd9Sstevel@tonic-gate devset = shp->sh_devset; 4314*7c478bd9Sstevel@tonic-gate 4315*7c478bd9Sstevel@tonic-gate devset &= SBD_DEVS_PRESENT(sbp); 4316*7c478bd9Sstevel@tonic-gate 4317*7c478bd9Sstevel@tonic-gate if (cmdp->cmd_cm.c_id.c_type == SBD_COMP_NONE) { 4318*7c478bd9Sstevel@tonic-gate if (cmdp->cmd_cm.c_flags & SBD_FLAG_ALLCMP) { 4319*7c478bd9Sstevel@tonic-gate /* 4320*7c478bd9Sstevel@tonic-gate * Get the number of components "ncm" on the board. 4321*7c478bd9Sstevel@tonic-gate * Calculate size of buffer required to store one 4322*7c478bd9Sstevel@tonic-gate * sbd_stat_t structure plus ncm-1 sbd_dev_stat_t 4323*7c478bd9Sstevel@tonic-gate * structures. Note that sbd_stat_t already contains 4324*7c478bd9Sstevel@tonic-gate * one sbd_dev_stat_t, so only an additional ncm-1 4325*7c478bd9Sstevel@tonic-gate * sbd_dev_stat_t structures need to be accounted for 4326*7c478bd9Sstevel@tonic-gate * in the calculation when more than one component 4327*7c478bd9Sstevel@tonic-gate * is present. 4328*7c478bd9Sstevel@tonic-gate */ 4329*7c478bd9Sstevel@tonic-gate ncm = sbd_cpu_cnt(hp, devset) + sbd_io_cnt(hp, devset) + 4330*7c478bd9Sstevel@tonic-gate sbd_mem_cnt(hp, devset); 4331*7c478bd9Sstevel@tonic-gate 4332*7c478bd9Sstevel@tonic-gate } else { 4333*7c478bd9Sstevel@tonic-gate /* 4334*7c478bd9Sstevel@tonic-gate * In the case of c_type == SBD_COMP_NONE, and 4335*7c478bd9Sstevel@tonic-gate * SBD_FLAG_ALLCMP not specified, only the board 4336*7c478bd9Sstevel@tonic-gate * info is to be returned, no components. 4337*7c478bd9Sstevel@tonic-gate */ 4338*7c478bd9Sstevel@tonic-gate ncm = 0; 4339*7c478bd9Sstevel@tonic-gate devset = 0; 4340*7c478bd9Sstevel@tonic-gate } 4341*7c478bd9Sstevel@tonic-gate } else { 4342*7c478bd9Sstevel@tonic-gate /* Confirm that only one component is selected. */ 4343*7c478bd9Sstevel@tonic-gate ncm = sbd_cpu_cnt(hp, devset) + sbd_io_cnt(hp, devset) + 4344*7c478bd9Sstevel@tonic-gate sbd_mem_cnt(hp, devset); 4345*7c478bd9Sstevel@tonic-gate if (ncm != 1) { 4346*7c478bd9Sstevel@tonic-gate PR_ALL("%s: expected ncm of 1, got %d, devset 0x%x\n", 4347*7c478bd9Sstevel@tonic-gate f, ncm, devset); 4348*7c478bd9Sstevel@tonic-gate SBD_SET_ERRNO(SBD_HD2ERR(hp), EINVAL); 4349*7c478bd9Sstevel@tonic-gate return; 4350*7c478bd9Sstevel@tonic-gate } 4351*7c478bd9Sstevel@tonic-gate } 4352*7c478bd9Sstevel@tonic-gate 4353*7c478bd9Sstevel@tonic-gate sz = sizeof (sbd_stat_t); 4354*7c478bd9Sstevel@tonic-gate if (ncm > 1) 4355*7c478bd9Sstevel@tonic-gate sz += sizeof (sbd_dev_stat_t) * (ncm - 1); 4356*7c478bd9Sstevel@tonic-gate 4357*7c478bd9Sstevel@tonic-gate cksz = sz; 4358*7c478bd9Sstevel@tonic-gate 4359*7c478bd9Sstevel@tonic-gate /* 4360*7c478bd9Sstevel@tonic-gate * s_nbytes describes the size of the preallocated user 4361*7c478bd9Sstevel@tonic-gate * buffer into which the application is executing to 4362*7c478bd9Sstevel@tonic-gate * receive the sbd_stat_t and sbd_dev_stat_t structures. 4363*7c478bd9Sstevel@tonic-gate * This buffer must be at least the required (sz) size. 4364*7c478bd9Sstevel@tonic-gate */ 4365*7c478bd9Sstevel@tonic-gate 4366*7c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 4367*7c478bd9Sstevel@tonic-gate 4368*7c478bd9Sstevel@tonic-gate /* 4369*7c478bd9Sstevel@tonic-gate * More buffer space is required for the 64bit to 32bit 4370*7c478bd9Sstevel@tonic-gate * conversion of data structures. 4371*7c478bd9Sstevel@tonic-gate */ 4372*7c478bd9Sstevel@tonic-gate if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) { 4373*7c478bd9Sstevel@tonic-gate sz32 = sizeof (sbd_stat32_t); 4374*7c478bd9Sstevel@tonic-gate if (ncm > 1) 4375*7c478bd9Sstevel@tonic-gate sz32 += sizeof (sbd_dev_stat32_t) * (ncm - 1); 4376*7c478bd9Sstevel@tonic-gate cksz = sz32; 4377*7c478bd9Sstevel@tonic-gate } else 4378*7c478bd9Sstevel@tonic-gate sz32 = 0; 4379*7c478bd9Sstevel@tonic-gate #endif 4380*7c478bd9Sstevel@tonic-gate 4381*7c478bd9Sstevel@tonic-gate if ((int)cmdp->cmd_stat.s_nbytes < cksz) { 4382*7c478bd9Sstevel@tonic-gate PR_ALL("%s: ncm=%d s_nbytes = 0x%x\n", f, ncm, 4383*7c478bd9Sstevel@tonic-gate cmdp->cmd_stat.s_nbytes); 4384*7c478bd9Sstevel@tonic-gate PR_ALL("%s: expected size of 0x%x\n", f, cksz); 4385*7c478bd9Sstevel@tonic-gate SBD_SET_ERRNO(SBD_HD2ERR(hp), EINVAL); 4386*7c478bd9Sstevel@tonic-gate return; 4387*7c478bd9Sstevel@tonic-gate } 4388*7c478bd9Sstevel@tonic-gate 4389*7c478bd9Sstevel@tonic-gate dstatp = kmem_zalloc(sz, KM_SLEEP); 4390*7c478bd9Sstevel@tonic-gate devstatp = &dstatp->s_stat[0]; 4391*7c478bd9Sstevel@tonic-gate 4392*7c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 4393*7c478bd9Sstevel@tonic-gate if (sz32 != 0) 4394*7c478bd9Sstevel@tonic-gate dstat32p = kmem_zalloc(sz32, KM_SLEEP); 4395*7c478bd9Sstevel@tonic-gate #endif 4396*7c478bd9Sstevel@tonic-gate 4397*7c478bd9Sstevel@tonic-gate /* 4398*7c478bd9Sstevel@tonic-gate * if connected or better, provide cached status if available, 4399*7c478bd9Sstevel@tonic-gate * otherwise call sbdp for status 4400*7c478bd9Sstevel@tonic-gate */ 4401*7c478bd9Sstevel@tonic-gate mutex_enter(&sbp->sb_flags_mutex); 4402*7c478bd9Sstevel@tonic-gate switch (sbp->sb_state) { 4403*7c478bd9Sstevel@tonic-gate 4404*7c478bd9Sstevel@tonic-gate case SBD_STATE_CONNECTED: 4405*7c478bd9Sstevel@tonic-gate case SBD_STATE_PARTIAL: 4406*7c478bd9Sstevel@tonic-gate case SBD_STATE_CONFIGURED: 4407*7c478bd9Sstevel@tonic-gate if (sbp->sb_flags & SBD_BOARD_STATUS_CACHED) { 4408*7c478bd9Sstevel@tonic-gate bcopy(&sbp->sb_stat, dstatp, sizeof (sbd_stat_t)); 4409*7c478bd9Sstevel@tonic-gate dstatp->s_rstate = rstate_cvt(sbp->sb_state); 4410*7c478bd9Sstevel@tonic-gate dstatp->s_ostate = ostate_cvt(sbp->sb_state); 4411*7c478bd9Sstevel@tonic-gate dstatp->s_busy = sbp->sb_busy; 4412*7c478bd9Sstevel@tonic-gate dstatp->s_time = sbp->sb_time; 4413*7c478bd9Sstevel@tonic-gate dstatp->s_cond = sbp->sb_cond; 4414*7c478bd9Sstevel@tonic-gate break; 4415*7c478bd9Sstevel@tonic-gate } 4416*7c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 4417*7c478bd9Sstevel@tonic-gate 4418*7c478bd9Sstevel@tonic-gate default: 4419*7c478bd9Sstevel@tonic-gate sbp->sb_flags &= ~SBD_BOARD_STATUS_CACHED; 4420*7c478bd9Sstevel@tonic-gate dstatp->s_board = sbp->sb_num; 4421*7c478bd9Sstevel@tonic-gate dstatp->s_ostate = ostate_cvt(sbp->sb_state); 4422*7c478bd9Sstevel@tonic-gate dstatp->s_time = sbp->sb_time; 4423*7c478bd9Sstevel@tonic-gate 4424*7c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 4425*7c478bd9Sstevel@tonic-gate 4426*7c478bd9Sstevel@tonic-gate if (sbdp_get_board_status(hdp, dstatp) != 0) { 4427*7c478bd9Sstevel@tonic-gate SBD_GET_PERR(hdp->h_err, SBD_HD2ERR(hp)); 4428*7c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 4429*7c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 4430*7c478bd9Sstevel@tonic-gate if (sz32 != 0) 4431*7c478bd9Sstevel@tonic-gate kmem_free(dstat32p, sz32); 4432*7c478bd9Sstevel@tonic-gate #endif 4433*7c478bd9Sstevel@tonic-gate kmem_free(dstatp, sz); 4434*7c478bd9Sstevel@tonic-gate mutex_exit(&sbp->sb_flags_mutex); 4435*7c478bd9Sstevel@tonic-gate return; 4436*7c478bd9Sstevel@tonic-gate } 4437*7c478bd9Sstevel@tonic-gate /* 4438*7c478bd9Sstevel@tonic-gate * Do not cache status if the busy flag has 4439*7c478bd9Sstevel@tonic-gate * been set by the call to sbdp_get_board_status(). 4440*7c478bd9Sstevel@tonic-gate */ 4441*7c478bd9Sstevel@tonic-gate if (!dstatp->s_busy) { 4442*7c478bd9Sstevel@tonic-gate /* Can get board busy flag now */ 4443*7c478bd9Sstevel@tonic-gate dstatp->s_busy = sbp->sb_busy; 4444*7c478bd9Sstevel@tonic-gate sbp->sb_cond = (sbd_cond_t)dstatp->s_cond; 4445*7c478bd9Sstevel@tonic-gate bcopy(dstatp, &sbp->sb_stat, 4446*7c478bd9Sstevel@tonic-gate sizeof (sbd_stat_t)); 4447*7c478bd9Sstevel@tonic-gate sbp->sb_flags |= SBD_BOARD_STATUS_CACHED; 4448*7c478bd9Sstevel@tonic-gate } 4449*7c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 4450*7c478bd9Sstevel@tonic-gate break; 4451*7c478bd9Sstevel@tonic-gate } 4452*7c478bd9Sstevel@tonic-gate mutex_exit(&sbp->sb_flags_mutex); 4453*7c478bd9Sstevel@tonic-gate 4454*7c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devset, SBD_COMP_CPU, DEVSET_ANYUNIT)) 4455*7c478bd9Sstevel@tonic-gate if ((nstat = sbd_cpu_flags(hp, devset, devstatp)) > 0) { 4456*7c478bd9Sstevel@tonic-gate dstatp->s_nstat += nstat; 4457*7c478bd9Sstevel@tonic-gate devstatp += nstat; 4458*7c478bd9Sstevel@tonic-gate } 4459*7c478bd9Sstevel@tonic-gate 4460*7c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devset, SBD_COMP_MEM, DEVSET_ANYUNIT)) 4461*7c478bd9Sstevel@tonic-gate if ((nstat = sbd_mem_status(hp, devset, devstatp)) > 0) { 4462*7c478bd9Sstevel@tonic-gate dstatp->s_nstat += nstat; 4463*7c478bd9Sstevel@tonic-gate devstatp += nstat; 4464*7c478bd9Sstevel@tonic-gate } 4465*7c478bd9Sstevel@tonic-gate 4466*7c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devset, SBD_COMP_IO, DEVSET_ANYUNIT)) 4467*7c478bd9Sstevel@tonic-gate if ((nstat = sbd_io_status(hp, devset, devstatp)) > 0) { 4468*7c478bd9Sstevel@tonic-gate dstatp->s_nstat += nstat; 4469*7c478bd9Sstevel@tonic-gate devstatp += nstat; 4470*7c478bd9Sstevel@tonic-gate } 4471*7c478bd9Sstevel@tonic-gate 4472*7c478bd9Sstevel@tonic-gate /* paranoia: detect buffer overrun */ 4473*7c478bd9Sstevel@tonic-gate if ((caddr_t)devstatp > ((caddr_t)dstatp) + sz) { 4474*7c478bd9Sstevel@tonic-gate PR_ALL("%s: buffer overrun\n", f); 4475*7c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 4476*7c478bd9Sstevel@tonic-gate if (sz32 != 0) 4477*7c478bd9Sstevel@tonic-gate kmem_free(dstat32p, sz32); 4478*7c478bd9Sstevel@tonic-gate #endif 4479*7c478bd9Sstevel@tonic-gate kmem_free(dstatp, sz); 4480*7c478bd9Sstevel@tonic-gate SBD_SET_ERRNO(SBD_HD2ERR(hp), EINVAL); 4481*7c478bd9Sstevel@tonic-gate return; 4482*7c478bd9Sstevel@tonic-gate } 4483*7c478bd9Sstevel@tonic-gate 4484*7c478bd9Sstevel@tonic-gate /* if necessary, move data into intermediate device status buffer */ 4485*7c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 4486*7c478bd9Sstevel@tonic-gate if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) { 4487*7c478bd9Sstevel@tonic-gate int i, j; 4488*7c478bd9Sstevel@tonic-gate 4489*7c478bd9Sstevel@tonic-gate ASSERT(sz32 != 0); 4490*7c478bd9Sstevel@tonic-gate /* paranoia: detect buffer overrun */ 4491*7c478bd9Sstevel@tonic-gate if ((caddr_t)&dstat32p->s_stat[dstatp->s_nstat] > 4492*7c478bd9Sstevel@tonic-gate ((caddr_t)dstat32p) + sz32) { 4493*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 4494*7c478bd9Sstevel@tonic-gate "sbd:%s: buffer32 overrun", f); 4495*7c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 4496*7c478bd9Sstevel@tonic-gate if (sz32 != 0) 4497*7c478bd9Sstevel@tonic-gate kmem_free(dstat32p, sz32); 4498*7c478bd9Sstevel@tonic-gate #endif 4499*7c478bd9Sstevel@tonic-gate kmem_free(dstatp, sz); 4500*7c478bd9Sstevel@tonic-gate SBD_SET_ERRNO(SBD_HD2ERR(hp), EINVAL); 4501*7c478bd9Sstevel@tonic-gate return; 4502*7c478bd9Sstevel@tonic-gate } 4503*7c478bd9Sstevel@tonic-gate 4504*7c478bd9Sstevel@tonic-gate /* 4505*7c478bd9Sstevel@tonic-gate * initialize 32 bit sbd board status structure 4506*7c478bd9Sstevel@tonic-gate */ 4507*7c478bd9Sstevel@tonic-gate dstat32p->s_board = (int32_t)dstatp->s_board; 4508*7c478bd9Sstevel@tonic-gate dstat32p->s_nstat = (int32_t)dstatp->s_nstat; 4509*7c478bd9Sstevel@tonic-gate dstat32p->s_rstate = dstatp->s_rstate; 4510*7c478bd9Sstevel@tonic-gate dstat32p->s_ostate = dstatp->s_ostate; 4511*7c478bd9Sstevel@tonic-gate dstat32p->s_cond = dstatp->s_cond; 4512*7c478bd9Sstevel@tonic-gate dstat32p->s_busy = dstatp->s_busy; 4513*7c478bd9Sstevel@tonic-gate dstat32p->s_time = dstatp->s_time; 4514*7c478bd9Sstevel@tonic-gate dstat32p->s_assigned = dstatp->s_assigned; 4515*7c478bd9Sstevel@tonic-gate dstat32p->s_power = dstatp->s_power; 4516*7c478bd9Sstevel@tonic-gate dstat32p->s_platopts = (int32_t)dstatp->s_platopts; 4517*7c478bd9Sstevel@tonic-gate (void) strcpy(dstat32p->s_type, dstatp->s_type); 4518*7c478bd9Sstevel@tonic-gate 4519*7c478bd9Sstevel@tonic-gate for (i = 0; i < dstatp->s_nstat; i++) { 4520*7c478bd9Sstevel@tonic-gate sbd_dev_stat_t *dsp = &dstatp->s_stat[i]; 4521*7c478bd9Sstevel@tonic-gate sbd_dev_stat32_t *ds32p = &dstat32p->s_stat[i]; 4522*7c478bd9Sstevel@tonic-gate 4523*7c478bd9Sstevel@tonic-gate /* 4524*7c478bd9Sstevel@tonic-gate * copy common data for the device 4525*7c478bd9Sstevel@tonic-gate */ 4526*7c478bd9Sstevel@tonic-gate ds32p->d_cm.ci_type = (int32_t)dsp->d_cm.ci_type; 4527*7c478bd9Sstevel@tonic-gate ds32p->d_cm.ci_unit = (int32_t)dsp->d_cm.ci_unit; 4528*7c478bd9Sstevel@tonic-gate ds32p->d_cm.c_ostate = (int32_t)dsp->d_cm.c_ostate; 4529*7c478bd9Sstevel@tonic-gate ds32p->d_cm.c_cond = (int32_t)dsp->d_cm.c_cond; 4530*7c478bd9Sstevel@tonic-gate ds32p->d_cm.c_busy = (int32_t)dsp->d_cm.c_busy; 4531*7c478bd9Sstevel@tonic-gate ds32p->d_cm.c_time = (time32_t)dsp->d_cm.c_time; 4532*7c478bd9Sstevel@tonic-gate ds32p->d_cm.c_sflags = (int32_t)dsp->d_cm.c_sflags; 4533*7c478bd9Sstevel@tonic-gate (void) strcpy(ds32p->d_cm.ci_name, dsp->d_cm.ci_name); 4534*7c478bd9Sstevel@tonic-gate 4535*7c478bd9Sstevel@tonic-gate /* copy type specific data for the device */ 4536*7c478bd9Sstevel@tonic-gate switch (dsp->d_cm.ci_type) { 4537*7c478bd9Sstevel@tonic-gate 4538*7c478bd9Sstevel@tonic-gate case SBD_COMP_CPU: 4539*7c478bd9Sstevel@tonic-gate ds32p->d_cpu.cs_isbootproc = 4540*7c478bd9Sstevel@tonic-gate (int32_t)dsp->d_cpu.cs_isbootproc; 4541*7c478bd9Sstevel@tonic-gate ds32p->d_cpu.cs_cpuid = 4542*7c478bd9Sstevel@tonic-gate (int32_t)dsp->d_cpu.cs_cpuid; 4543*7c478bd9Sstevel@tonic-gate ds32p->d_cpu.cs_speed = 4544*7c478bd9Sstevel@tonic-gate (int32_t)dsp->d_cpu.cs_speed; 4545*7c478bd9Sstevel@tonic-gate ds32p->d_cpu.cs_ecache = 4546*7c478bd9Sstevel@tonic-gate (int32_t)dsp->d_cpu.cs_ecache; 4547*7c478bd9Sstevel@tonic-gate break; 4548*7c478bd9Sstevel@tonic-gate 4549*7c478bd9Sstevel@tonic-gate case SBD_COMP_MEM: 4550*7c478bd9Sstevel@tonic-gate ds32p->d_mem.ms_type = 4551*7c478bd9Sstevel@tonic-gate (int32_t)dsp->d_mem.ms_type; 4552*7c478bd9Sstevel@tonic-gate ds32p->d_mem.ms_ostate = 4553*7c478bd9Sstevel@tonic-gate (int32_t)dsp->d_mem.ms_ostate; 4554*7c478bd9Sstevel@tonic-gate ds32p->d_mem.ms_cond = 4555*7c478bd9Sstevel@tonic-gate (int32_t)dsp->d_mem.ms_cond; 4556*7c478bd9Sstevel@tonic-gate ds32p->d_mem.ms_interleave = 4557*7c478bd9Sstevel@tonic-gate (uint32_t)dsp->d_mem.ms_interleave; 4558*7c478bd9Sstevel@tonic-gate ds32p->d_mem.ms_basepfn = 4559*7c478bd9Sstevel@tonic-gate (uint32_t)dsp->d_mem.ms_basepfn; 4560*7c478bd9Sstevel@tonic-gate ds32p->d_mem.ms_totpages = 4561*7c478bd9Sstevel@tonic-gate (uint32_t)dsp->d_mem.ms_totpages; 4562*7c478bd9Sstevel@tonic-gate ds32p->d_mem.ms_detpages = 4563*7c478bd9Sstevel@tonic-gate (uint32_t)dsp->d_mem.ms_detpages; 4564*7c478bd9Sstevel@tonic-gate ds32p->d_mem.ms_pageslost = 4565*7c478bd9Sstevel@tonic-gate (int32_t)dsp->d_mem.ms_pageslost; 4566*7c478bd9Sstevel@tonic-gate ds32p->d_mem.ms_managed_pages = 4567*7c478bd9Sstevel@tonic-gate (int32_t)dsp->d_mem.ms_managed_pages; 4568*7c478bd9Sstevel@tonic-gate ds32p->d_mem.ms_noreloc_pages = 4569*7c478bd9Sstevel@tonic-gate (int32_t)dsp->d_mem.ms_noreloc_pages; 4570*7c478bd9Sstevel@tonic-gate ds32p->d_mem.ms_noreloc_first = 4571*7c478bd9Sstevel@tonic-gate (int32_t)dsp->d_mem.ms_noreloc_first; 4572*7c478bd9Sstevel@tonic-gate ds32p->d_mem.ms_noreloc_last = 4573*7c478bd9Sstevel@tonic-gate (int32_t)dsp->d_mem.ms_noreloc_last; 4574*7c478bd9Sstevel@tonic-gate ds32p->d_mem.ms_cage_enabled = 4575*7c478bd9Sstevel@tonic-gate (int32_t)dsp->d_mem.ms_cage_enabled; 4576*7c478bd9Sstevel@tonic-gate ds32p->d_mem.ms_peer_is_target = 4577*7c478bd9Sstevel@tonic-gate (int32_t)dsp->d_mem.ms_peer_is_target; 4578*7c478bd9Sstevel@tonic-gate (void) strcpy(ds32p->d_mem.ms_peer_ap_id, 4579*7c478bd9Sstevel@tonic-gate dsp->d_mem.ms_peer_ap_id); 4580*7c478bd9Sstevel@tonic-gate break; 4581*7c478bd9Sstevel@tonic-gate 4582*7c478bd9Sstevel@tonic-gate 4583*7c478bd9Sstevel@tonic-gate case SBD_COMP_IO: 4584*7c478bd9Sstevel@tonic-gate 4585*7c478bd9Sstevel@tonic-gate ds32p->d_io.is_type = 4586*7c478bd9Sstevel@tonic-gate (int32_t)dsp->d_io.is_type; 4587*7c478bd9Sstevel@tonic-gate ds32p->d_io.is_unsafe_count = 4588*7c478bd9Sstevel@tonic-gate (int32_t)dsp->d_io.is_unsafe_count; 4589*7c478bd9Sstevel@tonic-gate ds32p->d_io.is_referenced = 4590*7c478bd9Sstevel@tonic-gate (int32_t)dsp->d_io.is_referenced; 4591*7c478bd9Sstevel@tonic-gate for (j = 0; j < SBD_MAX_UNSAFE; j++) 4592*7c478bd9Sstevel@tonic-gate ds32p->d_io.is_unsafe_list[j] = 4593*7c478bd9Sstevel@tonic-gate (int32_t) 4594*7c478bd9Sstevel@tonic-gate ds32p->d_io.is_unsafe_list[j]; 4595*7c478bd9Sstevel@tonic-gate bcopy(dsp->d_io.is_pathname, 4596*7c478bd9Sstevel@tonic-gate ds32p->d_io.is_pathname, MAXPATHLEN); 4597*7c478bd9Sstevel@tonic-gate break; 4598*7c478bd9Sstevel@tonic-gate 4599*7c478bd9Sstevel@tonic-gate case SBD_COMP_CMP: 4600*7c478bd9Sstevel@tonic-gate /* copy sbd_cmp_stat_t structure members */ 4601*7c478bd9Sstevel@tonic-gate bcopy(&dsp->d_cmp.ps_cpuid[0], 4602*7c478bd9Sstevel@tonic-gate &ds32p->d_cmp.ps_cpuid[0], 4603*7c478bd9Sstevel@tonic-gate sizeof (ds32p->d_cmp.ps_cpuid)); 4604*7c478bd9Sstevel@tonic-gate ds32p->d_cmp.ps_ncores = 4605*7c478bd9Sstevel@tonic-gate (int32_t)dsp->d_cmp.ps_ncores; 4606*7c478bd9Sstevel@tonic-gate ds32p->d_cmp.ps_speed = 4607*7c478bd9Sstevel@tonic-gate (int32_t)dsp->d_cmp.ps_speed; 4608*7c478bd9Sstevel@tonic-gate ds32p->d_cmp.ps_ecache = 4609*7c478bd9Sstevel@tonic-gate (int32_t)dsp->d_cmp.ps_ecache; 4610*7c478bd9Sstevel@tonic-gate break; 4611*7c478bd9Sstevel@tonic-gate 4612*7c478bd9Sstevel@tonic-gate default: 4613*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 4614*7c478bd9Sstevel@tonic-gate "sbd:%s: unknown dev type (%d)", f, 4615*7c478bd9Sstevel@tonic-gate (int)dsp->d_cm.c_id.c_type); 4616*7c478bd9Sstevel@tonic-gate break; 4617*7c478bd9Sstevel@tonic-gate } 4618*7c478bd9Sstevel@tonic-gate } 4619*7c478bd9Sstevel@tonic-gate 4620*7c478bd9Sstevel@tonic-gate if (ddi_copyout((void *)dstat32p, 4621*7c478bd9Sstevel@tonic-gate cmdp->cmd_stat.s_statp, sz32, mode) != 0) { 4622*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 4623*7c478bd9Sstevel@tonic-gate "sbd:%s: failed to copyout status " 4624*7c478bd9Sstevel@tonic-gate "for board %d", f, sbp->sb_num); 4625*7c478bd9Sstevel@tonic-gate SBD_SET_ERRNO(SBD_HD2ERR(hp), EFAULT); 4626*7c478bd9Sstevel@tonic-gate } 4627*7c478bd9Sstevel@tonic-gate } else 4628*7c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */ 4629*7c478bd9Sstevel@tonic-gate if (ddi_copyout((void *)dstatp, cmdp->cmd_stat.s_statp, 4630*7c478bd9Sstevel@tonic-gate sz, mode) != 0) { 4631*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 4632*7c478bd9Sstevel@tonic-gate "sbd:%s: failed to copyout status for board %d", 4633*7c478bd9Sstevel@tonic-gate f, sbp->sb_num); 4634*7c478bd9Sstevel@tonic-gate SBD_SET_ERRNO(SBD_HD2ERR(hp), EFAULT); 4635*7c478bd9Sstevel@tonic-gate } 4636*7c478bd9Sstevel@tonic-gate 4637*7c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 4638*7c478bd9Sstevel@tonic-gate if (sz32 != 0) 4639*7c478bd9Sstevel@tonic-gate kmem_free(dstat32p, sz32); 4640*7c478bd9Sstevel@tonic-gate #endif 4641*7c478bd9Sstevel@tonic-gate kmem_free(dstatp, sz); 4642*7c478bd9Sstevel@tonic-gate } 4643*7c478bd9Sstevel@tonic-gate 4644*7c478bd9Sstevel@tonic-gate /* 4645*7c478bd9Sstevel@tonic-gate * Called at driver load time to determine the state and condition 4646*7c478bd9Sstevel@tonic-gate * of an existing board in the system. 4647*7c478bd9Sstevel@tonic-gate */ 4648*7c478bd9Sstevel@tonic-gate static void 4649*7c478bd9Sstevel@tonic-gate sbd_board_discovery(sbd_board_t *sbp) 4650*7c478bd9Sstevel@tonic-gate { 4651*7c478bd9Sstevel@tonic-gate int i; 4652*7c478bd9Sstevel@tonic-gate dev_info_t *dip; 4653*7c478bd9Sstevel@tonic-gate sbd_devset_t devs_lost, devs_attached = 0; 4654*7c478bd9Sstevel@tonic-gate extern kmutex_t cpu_lock; 4655*7c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 4656*7c478bd9Sstevel@tonic-gate static fn_t f = "sbd_board_discovery"; 4657*7c478bd9Sstevel@tonic-gate sbderror_t error, *ep; 4658*7c478bd9Sstevel@tonic-gate sbd_handle_t *hp = MACHBD2HD(sbp); 4659*7c478bd9Sstevel@tonic-gate 4660*7c478bd9Sstevel@tonic-gate if (SBD_DEVS_PRESENT(sbp) == 0) { 4661*7c478bd9Sstevel@tonic-gate PR_ALL("%s: board %d has no devices present\n", 4662*7c478bd9Sstevel@tonic-gate f, sbp->sb_num); 4663*7c478bd9Sstevel@tonic-gate return; 4664*7c478bd9Sstevel@tonic-gate } 4665*7c478bd9Sstevel@tonic-gate 4666*7c478bd9Sstevel@tonic-gate ep = &error; 4667*7c478bd9Sstevel@tonic-gate bzero(ep, sizeof (sbderror_t)); 4668*7c478bd9Sstevel@tonic-gate 4669*7c478bd9Sstevel@tonic-gate /* 4670*7c478bd9Sstevel@tonic-gate * Check for existence of cpus. 4671*7c478bd9Sstevel@tonic-gate */ 4672*7c478bd9Sstevel@tonic-gate 4673*7c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 4674*7c478bd9Sstevel@tonic-gate 4675*7c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_CPU_UNITS_PER_BOARD; i++) { 4676*7c478bd9Sstevel@tonic-gate processorid_t cpuid; 4677*7c478bd9Sstevel@tonic-gate 4678*7c478bd9Sstevel@tonic-gate if (!SBD_DEV_IS_PRESENT(sbp, SBD_COMP_CPU, i)) 4679*7c478bd9Sstevel@tonic-gate continue; 4680*7c478bd9Sstevel@tonic-gate 4681*7c478bd9Sstevel@tonic-gate dip = sbp->sb_devlist[NIX(SBD_COMP_CPU)][i]; 4682*7c478bd9Sstevel@tonic-gate 4683*7c478bd9Sstevel@tonic-gate if (dip != NULL) { 4684*7c478bd9Sstevel@tonic-gate cpuid = sbdp_get_cpuid(hdp, dip); 4685*7c478bd9Sstevel@tonic-gate 4686*7c478bd9Sstevel@tonic-gate if (cpuid < 0) { 4687*7c478bd9Sstevel@tonic-gate SBD_GET_PERR(hdp->h_err, 4688*7c478bd9Sstevel@tonic-gate ep); 4689*7c478bd9Sstevel@tonic-gate continue; 4690*7c478bd9Sstevel@tonic-gate } 4691*7c478bd9Sstevel@tonic-gate 4692*7c478bd9Sstevel@tonic-gate mutex_enter(&cpu_lock); /* needed to call cpu_get() */ 4693*7c478bd9Sstevel@tonic-gate if (cpu_get(cpuid)) { 4694*7c478bd9Sstevel@tonic-gate SBD_DEV_SET_ATTACHED(sbp, SBD_COMP_CPU, i); 4695*7c478bd9Sstevel@tonic-gate DEVSET_ADD(devs_attached, SBD_COMP_CPU, i); 4696*7c478bd9Sstevel@tonic-gate PR_ALL("%s: board %d, cpuid %d - attached\n", 4697*7c478bd9Sstevel@tonic-gate f, sbp->sb_num, cpuid); 4698*7c478bd9Sstevel@tonic-gate } 4699*7c478bd9Sstevel@tonic-gate mutex_exit(&cpu_lock); 4700*7c478bd9Sstevel@tonic-gate sbd_init_cpu_unit(sbp, i); 4701*7c478bd9Sstevel@tonic-gate } 4702*7c478bd9Sstevel@tonic-gate } 4703*7c478bd9Sstevel@tonic-gate 4704*7c478bd9Sstevel@tonic-gate /* 4705*7c478bd9Sstevel@tonic-gate * Check for existence of memory. 4706*7c478bd9Sstevel@tonic-gate */ 4707*7c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_MEM_UNITS_PER_BOARD; i++) { 4708*7c478bd9Sstevel@tonic-gate uint64_t basepa, endpa; 4709*7c478bd9Sstevel@tonic-gate struct memlist *ml; 4710*7c478bd9Sstevel@tonic-gate extern struct memlist *phys_install; 4711*7c478bd9Sstevel@tonic-gate 4712*7c478bd9Sstevel@tonic-gate if (!SBD_DEV_IS_PRESENT(sbp, SBD_COMP_MEM, i)) 4713*7c478bd9Sstevel@tonic-gate continue; 4714*7c478bd9Sstevel@tonic-gate 4715*7c478bd9Sstevel@tonic-gate dip = sbp->sb_devlist[NIX(SBD_COMP_MEM)][i]; 4716*7c478bd9Sstevel@tonic-gate if (dip == NULL) 4717*7c478bd9Sstevel@tonic-gate continue; 4718*7c478bd9Sstevel@tonic-gate 4719*7c478bd9Sstevel@tonic-gate if (sbdphw_get_base_physaddr(hdp, dip, &basepa)) { 4720*7c478bd9Sstevel@tonic-gate /* omit phantom memory controllers on I/O boards */ 4721*7c478bd9Sstevel@tonic-gate if (SBD_DEV_IS_PRESENT(sbp, SBD_COMP_MEM, i)) { 4722*7c478bd9Sstevel@tonic-gate ASSERT(sbp->sb_ndev != 0); 4723*7c478bd9Sstevel@tonic-gate SBD_DEV_CLR_PRESENT(sbp, SBD_COMP_MEM, i); 4724*7c478bd9Sstevel@tonic-gate sbp->sb_ndev--; 4725*7c478bd9Sstevel@tonic-gate } 4726*7c478bd9Sstevel@tonic-gate sbp->sb_devlist[NIX(SBD_COMP_MEM)][i] = NULL; 4727*7c478bd9Sstevel@tonic-gate continue; 4728*7c478bd9Sstevel@tonic-gate } 4729*7c478bd9Sstevel@tonic-gate 4730*7c478bd9Sstevel@tonic-gate /* 4731*7c478bd9Sstevel@tonic-gate * basepa may not be on a alignment boundary, make it so. 4732*7c478bd9Sstevel@tonic-gate */ 4733*7c478bd9Sstevel@tonic-gate if (sbdp_get_mem_alignment(hdp, dip, &endpa)) { 4734*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "%s sbdp_get_mem_alignment fail", f); 4735*7c478bd9Sstevel@tonic-gate continue; 4736*7c478bd9Sstevel@tonic-gate } 4737*7c478bd9Sstevel@tonic-gate 4738*7c478bd9Sstevel@tonic-gate basepa &= ~(endpa - 1); 4739*7c478bd9Sstevel@tonic-gate endpa += basepa; 4740*7c478bd9Sstevel@tonic-gate 4741*7c478bd9Sstevel@tonic-gate /* 4742*7c478bd9Sstevel@tonic-gate * Check if base address is in phys_install. 4743*7c478bd9Sstevel@tonic-gate */ 4744*7c478bd9Sstevel@tonic-gate memlist_read_lock(); 4745*7c478bd9Sstevel@tonic-gate for (ml = phys_install; ml; ml = ml->next) 4746*7c478bd9Sstevel@tonic-gate if ((endpa <= ml->address) || 4747*7c478bd9Sstevel@tonic-gate (basepa >= (ml->address + ml->size))) 4748*7c478bd9Sstevel@tonic-gate continue; 4749*7c478bd9Sstevel@tonic-gate else 4750*7c478bd9Sstevel@tonic-gate break; 4751*7c478bd9Sstevel@tonic-gate memlist_read_unlock(); 4752*7c478bd9Sstevel@tonic-gate 4753*7c478bd9Sstevel@tonic-gate if (ml) { 4754*7c478bd9Sstevel@tonic-gate SBD_DEV_SET_ATTACHED(sbp, SBD_COMP_MEM, i); 4755*7c478bd9Sstevel@tonic-gate DEVSET_ADD(devs_attached, SBD_COMP_MEM, i); 4756*7c478bd9Sstevel@tonic-gate PR_ALL("%s: board %d, mem-unit %d - attached\n", 4757*7c478bd9Sstevel@tonic-gate f, sbp->sb_num, i); 4758*7c478bd9Sstevel@tonic-gate } 4759*7c478bd9Sstevel@tonic-gate sbd_init_mem_unit(sbp, i, ep); 4760*7c478bd9Sstevel@tonic-gate } 4761*7c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 4762*7c478bd9Sstevel@tonic-gate 4763*7c478bd9Sstevel@tonic-gate /* 4764*7c478bd9Sstevel@tonic-gate * If so far we have found an error, we just log it but continue 4765*7c478bd9Sstevel@tonic-gate */ 4766*7c478bd9Sstevel@tonic-gate if (SBD_GET_ERRNO(ep) != 0) 4767*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "%s errno has occurred: errno %d", f, 4768*7c478bd9Sstevel@tonic-gate SBD_GET_ERRNO(ep)); 4769*7c478bd9Sstevel@tonic-gate 4770*7c478bd9Sstevel@tonic-gate /* 4771*7c478bd9Sstevel@tonic-gate * Check for i/o state. 4772*7c478bd9Sstevel@tonic-gate */ 4773*7c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_IO_UNITS_PER_BOARD; i++) { 4774*7c478bd9Sstevel@tonic-gate 4775*7c478bd9Sstevel@tonic-gate if (!SBD_DEV_IS_PRESENT(sbp, SBD_COMP_IO, i)) 4776*7c478bd9Sstevel@tonic-gate continue; 4777*7c478bd9Sstevel@tonic-gate 4778*7c478bd9Sstevel@tonic-gate dip = sbp->sb_devlist[NIX(SBD_COMP_IO)][i]; 4779*7c478bd9Sstevel@tonic-gate if (dip == NULL) 4780*7c478bd9Sstevel@tonic-gate continue; 4781*7c478bd9Sstevel@tonic-gate 4782*7c478bd9Sstevel@tonic-gate ASSERT(e_ddi_branch_held(dip)); 4783*7c478bd9Sstevel@tonic-gate 4784*7c478bd9Sstevel@tonic-gate /* 4785*7c478bd9Sstevel@tonic-gate * XXX Is the devstate check needed ? 4786*7c478bd9Sstevel@tonic-gate */ 4787*7c478bd9Sstevel@tonic-gate if (i_ddi_node_state(dip) >= DS_ATTACHED || 4788*7c478bd9Sstevel@tonic-gate ddi_get_devstate(dip) == DDI_DEVSTATE_UP) { 4789*7c478bd9Sstevel@tonic-gate 4790*7c478bd9Sstevel@tonic-gate /* 4791*7c478bd9Sstevel@tonic-gate * Found it! 4792*7c478bd9Sstevel@tonic-gate */ 4793*7c478bd9Sstevel@tonic-gate SBD_DEV_SET_ATTACHED(sbp, SBD_COMP_IO, i); 4794*7c478bd9Sstevel@tonic-gate DEVSET_ADD(devs_attached, SBD_COMP_IO, i); 4795*7c478bd9Sstevel@tonic-gate PR_ALL("%s: board %d, io-unit %d - attached\n", 4796*7c478bd9Sstevel@tonic-gate f, sbp->sb_num, i); 4797*7c478bd9Sstevel@tonic-gate } 4798*7c478bd9Sstevel@tonic-gate sbd_init_io_unit(sbp, i); 4799*7c478bd9Sstevel@tonic-gate } 4800*7c478bd9Sstevel@tonic-gate 4801*7c478bd9Sstevel@tonic-gate SBD_DEVS_CONFIGURE(sbp, devs_attached); 4802*7c478bd9Sstevel@tonic-gate if (devs_attached && ((devs_lost = SBD_DEVS_UNATTACHED(sbp)) != 0)) { 4803*7c478bd9Sstevel@tonic-gate int ut; 4804*7c478bd9Sstevel@tonic-gate /* 4805*7c478bd9Sstevel@tonic-gate * A prior comment stated that a partially configured 4806*7c478bd9Sstevel@tonic-gate * board was not permitted. The Serengeti architecture 4807*7c478bd9Sstevel@tonic-gate * makes this possible, so the SB_DEVS_DISCONNECT 4808*7c478bd9Sstevel@tonic-gate * at the end of this block has been removed. 4809*7c478bd9Sstevel@tonic-gate */ 4810*7c478bd9Sstevel@tonic-gate 4811*7c478bd9Sstevel@tonic-gate PR_ALL("%s: some devices not configured (0x%x)...\n", 4812*7c478bd9Sstevel@tonic-gate f, devs_lost); 4813*7c478bd9Sstevel@tonic-gate 4814*7c478bd9Sstevel@tonic-gate for (ut = 0; ut < MAX_CPU_UNITS_PER_BOARD; ut++) 4815*7c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devs_lost, SBD_COMP_CPU, ut)) { 4816*7c478bd9Sstevel@tonic-gate SBD_DEVICE_TRANSITION(sbp, SBD_COMP_CPU, 4817*7c478bd9Sstevel@tonic-gate ut, SBD_STATE_UNCONFIGURED); 4818*7c478bd9Sstevel@tonic-gate } 4819*7c478bd9Sstevel@tonic-gate 4820*7c478bd9Sstevel@tonic-gate for (ut = 0; ut < MAX_MEM_UNITS_PER_BOARD; ut++) 4821*7c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devs_lost, SBD_COMP_MEM, ut)) { 4822*7c478bd9Sstevel@tonic-gate SBD_DEVICE_TRANSITION(sbp, SBD_COMP_MEM, 4823*7c478bd9Sstevel@tonic-gate ut, SBD_STATE_UNCONFIGURED); 4824*7c478bd9Sstevel@tonic-gate } 4825*7c478bd9Sstevel@tonic-gate 4826*7c478bd9Sstevel@tonic-gate for (ut = 0; ut < MAX_IO_UNITS_PER_BOARD; ut++) 4827*7c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devs_lost, SBD_COMP_IO, ut)) { 4828*7c478bd9Sstevel@tonic-gate SBD_DEVICE_TRANSITION(sbp, SBD_COMP_IO, 4829*7c478bd9Sstevel@tonic-gate ut, SBD_STATE_UNCONFIGURED); 4830*7c478bd9Sstevel@tonic-gate } 4831*7c478bd9Sstevel@tonic-gate } 4832*7c478bd9Sstevel@tonic-gate } 4833*7c478bd9Sstevel@tonic-gate 4834*7c478bd9Sstevel@tonic-gate static int 4835*7c478bd9Sstevel@tonic-gate hold_rele_branch(dev_info_t *rdip, void *arg) 4836*7c478bd9Sstevel@tonic-gate { 4837*7c478bd9Sstevel@tonic-gate walk_tree_t *wp = (walk_tree_t *)arg; 4838*7c478bd9Sstevel@tonic-gate 4839*7c478bd9Sstevel@tonic-gate ASSERT(wp && (wp->hold == 0 || wp->hold == 1)); 4840*7c478bd9Sstevel@tonic-gate 4841*7c478bd9Sstevel@tonic-gate switch (get_node_type(wp->sbp, rdip, NULL)) { 4842*7c478bd9Sstevel@tonic-gate case SBD_COMP_CMP: 4843*7c478bd9Sstevel@tonic-gate case SBD_COMP_MEM: 4844*7c478bd9Sstevel@tonic-gate case SBD_COMP_IO: 4845*7c478bd9Sstevel@tonic-gate break; 4846*7c478bd9Sstevel@tonic-gate case SBD_COMP_CPU: 4847*7c478bd9Sstevel@tonic-gate 4848*7c478bd9Sstevel@tonic-gate /* 4849*7c478bd9Sstevel@tonic-gate * All CPU nodes under CMP nodes should have 4850*7c478bd9Sstevel@tonic-gate * gotten pruned when the CMP node was first 4851*7c478bd9Sstevel@tonic-gate * encountered. 4852*7c478bd9Sstevel@tonic-gate */ 4853*7c478bd9Sstevel@tonic-gate ASSERT(!sbd_is_cmp_child(rdip)); 4854*7c478bd9Sstevel@tonic-gate 4855*7c478bd9Sstevel@tonic-gate break; 4856*7c478bd9Sstevel@tonic-gate 4857*7c478bd9Sstevel@tonic-gate case SBD_COMP_UNKNOWN: 4858*7c478bd9Sstevel@tonic-gate /* Not of interest to us */ 4859*7c478bd9Sstevel@tonic-gate return (DDI_WALK_CONTINUE); 4860*7c478bd9Sstevel@tonic-gate default: 4861*7c478bd9Sstevel@tonic-gate ASSERT(0); 4862*7c478bd9Sstevel@tonic-gate return (DDI_WALK_PRUNECHILD); 4863*7c478bd9Sstevel@tonic-gate } 4864*7c478bd9Sstevel@tonic-gate 4865*7c478bd9Sstevel@tonic-gate if (wp->hold) { 4866*7c478bd9Sstevel@tonic-gate ASSERT(!e_ddi_branch_held(rdip)); 4867*7c478bd9Sstevel@tonic-gate e_ddi_branch_hold(rdip); 4868*7c478bd9Sstevel@tonic-gate } else { 4869*7c478bd9Sstevel@tonic-gate ASSERT(e_ddi_branch_held(rdip)); 4870*7c478bd9Sstevel@tonic-gate e_ddi_branch_rele(rdip); 4871*7c478bd9Sstevel@tonic-gate } 4872*7c478bd9Sstevel@tonic-gate 4873*7c478bd9Sstevel@tonic-gate return (DDI_WALK_PRUNECHILD); 4874*7c478bd9Sstevel@tonic-gate } 4875*7c478bd9Sstevel@tonic-gate 4876*7c478bd9Sstevel@tonic-gate static void 4877*7c478bd9Sstevel@tonic-gate sbd_board_init(sbd_board_t *sbp, sbd_softstate_t *softsp, 4878*7c478bd9Sstevel@tonic-gate int bd, dev_info_t *top_dip, int wnode) 4879*7c478bd9Sstevel@tonic-gate { 4880*7c478bd9Sstevel@tonic-gate int i; 4881*7c478bd9Sstevel@tonic-gate dev_info_t *pdip; 4882*7c478bd9Sstevel@tonic-gate int circ; 4883*7c478bd9Sstevel@tonic-gate walk_tree_t walk = {0}; 4884*7c478bd9Sstevel@tonic-gate 4885*7c478bd9Sstevel@tonic-gate mutex_init(&sbp->sb_mutex, NULL, MUTEX_DRIVER, NULL); 4886*7c478bd9Sstevel@tonic-gate mutex_init(&sbp->sb_flags_mutex, NULL, MUTEX_DRIVER, NULL); 4887*7c478bd9Sstevel@tonic-gate mutex_init(&sbp->sb_slock, NULL, MUTEX_DRIVER, NULL); 4888*7c478bd9Sstevel@tonic-gate 4889*7c478bd9Sstevel@tonic-gate sbp->sb_ref = 0; 4890*7c478bd9Sstevel@tonic-gate sbp->sb_num = bd; 4891*7c478bd9Sstevel@tonic-gate sbp->sb_time = gethrestime_sec(); 4892*7c478bd9Sstevel@tonic-gate /* 4893*7c478bd9Sstevel@tonic-gate * For serengeti, top_dip doesn't need to be held because 4894*7c478bd9Sstevel@tonic-gate * sbp i.e. sbd_board_t will be destroyed in sbd_teardown_instance() 4895*7c478bd9Sstevel@tonic-gate * before top_dip detaches. For Daktari, top_dip is the 4896*7c478bd9Sstevel@tonic-gate * root node which never has to be held. 4897*7c478bd9Sstevel@tonic-gate */ 4898*7c478bd9Sstevel@tonic-gate sbp->sb_topdip = top_dip; 4899*7c478bd9Sstevel@tonic-gate sbp->sb_cpuid = -1; 4900*7c478bd9Sstevel@tonic-gate sbp->sb_softsp = (void *) softsp; 4901*7c478bd9Sstevel@tonic-gate sbp->sb_cond = SBD_COND_UNKNOWN; 4902*7c478bd9Sstevel@tonic-gate sbp->sb_wnode = wnode; 4903*7c478bd9Sstevel@tonic-gate sbp->sb_memaccess_ok = 1; 4904*7c478bd9Sstevel@tonic-gate 4905*7c478bd9Sstevel@tonic-gate ASSERT(MAX_IO_UNITS_PER_BOARD <= SBD_MAX_UNITS_PER_BOARD); 4906*7c478bd9Sstevel@tonic-gate ASSERT(MAX_CPU_UNITS_PER_BOARD <= SBD_MAX_UNITS_PER_BOARD); 4907*7c478bd9Sstevel@tonic-gate ASSERT(MAX_MEM_UNITS_PER_BOARD <= SBD_MAX_UNITS_PER_BOARD); 4908*7c478bd9Sstevel@tonic-gate 4909*7c478bd9Sstevel@tonic-gate /* 4910*7c478bd9Sstevel@tonic-gate * Allocate the devlist for cpus. 4911*7c478bd9Sstevel@tonic-gate */ 4912*7c478bd9Sstevel@tonic-gate sbp->sb_devlist[NIX(SBD_COMP_CPU)] = GETSTRUCT(dev_info_t *, 4913*7c478bd9Sstevel@tonic-gate MAX_CPU_UNITS_PER_BOARD); 4914*7c478bd9Sstevel@tonic-gate 4915*7c478bd9Sstevel@tonic-gate /* 4916*7c478bd9Sstevel@tonic-gate * Allocate the devlist for mem. 4917*7c478bd9Sstevel@tonic-gate */ 4918*7c478bd9Sstevel@tonic-gate sbp->sb_devlist[NIX(SBD_COMP_MEM)] = GETSTRUCT(dev_info_t *, 4919*7c478bd9Sstevel@tonic-gate MAX_MEM_UNITS_PER_BOARD); 4920*7c478bd9Sstevel@tonic-gate 4921*7c478bd9Sstevel@tonic-gate /* 4922*7c478bd9Sstevel@tonic-gate * Allocate the devlist for io. 4923*7c478bd9Sstevel@tonic-gate */ 4924*7c478bd9Sstevel@tonic-gate sbp->sb_devlist[NIX(SBD_COMP_IO)] = GETSTRUCT(dev_info_t *, 4925*7c478bd9Sstevel@tonic-gate MAX_IO_UNITS_PER_BOARD); 4926*7c478bd9Sstevel@tonic-gate 4927*7c478bd9Sstevel@tonic-gate 4928*7c478bd9Sstevel@tonic-gate sbp->sb_dev[NIX(SBD_COMP_CPU)] = GETSTRUCT(sbd_dev_unit_t, 4929*7c478bd9Sstevel@tonic-gate MAX_CPU_UNITS_PER_BOARD); 4930*7c478bd9Sstevel@tonic-gate 4931*7c478bd9Sstevel@tonic-gate sbp->sb_dev[NIX(SBD_COMP_MEM)] = GETSTRUCT(sbd_dev_unit_t, 4932*7c478bd9Sstevel@tonic-gate MAX_MEM_UNITS_PER_BOARD); 4933*7c478bd9Sstevel@tonic-gate 4934*7c478bd9Sstevel@tonic-gate sbp->sb_dev[NIX(SBD_COMP_IO)] = GETSTRUCT(sbd_dev_unit_t, 4935*7c478bd9Sstevel@tonic-gate MAX_IO_UNITS_PER_BOARD); 4936*7c478bd9Sstevel@tonic-gate 4937*7c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_CPU_UNITS_PER_BOARD; i++) { 4938*7c478bd9Sstevel@tonic-gate sbp->sb_cpupath[i] = kmem_zalloc(MAXPATHLEN, KM_SLEEP); 4939*7c478bd9Sstevel@tonic-gate } 4940*7c478bd9Sstevel@tonic-gate 4941*7c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_MEM_UNITS_PER_BOARD; i++) { 4942*7c478bd9Sstevel@tonic-gate sbp->sb_mempath[i] = kmem_zalloc(MAXPATHLEN, KM_SLEEP); 4943*7c478bd9Sstevel@tonic-gate } 4944*7c478bd9Sstevel@tonic-gate 4945*7c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_IO_UNITS_PER_BOARD; i++) { 4946*7c478bd9Sstevel@tonic-gate sbp->sb_iopath[i] = kmem_zalloc(MAXPATHLEN, KM_SLEEP); 4947*7c478bd9Sstevel@tonic-gate } 4948*7c478bd9Sstevel@tonic-gate 4949*7c478bd9Sstevel@tonic-gate /* 4950*7c478bd9Sstevel@tonic-gate * Walk the device tree, find all top dips on this board and 4951*7c478bd9Sstevel@tonic-gate * hold the branches rooted at them 4952*7c478bd9Sstevel@tonic-gate */ 4953*7c478bd9Sstevel@tonic-gate ASSERT(sbp->sb_topdip); 4954*7c478bd9Sstevel@tonic-gate pdip = ddi_get_parent(sbp->sb_topdip); 4955*7c478bd9Sstevel@tonic-gate if (pdip) 4956*7c478bd9Sstevel@tonic-gate ndi_devi_enter(pdip, &circ); 4957*7c478bd9Sstevel@tonic-gate walk.sbp = sbp; 4958*7c478bd9Sstevel@tonic-gate walk.hold = 1; 4959*7c478bd9Sstevel@tonic-gate ddi_walk_devs(sbp->sb_topdip, hold_rele_branch, (void *)&walk); 4960*7c478bd9Sstevel@tonic-gate if (pdip) 4961*7c478bd9Sstevel@tonic-gate ndi_devi_exit(pdip, circ); 4962*7c478bd9Sstevel@tonic-gate 4963*7c478bd9Sstevel@tonic-gate /* 4964*7c478bd9Sstevel@tonic-gate * Initialize the devlists 4965*7c478bd9Sstevel@tonic-gate */ 4966*7c478bd9Sstevel@tonic-gate if (sbd_init_devlists(sbp) == 0) { 4967*7c478bd9Sstevel@tonic-gate SBD_BOARD_TRANSITION(sbp, SBD_STATE_EMPTY); 4968*7c478bd9Sstevel@tonic-gate } else { 4969*7c478bd9Sstevel@tonic-gate /* 4970*7c478bd9Sstevel@tonic-gate * Couldn't have made it down here without 4971*7c478bd9Sstevel@tonic-gate * having found at least one device. 4972*7c478bd9Sstevel@tonic-gate */ 4973*7c478bd9Sstevel@tonic-gate ASSERT(SBD_DEVS_PRESENT(sbp) != 0); 4974*7c478bd9Sstevel@tonic-gate /* 4975*7c478bd9Sstevel@tonic-gate * Check the state of any possible devices on the 4976*7c478bd9Sstevel@tonic-gate * board. 4977*7c478bd9Sstevel@tonic-gate */ 4978*7c478bd9Sstevel@tonic-gate sbd_board_discovery(sbp); 4979*7c478bd9Sstevel@tonic-gate 4980*7c478bd9Sstevel@tonic-gate if (SBD_DEVS_UNATTACHED(sbp) == 0) { 4981*7c478bd9Sstevel@tonic-gate /* 4982*7c478bd9Sstevel@tonic-gate * The board has no unattached devices, therefore 4983*7c478bd9Sstevel@tonic-gate * by reason of insanity it must be configured! 4984*7c478bd9Sstevel@tonic-gate */ 4985*7c478bd9Sstevel@tonic-gate SBD_BOARD_TRANSITION(sbp, SBD_STATE_CONFIGURED); 4986*7c478bd9Sstevel@tonic-gate sbp->sb_cond = SBD_COND_OK; 4987*7c478bd9Sstevel@tonic-gate } else if (SBD_DEVS_ATTACHED(sbp)) { 4988*7c478bd9Sstevel@tonic-gate SBD_BOARD_TRANSITION(sbp, SBD_STATE_PARTIAL); 4989*7c478bd9Sstevel@tonic-gate } else { 4990*7c478bd9Sstevel@tonic-gate SBD_BOARD_TRANSITION(sbp, SBD_STATE_CONNECTED); 4991*7c478bd9Sstevel@tonic-gate } 4992*7c478bd9Sstevel@tonic-gate } 4993*7c478bd9Sstevel@tonic-gate } 4994*7c478bd9Sstevel@tonic-gate 4995*7c478bd9Sstevel@tonic-gate static void 4996*7c478bd9Sstevel@tonic-gate sbd_board_destroy(sbd_board_t *sbp) 4997*7c478bd9Sstevel@tonic-gate { 4998*7c478bd9Sstevel@tonic-gate int i; 4999*7c478bd9Sstevel@tonic-gate dev_info_t *pdip; 5000*7c478bd9Sstevel@tonic-gate int circ; 5001*7c478bd9Sstevel@tonic-gate walk_tree_t walk = {0}; 5002*7c478bd9Sstevel@tonic-gate 5003*7c478bd9Sstevel@tonic-gate SBD_BOARD_TRANSITION(sbp, SBD_STATE_EMPTY); 5004*7c478bd9Sstevel@tonic-gate 5005*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 5006*7c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_MEM_UNITS_PER_BOARD; i++) { 5007*7c478bd9Sstevel@tonic-gate sbd_mem_unit_t *mp; 5008*7c478bd9Sstevel@tonic-gate 5009*7c478bd9Sstevel@tonic-gate mp = SBD_GET_BOARD_MEMUNIT(sbp, i); 5010*7c478bd9Sstevel@tonic-gate ASSERT(mp->sbm_mlist == NULL); 5011*7c478bd9Sstevel@tonic-gate } 5012*7c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 5013*7c478bd9Sstevel@tonic-gate 5014*7c478bd9Sstevel@tonic-gate /* 5015*7c478bd9Sstevel@tonic-gate * Free up MEM unit structs. 5016*7c478bd9Sstevel@tonic-gate */ 5017*7c478bd9Sstevel@tonic-gate FREESTRUCT(sbp->sb_dev[NIX(SBD_COMP_MEM)], 5018*7c478bd9Sstevel@tonic-gate sbd_dev_unit_t, MAX_MEM_UNITS_PER_BOARD); 5019*7c478bd9Sstevel@tonic-gate sbp->sb_dev[NIX(SBD_COMP_MEM)] = NULL; 5020*7c478bd9Sstevel@tonic-gate 5021*7c478bd9Sstevel@tonic-gate /* 5022*7c478bd9Sstevel@tonic-gate * Free up CPU unit structs. 5023*7c478bd9Sstevel@tonic-gate */ 5024*7c478bd9Sstevel@tonic-gate FREESTRUCT(sbp->sb_dev[NIX(SBD_COMP_CPU)], 5025*7c478bd9Sstevel@tonic-gate sbd_dev_unit_t, MAX_CPU_UNITS_PER_BOARD); 5026*7c478bd9Sstevel@tonic-gate sbp->sb_dev[NIX(SBD_COMP_CPU)] = NULL; 5027*7c478bd9Sstevel@tonic-gate 5028*7c478bd9Sstevel@tonic-gate /* 5029*7c478bd9Sstevel@tonic-gate * Free up IO unit structs. 5030*7c478bd9Sstevel@tonic-gate */ 5031*7c478bd9Sstevel@tonic-gate FREESTRUCT(sbp->sb_dev[NIX(SBD_COMP_IO)], 5032*7c478bd9Sstevel@tonic-gate sbd_dev_unit_t, MAX_IO_UNITS_PER_BOARD); 5033*7c478bd9Sstevel@tonic-gate sbp->sb_dev[NIX(SBD_COMP_IO)] = NULL; 5034*7c478bd9Sstevel@tonic-gate 5035*7c478bd9Sstevel@tonic-gate /* 5036*7c478bd9Sstevel@tonic-gate * free up CPU devlists. 5037*7c478bd9Sstevel@tonic-gate */ 5038*7c478bd9Sstevel@tonic-gate 5039*7c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_CPU_UNITS_PER_BOARD; i++) { 5040*7c478bd9Sstevel@tonic-gate kmem_free((caddr_t)sbp->sb_cpupath[i], MAXPATHLEN); 5041*7c478bd9Sstevel@tonic-gate } 5042*7c478bd9Sstevel@tonic-gate FREESTRUCT(sbp->sb_devlist[NIX(SBD_COMP_CPU)], dev_info_t *, 5043*7c478bd9Sstevel@tonic-gate MAX_CPU_UNITS_PER_BOARD); 5044*7c478bd9Sstevel@tonic-gate sbp->sb_devlist[NIX(SBD_COMP_CPU)] = NULL; 5045*7c478bd9Sstevel@tonic-gate 5046*7c478bd9Sstevel@tonic-gate /* 5047*7c478bd9Sstevel@tonic-gate * free up MEM devlists. 5048*7c478bd9Sstevel@tonic-gate */ 5049*7c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_MEM_UNITS_PER_BOARD; i++) { 5050*7c478bd9Sstevel@tonic-gate kmem_free((caddr_t)sbp->sb_mempath[i], MAXPATHLEN); 5051*7c478bd9Sstevel@tonic-gate } 5052*7c478bd9Sstevel@tonic-gate FREESTRUCT(sbp->sb_devlist[NIX(SBD_COMP_MEM)], dev_info_t *, 5053*7c478bd9Sstevel@tonic-gate MAX_MEM_UNITS_PER_BOARD); 5054*7c478bd9Sstevel@tonic-gate sbp->sb_devlist[NIX(SBD_COMP_MEM)] = NULL; 5055*7c478bd9Sstevel@tonic-gate 5056*7c478bd9Sstevel@tonic-gate /* 5057*7c478bd9Sstevel@tonic-gate * free up IO devlists. 5058*7c478bd9Sstevel@tonic-gate */ 5059*7c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_IO_UNITS_PER_BOARD; i++) { 5060*7c478bd9Sstevel@tonic-gate kmem_free((caddr_t)sbp->sb_iopath[i], MAXPATHLEN); 5061*7c478bd9Sstevel@tonic-gate } 5062*7c478bd9Sstevel@tonic-gate FREESTRUCT(sbp->sb_devlist[NIX(SBD_COMP_IO)], dev_info_t *, 5063*7c478bd9Sstevel@tonic-gate MAX_IO_UNITS_PER_BOARD); 5064*7c478bd9Sstevel@tonic-gate sbp->sb_devlist[NIX(SBD_COMP_IO)] = NULL; 5065*7c478bd9Sstevel@tonic-gate 5066*7c478bd9Sstevel@tonic-gate /* 5067*7c478bd9Sstevel@tonic-gate * Release all branches held earlier 5068*7c478bd9Sstevel@tonic-gate */ 5069*7c478bd9Sstevel@tonic-gate ASSERT(sbp->sb_topdip); 5070*7c478bd9Sstevel@tonic-gate pdip = ddi_get_parent(sbp->sb_topdip); 5071*7c478bd9Sstevel@tonic-gate if (pdip) 5072*7c478bd9Sstevel@tonic-gate ndi_devi_enter(pdip, &circ); 5073*7c478bd9Sstevel@tonic-gate walk.sbp = sbp; 5074*7c478bd9Sstevel@tonic-gate walk.hold = 0; 5075*7c478bd9Sstevel@tonic-gate ddi_walk_devs(sbp->sb_topdip, hold_rele_branch, (void *)&walk); 5076*7c478bd9Sstevel@tonic-gate if (pdip) 5077*7c478bd9Sstevel@tonic-gate ndi_devi_exit(pdip, circ); 5078*7c478bd9Sstevel@tonic-gate 5079*7c478bd9Sstevel@tonic-gate mutex_destroy(&sbp->sb_slock); 5080*7c478bd9Sstevel@tonic-gate mutex_destroy(&sbp->sb_flags_mutex); 5081*7c478bd9Sstevel@tonic-gate mutex_destroy(&sbp->sb_mutex); 5082*7c478bd9Sstevel@tonic-gate } 5083*7c478bd9Sstevel@tonic-gate 5084*7c478bd9Sstevel@tonic-gate sbd_comp_type_t 5085*7c478bd9Sstevel@tonic-gate sbd_cm_type(char *name) 5086*7c478bd9Sstevel@tonic-gate { 5087*7c478bd9Sstevel@tonic-gate sbd_comp_type_t type = SBD_COMP_UNKNOWN; 5088*7c478bd9Sstevel@tonic-gate int i; 5089*7c478bd9Sstevel@tonic-gate 5090*7c478bd9Sstevel@tonic-gate /* look up type in table */ 5091*7c478bd9Sstevel@tonic-gate for (i = 0; SBD_COMP(i) != SBD_COMP_UNKNOWN; i++) { 5092*7c478bd9Sstevel@tonic-gate if (strcmp(name, SBD_OTYPE(i)) == 0) { 5093*7c478bd9Sstevel@tonic-gate type = SBD_COMP(i); 5094*7c478bd9Sstevel@tonic-gate break; 5095*7c478bd9Sstevel@tonic-gate } 5096*7c478bd9Sstevel@tonic-gate } 5097*7c478bd9Sstevel@tonic-gate 5098*7c478bd9Sstevel@tonic-gate return (type); 5099*7c478bd9Sstevel@tonic-gate } 5100*7c478bd9Sstevel@tonic-gate 5101*7c478bd9Sstevel@tonic-gate /* 5102*7c478bd9Sstevel@tonic-gate * There are certain cases where obp marks components as failed 5103*7c478bd9Sstevel@tonic-gate * If the status is ok the node won't have any status property. It 5104*7c478bd9Sstevel@tonic-gate * is only there if the status is other than ok. 5105*7c478bd9Sstevel@tonic-gate * 5106*7c478bd9Sstevel@tonic-gate * The translation is as follows: 5107*7c478bd9Sstevel@tonic-gate * If there is no status prop, the the cond is SBD_COND_OK 5108*7c478bd9Sstevel@tonic-gate * If we find a status prop but can't get to it then cond is SBD_COND_UNKNOWN 5109*7c478bd9Sstevel@tonic-gate * if we find a stat and it is failed the cond is SBD_COND_FAILED 5110*7c478bd9Sstevel@tonic-gate * If the stat is disabled, the cond is SBD_COND_UNUSABLE 5111*7c478bd9Sstevel@tonic-gate * Otherwise we return con as SBD_COND_OK 5112*7c478bd9Sstevel@tonic-gate */ 5113*7c478bd9Sstevel@tonic-gate sbd_cond_t 5114*7c478bd9Sstevel@tonic-gate sbd_get_comp_cond(dev_info_t *dip) 5115*7c478bd9Sstevel@tonic-gate { 5116*7c478bd9Sstevel@tonic-gate int len; 5117*7c478bd9Sstevel@tonic-gate char *status_buf; 5118*7c478bd9Sstevel@tonic-gate static const char *status = "status"; 5119*7c478bd9Sstevel@tonic-gate static const char *failed = "fail"; 5120*7c478bd9Sstevel@tonic-gate static const char *disabled = "disabled"; 5121*7c478bd9Sstevel@tonic-gate 5122*7c478bd9Sstevel@tonic-gate if (dip == NULL) { 5123*7c478bd9Sstevel@tonic-gate PR_BYP("dip is NULL\n"); 5124*7c478bd9Sstevel@tonic-gate return (SBD_COND_UNKNOWN); 5125*7c478bd9Sstevel@tonic-gate } 5126*7c478bd9Sstevel@tonic-gate 5127*7c478bd9Sstevel@tonic-gate if (ddi_getproplen(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 5128*7c478bd9Sstevel@tonic-gate (char *)status, &len) != DDI_PROP_SUCCESS) { 5129*7c478bd9Sstevel@tonic-gate PR_CPU("status in sbd is ok\n"); 5130*7c478bd9Sstevel@tonic-gate return (SBD_COND_OK); 5131*7c478bd9Sstevel@tonic-gate } 5132*7c478bd9Sstevel@tonic-gate 5133*7c478bd9Sstevel@tonic-gate status_buf = kmem_zalloc(sizeof (char) * OBP_MAXPROPNAME, KM_SLEEP); 5134*7c478bd9Sstevel@tonic-gate if (ddi_getlongprop_buf(DDI_DEV_T_NONE, dip, DDI_PROP_DONTPASS, 5135*7c478bd9Sstevel@tonic-gate (char *)status, status_buf, &len) != DDI_PROP_SUCCESS) { 5136*7c478bd9Sstevel@tonic-gate PR_CPU("status in sbd is unknown\n"); 5137*7c478bd9Sstevel@tonic-gate return (SBD_COND_UNKNOWN); 5138*7c478bd9Sstevel@tonic-gate } 5139*7c478bd9Sstevel@tonic-gate 5140*7c478bd9Sstevel@tonic-gate if (strncmp(status_buf, failed, strlen(failed)) == 0) { 5141*7c478bd9Sstevel@tonic-gate PR_CPU("status in sbd is failed\n"); 5142*7c478bd9Sstevel@tonic-gate kmem_free(status_buf, sizeof (char) * OBP_MAXPROPNAME); 5143*7c478bd9Sstevel@tonic-gate return (SBD_COND_FAILED); 5144*7c478bd9Sstevel@tonic-gate } 5145*7c478bd9Sstevel@tonic-gate 5146*7c478bd9Sstevel@tonic-gate if (strcmp(status_buf, disabled) == 0) { 5147*7c478bd9Sstevel@tonic-gate PR_CPU("status in sbd is unusable\n"); 5148*7c478bd9Sstevel@tonic-gate kmem_free(status_buf, sizeof (char) * OBP_MAXPROPNAME); 5149*7c478bd9Sstevel@tonic-gate return (SBD_COND_UNUSABLE); 5150*7c478bd9Sstevel@tonic-gate } 5151*7c478bd9Sstevel@tonic-gate 5152*7c478bd9Sstevel@tonic-gate kmem_free(status_buf, sizeof (char) * OBP_MAXPROPNAME); 5153*7c478bd9Sstevel@tonic-gate return (SBD_COND_OK); 5154*7c478bd9Sstevel@tonic-gate } 5155*7c478bd9Sstevel@tonic-gate 5156*7c478bd9Sstevel@tonic-gate #ifdef SBD_DEBUG_ERRS 5157*7c478bd9Sstevel@tonic-gate 5158*7c478bd9Sstevel@tonic-gate /* function to simulate errors throughout the sbd code */ 5159*7c478bd9Sstevel@tonic-gate void 5160*7c478bd9Sstevel@tonic-gate sbd_inject_err(int error, sbderror_t *ep, int Errno, int ecode, 5161*7c478bd9Sstevel@tonic-gate char *rsc) 5162*7c478bd9Sstevel@tonic-gate { 5163*7c478bd9Sstevel@tonic-gate static fn_t f = "sbd_inject_err"; 5164*7c478bd9Sstevel@tonic-gate 5165*7c478bd9Sstevel@tonic-gate if (sbd_err_debug == 0) 5166*7c478bd9Sstevel@tonic-gate return; 5167*7c478bd9Sstevel@tonic-gate 5168*7c478bd9Sstevel@tonic-gate if (ep == NULL) { 5169*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "%s ep is NULL", f); 5170*7c478bd9Sstevel@tonic-gate return; 5171*7c478bd9Sstevel@tonic-gate } 5172*7c478bd9Sstevel@tonic-gate 5173*7c478bd9Sstevel@tonic-gate if (SBD_GET_ERRNO(ep) != 0) { 5174*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "%s errno already set to %d", f, 5175*7c478bd9Sstevel@tonic-gate SBD_GET_ERRNO(ep)); 5176*7c478bd9Sstevel@tonic-gate return; 5177*7c478bd9Sstevel@tonic-gate } 5178*7c478bd9Sstevel@tonic-gate 5179*7c478bd9Sstevel@tonic-gate if (SBD_GET_ERR(ep) != 0) { 5180*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "%s code already set to %d", f, 5181*7c478bd9Sstevel@tonic-gate SBD_GET_ERR(ep)); 5182*7c478bd9Sstevel@tonic-gate return; 5183*7c478bd9Sstevel@tonic-gate } 5184*7c478bd9Sstevel@tonic-gate 5185*7c478bd9Sstevel@tonic-gate if ((sbd_err_debug & (1 << error)) != 0) { 5186*7c478bd9Sstevel@tonic-gate ep->e_errno = Errno; 5187*7c478bd9Sstevel@tonic-gate ep->e_code = ecode; 5188*7c478bd9Sstevel@tonic-gate 5189*7c478bd9Sstevel@tonic-gate if (rsc != NULL) 5190*7c478bd9Sstevel@tonic-gate bcopy((caddr_t)rsc, 5191*7c478bd9Sstevel@tonic-gate (caddr_t)ep->e_rsc, 5192*7c478bd9Sstevel@tonic-gate sizeof (ep->e_rsc)); 5193*7c478bd9Sstevel@tonic-gate 5194*7c478bd9Sstevel@tonic-gate if (Errno != 0) 5195*7c478bd9Sstevel@tonic-gate PR_ERR_ERRNO("%s set errno to %d", f, ep->e_errno); 5196*7c478bd9Sstevel@tonic-gate 5197*7c478bd9Sstevel@tonic-gate if (ecode != 0) 5198*7c478bd9Sstevel@tonic-gate PR_ERR_ECODE("%s set ecode to %d", f, ep->e_code); 5199*7c478bd9Sstevel@tonic-gate 5200*7c478bd9Sstevel@tonic-gate if (rsc != NULL) 5201*7c478bd9Sstevel@tonic-gate PR_ERR_RSC("%s set rsc to %s", f, ep->e_rsc); 5202*7c478bd9Sstevel@tonic-gate } 5203*7c478bd9Sstevel@tonic-gate } 5204*7c478bd9Sstevel@tonic-gate #endif 5205