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 * This file contains ddi functions needed during boot and DR. 31*7c478bd9Sstevel@tonic-gate * Many functions in swapgeneric.c can be moved here. 32*7c478bd9Sstevel@tonic-gate * 33*7c478bd9Sstevel@tonic-gate * The object file is currently linked into unix. 34*7c478bd9Sstevel@tonic-gate */ 35*7c478bd9Sstevel@tonic-gate 36*7c478bd9Sstevel@tonic-gate #include <sys/bootconf.h> 37*7c478bd9Sstevel@tonic-gate #include <sys/conf.h> 38*7c478bd9Sstevel@tonic-gate #include <sys/ddi_impldefs.h> 39*7c478bd9Sstevel@tonic-gate #include <sys/ddi_implfuncs.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/hwconf.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/instance.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 43*7c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 44*7c478bd9Sstevel@tonic-gate #include <sys/promif.h> 45*7c478bd9Sstevel@tonic-gate #include <sys/sunndi.h> 46*7c478bd9Sstevel@tonic-gate #include <sys/ndi_impldefs.h> 47*7c478bd9Sstevel@tonic-gate #include <sys/systeminfo.h> 48*7c478bd9Sstevel@tonic-gate #include <sys/hwconf.h> 49*7c478bd9Sstevel@tonic-gate #include <sys/sysevent_impl.h> 50*7c478bd9Sstevel@tonic-gate #include <sys/sunldi_impl.h> 51*7c478bd9Sstevel@tonic-gate #include <sys/disp.h> 52*7c478bd9Sstevel@tonic-gate #include <sys/fm/util.h> 53*7c478bd9Sstevel@tonic-gate 54*7c478bd9Sstevel@tonic-gate extern dev_info_t *top_devinfo; 55*7c478bd9Sstevel@tonic-gate extern dev_info_t *scsi_vhci_dip; 56*7c478bd9Sstevel@tonic-gate extern struct hwc_class *hcl_head; 57*7c478bd9Sstevel@tonic-gate static char *rootname; /* node name of top_devinfo */ 58*7c478bd9Sstevel@tonic-gate 59*7c478bd9Sstevel@tonic-gate /* 60*7c478bd9Sstevel@tonic-gate * This lock must be held while updating devi_sibling pointers of 61*7c478bd9Sstevel@tonic-gate * rootnex immediate children 62*7c478bd9Sstevel@tonic-gate */ 63*7c478bd9Sstevel@tonic-gate kmutex_t global_vhci_lock; 64*7c478bd9Sstevel@tonic-gate 65*7c478bd9Sstevel@tonic-gate major_t mm_major; 66*7c478bd9Sstevel@tonic-gate 67*7c478bd9Sstevel@tonic-gate /* 68*7c478bd9Sstevel@tonic-gate * Forward declarations 69*7c478bd9Sstevel@tonic-gate */ 70*7c478bd9Sstevel@tonic-gate static void impl_create_root_class(void); 71*7c478bd9Sstevel@tonic-gate static void create_devinfo_tree(void); 72*7c478bd9Sstevel@tonic-gate 73*7c478bd9Sstevel@tonic-gate #if defined(__x86) 74*7c478bd9Sstevel@tonic-gate char *bootpath_prop = NULL; 75*7c478bd9Sstevel@tonic-gate char *fstype_prop = NULL; 76*7c478bd9Sstevel@tonic-gate #endif 77*7c478bd9Sstevel@tonic-gate 78*7c478bd9Sstevel@tonic-gate /* 79*7c478bd9Sstevel@tonic-gate * Setup the DDI but don't necessarily init the DDI. This will happen 80*7c478bd9Sstevel@tonic-gate * later once /boot is released. 81*7c478bd9Sstevel@tonic-gate */ 82*7c478bd9Sstevel@tonic-gate void 83*7c478bd9Sstevel@tonic-gate setup_ddi(void) 84*7c478bd9Sstevel@tonic-gate { 85*7c478bd9Sstevel@tonic-gate impl_ddi_init_nodeid(); 86*7c478bd9Sstevel@tonic-gate impl_create_root_class(); 87*7c478bd9Sstevel@tonic-gate create_devinfo_tree(); 88*7c478bd9Sstevel@tonic-gate e_ddi_instance_init(); 89*7c478bd9Sstevel@tonic-gate impl_ddi_callback_init(); 90*7c478bd9Sstevel@tonic-gate log_event_init(); 91*7c478bd9Sstevel@tonic-gate fm_init(); 92*7c478bd9Sstevel@tonic-gate 93*7c478bd9Sstevel@tonic-gate (void) i_ddi_load_drvconf((major_t)-1); 94*7c478bd9Sstevel@tonic-gate 95*7c478bd9Sstevel@tonic-gate ldi_init(); 96*7c478bd9Sstevel@tonic-gate 97*7c478bd9Sstevel@tonic-gate i_ddi_devices_init(); 98*7c478bd9Sstevel@tonic-gate i_ddi_read_devices_files(); 99*7c478bd9Sstevel@tonic-gate } 100*7c478bd9Sstevel@tonic-gate 101*7c478bd9Sstevel@tonic-gate /* 102*7c478bd9Sstevel@tonic-gate * Perform setup actions post startup (i_ddi_io_initialized) 103*7c478bd9Sstevel@tonic-gate */ 104*7c478bd9Sstevel@tonic-gate void 105*7c478bd9Sstevel@tonic-gate setup_ddi_poststartup(void) 106*7c478bd9Sstevel@tonic-gate { 107*7c478bd9Sstevel@tonic-gate extern void i_ddi_start_flush_daemon(void); 108*7c478bd9Sstevel@tonic-gate extern void i_ddi_intr_redist_all_cpus(void); 109*7c478bd9Sstevel@tonic-gate 110*7c478bd9Sstevel@tonic-gate i_ddi_start_flush_daemon(); 111*7c478bd9Sstevel@tonic-gate 112*7c478bd9Sstevel@tonic-gate /* 113*7c478bd9Sstevel@tonic-gate * For platforms that support INTR_WEIGHTED_DIST, we perform a 114*7c478bd9Sstevel@tonic-gate * redistribution at this point (after NICs configured) so that 115*7c478bd9Sstevel@tonic-gate * "isolation" relative to "ddi-intr-weight" occurs. 116*7c478bd9Sstevel@tonic-gate */ 117*7c478bd9Sstevel@tonic-gate i_ddi_intr_redist_all_cpus(); 118*7c478bd9Sstevel@tonic-gate } 119*7c478bd9Sstevel@tonic-gate 120*7c478bd9Sstevel@tonic-gate /* 121*7c478bd9Sstevel@tonic-gate * Create classes and major number bindings for the name of my root. 122*7c478bd9Sstevel@tonic-gate * Called immediately before 'loadrootmodules' 123*7c478bd9Sstevel@tonic-gate */ 124*7c478bd9Sstevel@tonic-gate static void 125*7c478bd9Sstevel@tonic-gate impl_create_root_class(void) 126*7c478bd9Sstevel@tonic-gate { 127*7c478bd9Sstevel@tonic-gate major_t major; 128*7c478bd9Sstevel@tonic-gate size_t size; 129*7c478bd9Sstevel@tonic-gate char *cp; 130*7c478bd9Sstevel@tonic-gate extern struct bootops *bootops; 131*7c478bd9Sstevel@tonic-gate 132*7c478bd9Sstevel@tonic-gate /* 133*7c478bd9Sstevel@tonic-gate * The name for the root nexus is exactly as the manufacturer 134*7c478bd9Sstevel@tonic-gate * placed it in the prom name property. No translation. 135*7c478bd9Sstevel@tonic-gate */ 136*7c478bd9Sstevel@tonic-gate if ((major = ddi_name_to_major("rootnex")) == (major_t)-1) 137*7c478bd9Sstevel@tonic-gate panic("Couldn't find major number for 'rootnex'"); 138*7c478bd9Sstevel@tonic-gate 139*7c478bd9Sstevel@tonic-gate size = (size_t)BOP_GETPROPLEN(bootops, "mfg-name"); 140*7c478bd9Sstevel@tonic-gate rootname = kmem_zalloc(size, KM_SLEEP); 141*7c478bd9Sstevel@tonic-gate (void) BOP_GETPROP(bootops, "mfg-name", rootname); 142*7c478bd9Sstevel@tonic-gate 143*7c478bd9Sstevel@tonic-gate /* 144*7c478bd9Sstevel@tonic-gate * Fix conflict between OBP names and filesystem names. 145*7c478bd9Sstevel@tonic-gate * Substitute '_' for '/' in the name. Ick. This is only 146*7c478bd9Sstevel@tonic-gate * needed for the root node since '/' is not a legal name 147*7c478bd9Sstevel@tonic-gate * character in an OBP device name. 148*7c478bd9Sstevel@tonic-gate */ 149*7c478bd9Sstevel@tonic-gate for (cp = rootname; *cp; cp++) 150*7c478bd9Sstevel@tonic-gate if (*cp == '/') 151*7c478bd9Sstevel@tonic-gate *cp = '_'; 152*7c478bd9Sstevel@tonic-gate 153*7c478bd9Sstevel@tonic-gate /* 154*7c478bd9Sstevel@tonic-gate * Bind rootname to rootnex driver 155*7c478bd9Sstevel@tonic-gate */ 156*7c478bd9Sstevel@tonic-gate if (make_mbind(rootname, major, NULL, mb_hashtab) != 0) { 157*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "A driver or driver alias has already " 158*7c478bd9Sstevel@tonic-gate "registered the name \"%s\". The root nexus needs to " 159*7c478bd9Sstevel@tonic-gate "use this name, and will override the existing entry. " 160*7c478bd9Sstevel@tonic-gate "Please correct /etc/name_to_major and/or " 161*7c478bd9Sstevel@tonic-gate "/etc/driver_aliases and reboot.", rootname); 162*7c478bd9Sstevel@tonic-gate 163*7c478bd9Sstevel@tonic-gate /* 164*7c478bd9Sstevel@tonic-gate * Resort to the emergency measure of blowing away the 165*7c478bd9Sstevel@tonic-gate * existing hash entry and replacing it with rootname's. 166*7c478bd9Sstevel@tonic-gate */ 167*7c478bd9Sstevel@tonic-gate delete_mbind(rootname, mb_hashtab); 168*7c478bd9Sstevel@tonic-gate if (make_mbind(rootname, major, NULL, mb_hashtab) != 0) 169*7c478bd9Sstevel@tonic-gate panic("mb_hashtab: inconsistent state."); 170*7c478bd9Sstevel@tonic-gate } 171*7c478bd9Sstevel@tonic-gate 172*7c478bd9Sstevel@tonic-gate /* 173*7c478bd9Sstevel@tonic-gate * The `platform' or `implementation architecture' name has been 174*7c478bd9Sstevel@tonic-gate * translated by boot to be proper for file system use. It is 175*7c478bd9Sstevel@tonic-gate * the `name' of the platform actually booted. Note the assumption 176*7c478bd9Sstevel@tonic-gate * is that the name will `fit' in the buffer platform (which is 177*7c478bd9Sstevel@tonic-gate * of size SYS_NMLN, which is far bigger than will actually ever 178*7c478bd9Sstevel@tonic-gate * be needed). 179*7c478bd9Sstevel@tonic-gate */ 180*7c478bd9Sstevel@tonic-gate (void) BOP_GETPROP(bootops, "impl-arch-name", platform); 181*7c478bd9Sstevel@tonic-gate 182*7c478bd9Sstevel@tonic-gate #if defined(__x86) 183*7c478bd9Sstevel@tonic-gate /* 184*7c478bd9Sstevel@tonic-gate * Retrieve and honor the bootpath and optional fstype properties 185*7c478bd9Sstevel@tonic-gate */ 186*7c478bd9Sstevel@tonic-gate size = (size_t)BOP_GETPROPLEN(bootops, "bootpath"); 187*7c478bd9Sstevel@tonic-gate if (size != -1) { 188*7c478bd9Sstevel@tonic-gate bootpath_prop = kmem_zalloc(size, KM_SLEEP); 189*7c478bd9Sstevel@tonic-gate (void) BOP_GETPROP(bootops, "bootpath", bootpath_prop); 190*7c478bd9Sstevel@tonic-gate setbootpath(bootpath_prop); 191*7c478bd9Sstevel@tonic-gate } 192*7c478bd9Sstevel@tonic-gate 193*7c478bd9Sstevel@tonic-gate size = (size_t)BOP_GETPROPLEN(bootops, "fstype"); 194*7c478bd9Sstevel@tonic-gate if (size != -1) { 195*7c478bd9Sstevel@tonic-gate fstype_prop = kmem_zalloc(size, KM_SLEEP); 196*7c478bd9Sstevel@tonic-gate (void) BOP_GETPROP(bootops, "fstype", fstype_prop); 197*7c478bd9Sstevel@tonic-gate setbootfstype(fstype_prop); 198*7c478bd9Sstevel@tonic-gate } 199*7c478bd9Sstevel@tonic-gate #endif 200*7c478bd9Sstevel@tonic-gate } 201*7c478bd9Sstevel@tonic-gate 202*7c478bd9Sstevel@tonic-gate /* 203*7c478bd9Sstevel@tonic-gate * Note that this routine does not take into account the endianness 204*7c478bd9Sstevel@tonic-gate * of the host or the device (or PROM) when retrieving properties. 205*7c478bd9Sstevel@tonic-gate */ 206*7c478bd9Sstevel@tonic-gate static int 207*7c478bd9Sstevel@tonic-gate getlongprop_buf(int id, char *name, char *buf, int maxlen) 208*7c478bd9Sstevel@tonic-gate { 209*7c478bd9Sstevel@tonic-gate int size; 210*7c478bd9Sstevel@tonic-gate 211*7c478bd9Sstevel@tonic-gate size = prom_getproplen((dnode_t)id, name); 212*7c478bd9Sstevel@tonic-gate if (size <= 0 || (size > maxlen - 1)) 213*7c478bd9Sstevel@tonic-gate return (-1); 214*7c478bd9Sstevel@tonic-gate 215*7c478bd9Sstevel@tonic-gate if (-1 == prom_getprop((dnode_t)id, name, buf)) 216*7c478bd9Sstevel@tonic-gate return (-1); 217*7c478bd9Sstevel@tonic-gate 218*7c478bd9Sstevel@tonic-gate /* 219*7c478bd9Sstevel@tonic-gate * Workaround for bugid 1085575 - OBP may return a "name" property 220*7c478bd9Sstevel@tonic-gate * without null terminating the string with '\0'. When this occurs, 221*7c478bd9Sstevel@tonic-gate * append a '\0' and return (size + 1). 222*7c478bd9Sstevel@tonic-gate */ 223*7c478bd9Sstevel@tonic-gate if (strcmp("name", name) == 0) { 224*7c478bd9Sstevel@tonic-gate if (buf[size - 1] != '\0') { 225*7c478bd9Sstevel@tonic-gate buf[size] = '\0'; 226*7c478bd9Sstevel@tonic-gate size += 1; 227*7c478bd9Sstevel@tonic-gate } 228*7c478bd9Sstevel@tonic-gate } 229*7c478bd9Sstevel@tonic-gate 230*7c478bd9Sstevel@tonic-gate return (size); 231*7c478bd9Sstevel@tonic-gate } 232*7c478bd9Sstevel@tonic-gate 233*7c478bd9Sstevel@tonic-gate /*ARGSUSED1*/ 234*7c478bd9Sstevel@tonic-gate static int 235*7c478bd9Sstevel@tonic-gate get_neighbors(dev_info_t *di, int flag) 236*7c478bd9Sstevel@tonic-gate { 237*7c478bd9Sstevel@tonic-gate register int nid, snid, cnid; 238*7c478bd9Sstevel@tonic-gate dev_info_t *parent; 239*7c478bd9Sstevel@tonic-gate char buf[OBP_MAXPROPNAME]; 240*7c478bd9Sstevel@tonic-gate 241*7c478bd9Sstevel@tonic-gate if (di == NULL) 242*7c478bd9Sstevel@tonic-gate return (DDI_WALK_CONTINUE); 243*7c478bd9Sstevel@tonic-gate 244*7c478bd9Sstevel@tonic-gate nid = ddi_get_nodeid(di); 245*7c478bd9Sstevel@tonic-gate 246*7c478bd9Sstevel@tonic-gate snid = cnid = 0; 247*7c478bd9Sstevel@tonic-gate switch (flag) { 248*7c478bd9Sstevel@tonic-gate case DDI_WALK_PRUNESIB: 249*7c478bd9Sstevel@tonic-gate cnid = (int)prom_childnode((dnode_t)nid); 250*7c478bd9Sstevel@tonic-gate break; 251*7c478bd9Sstevel@tonic-gate case DDI_WALK_PRUNECHILD: 252*7c478bd9Sstevel@tonic-gate snid = (int)prom_nextnode((dnode_t)nid); 253*7c478bd9Sstevel@tonic-gate break; 254*7c478bd9Sstevel@tonic-gate case 0: 255*7c478bd9Sstevel@tonic-gate snid = (int)prom_nextnode((dnode_t)nid); 256*7c478bd9Sstevel@tonic-gate cnid = (int)prom_childnode((dnode_t)nid); 257*7c478bd9Sstevel@tonic-gate break; 258*7c478bd9Sstevel@tonic-gate default: 259*7c478bd9Sstevel@tonic-gate return (DDI_WALK_TERMINATE); 260*7c478bd9Sstevel@tonic-gate } 261*7c478bd9Sstevel@tonic-gate 262*7c478bd9Sstevel@tonic-gate 263*7c478bd9Sstevel@tonic-gate if (snid && (snid != -1) && ((parent = ddi_get_parent(di)) != NULL)) { 264*7c478bd9Sstevel@tonic-gate /* 265*7c478bd9Sstevel@tonic-gate * add the first sibling that passes check_status() 266*7c478bd9Sstevel@tonic-gate */ 267*7c478bd9Sstevel@tonic-gate for (; snid && (snid != -1); 268*7c478bd9Sstevel@tonic-gate snid = (int)prom_nextnode((dnode_t)snid)) { 269*7c478bd9Sstevel@tonic-gate if (getlongprop_buf(snid, OBP_NAME, buf, 270*7c478bd9Sstevel@tonic-gate sizeof (buf)) > 0) { 271*7c478bd9Sstevel@tonic-gate if (check_status(snid, buf, parent) == 272*7c478bd9Sstevel@tonic-gate DDI_SUCCESS) { 273*7c478bd9Sstevel@tonic-gate (void) ddi_add_child(parent, buf, 274*7c478bd9Sstevel@tonic-gate snid, -1); 275*7c478bd9Sstevel@tonic-gate break; 276*7c478bd9Sstevel@tonic-gate } 277*7c478bd9Sstevel@tonic-gate } 278*7c478bd9Sstevel@tonic-gate } 279*7c478bd9Sstevel@tonic-gate } 280*7c478bd9Sstevel@tonic-gate 281*7c478bd9Sstevel@tonic-gate if (cnid && (cnid != -1)) { 282*7c478bd9Sstevel@tonic-gate /* 283*7c478bd9Sstevel@tonic-gate * add the first child that passes check_status() 284*7c478bd9Sstevel@tonic-gate */ 285*7c478bd9Sstevel@tonic-gate if (getlongprop_buf(cnid, OBP_NAME, buf, sizeof (buf)) > 0) { 286*7c478bd9Sstevel@tonic-gate if (check_status(cnid, buf, di) == DDI_SUCCESS) { 287*7c478bd9Sstevel@tonic-gate (void) ddi_add_child(di, buf, cnid, -1); 288*7c478bd9Sstevel@tonic-gate } else { 289*7c478bd9Sstevel@tonic-gate for (cnid = (int)prom_nextnode((dnode_t)cnid); 290*7c478bd9Sstevel@tonic-gate cnid && (cnid != -1); 291*7c478bd9Sstevel@tonic-gate cnid = (int)prom_nextnode((dnode_t)cnid)) { 292*7c478bd9Sstevel@tonic-gate if (getlongprop_buf(cnid, OBP_NAME, 293*7c478bd9Sstevel@tonic-gate buf, sizeof (buf)) > 0) { 294*7c478bd9Sstevel@tonic-gate if (check_status(cnid, buf, di) 295*7c478bd9Sstevel@tonic-gate == DDI_SUCCESS) { 296*7c478bd9Sstevel@tonic-gate (void) ddi_add_child( 297*7c478bd9Sstevel@tonic-gate di, buf, cnid, -1); 298*7c478bd9Sstevel@tonic-gate break; 299*7c478bd9Sstevel@tonic-gate } 300*7c478bd9Sstevel@tonic-gate } 301*7c478bd9Sstevel@tonic-gate } 302*7c478bd9Sstevel@tonic-gate } 303*7c478bd9Sstevel@tonic-gate } 304*7c478bd9Sstevel@tonic-gate } 305*7c478bd9Sstevel@tonic-gate 306*7c478bd9Sstevel@tonic-gate return (DDI_WALK_CONTINUE); 307*7c478bd9Sstevel@tonic-gate } 308*7c478bd9Sstevel@tonic-gate 309*7c478bd9Sstevel@tonic-gate static void 310*7c478bd9Sstevel@tonic-gate di_dfs(dev_info_t *devi, int (*f)(dev_info_t *, int), caddr_t arg) 311*7c478bd9Sstevel@tonic-gate { 312*7c478bd9Sstevel@tonic-gate (void) (*f)(devi, 0); 313*7c478bd9Sstevel@tonic-gate if (devi) { 314*7c478bd9Sstevel@tonic-gate di_dfs((dev_info_t *)DEVI(devi)->devi_child, f, arg); 315*7c478bd9Sstevel@tonic-gate di_dfs((dev_info_t *)DEVI(devi)->devi_sibling, f, arg); 316*7c478bd9Sstevel@tonic-gate } 317*7c478bd9Sstevel@tonic-gate } 318*7c478bd9Sstevel@tonic-gate 319*7c478bd9Sstevel@tonic-gate dev_info_t * 320*7c478bd9Sstevel@tonic-gate i_ddi_create_branch(dev_info_t *pdip, int nid) 321*7c478bd9Sstevel@tonic-gate { 322*7c478bd9Sstevel@tonic-gate char *buf; 323*7c478bd9Sstevel@tonic-gate dev_info_t *dip = NULL; 324*7c478bd9Sstevel@tonic-gate 325*7c478bd9Sstevel@tonic-gate if (pdip == NULL || nid == OBP_NONODE || nid == OBP_BADNODE) 326*7c478bd9Sstevel@tonic-gate return (NULL); 327*7c478bd9Sstevel@tonic-gate 328*7c478bd9Sstevel@tonic-gate buf = kmem_alloc(OBP_MAXPROPNAME, KM_SLEEP); 329*7c478bd9Sstevel@tonic-gate 330*7c478bd9Sstevel@tonic-gate if (getlongprop_buf(nid, OBP_NAME, buf, OBP_MAXPROPNAME) > 0) { 331*7c478bd9Sstevel@tonic-gate if (check_status(nid, buf, pdip) == DDI_SUCCESS) 332*7c478bd9Sstevel@tonic-gate dip = ddi_add_child(pdip, buf, nid, -1); 333*7c478bd9Sstevel@tonic-gate } 334*7c478bd9Sstevel@tonic-gate 335*7c478bd9Sstevel@tonic-gate kmem_free(buf, OBP_MAXPROPNAME); 336*7c478bd9Sstevel@tonic-gate 337*7c478bd9Sstevel@tonic-gate if (dip == NULL) 338*7c478bd9Sstevel@tonic-gate return (NULL); 339*7c478bd9Sstevel@tonic-gate 340*7c478bd9Sstevel@tonic-gate /* 341*7c478bd9Sstevel@tonic-gate * Don't create any siblings of the branch root, just 342*7c478bd9Sstevel@tonic-gate * children. 343*7c478bd9Sstevel@tonic-gate */ 344*7c478bd9Sstevel@tonic-gate (void) get_neighbors(dip, DDI_WALK_PRUNESIB); 345*7c478bd9Sstevel@tonic-gate 346*7c478bd9Sstevel@tonic-gate di_dfs(ddi_get_child(dip), get_neighbors, 0); 347*7c478bd9Sstevel@tonic-gate 348*7c478bd9Sstevel@tonic-gate return (dip); 349*7c478bd9Sstevel@tonic-gate } 350*7c478bd9Sstevel@tonic-gate 351*7c478bd9Sstevel@tonic-gate static void 352*7c478bd9Sstevel@tonic-gate create_devinfo_tree(void) 353*7c478bd9Sstevel@tonic-gate { 354*7c478bd9Sstevel@tonic-gate major_t major; 355*7c478bd9Sstevel@tonic-gate dnode_t nodeid; 356*7c478bd9Sstevel@tonic-gate 357*7c478bd9Sstevel@tonic-gate i_ddi_node_cache_init(); 358*7c478bd9Sstevel@tonic-gate #if defined(__sparc) 359*7c478bd9Sstevel@tonic-gate nodeid = prom_nextnode(0); 360*7c478bd9Sstevel@tonic-gate #else /* x86 */ 361*7c478bd9Sstevel@tonic-gate nodeid = DEVI_SID_NODEID; 362*7c478bd9Sstevel@tonic-gate #endif 363*7c478bd9Sstevel@tonic-gate top_devinfo = i_ddi_alloc_node(NULL, rootname, 364*7c478bd9Sstevel@tonic-gate nodeid, -1, NULL, KM_SLEEP); 365*7c478bd9Sstevel@tonic-gate ndi_hold_devi(top_devinfo); /* never release the root */ 366*7c478bd9Sstevel@tonic-gate 367*7c478bd9Sstevel@tonic-gate i_ddi_add_devimap(top_devinfo); 368*7c478bd9Sstevel@tonic-gate 369*7c478bd9Sstevel@tonic-gate /* 370*7c478bd9Sstevel@tonic-gate * Bind root node. 371*7c478bd9Sstevel@tonic-gate * This code is special because root node has no parent 372*7c478bd9Sstevel@tonic-gate */ 373*7c478bd9Sstevel@tonic-gate major = ddi_name_to_major("rootnex"); 374*7c478bd9Sstevel@tonic-gate ASSERT(major != (major_t)-1); 375*7c478bd9Sstevel@tonic-gate DEVI(top_devinfo)->devi_major = major; 376*7c478bd9Sstevel@tonic-gate devnamesp[major].dn_head = top_devinfo; 377*7c478bd9Sstevel@tonic-gate i_ddi_set_binding_name(top_devinfo, rootname); 378*7c478bd9Sstevel@tonic-gate i_ddi_set_node_state(top_devinfo, DS_BOUND); 379*7c478bd9Sstevel@tonic-gate 380*7c478bd9Sstevel@tonic-gate /* 381*7c478bd9Sstevel@tonic-gate * Record that devinfos have been made for "rootnex." 382*7c478bd9Sstevel@tonic-gate * di_dfs() is used to read the prom because it doesn't get the 383*7c478bd9Sstevel@tonic-gate * next sibling until the function returns, unlike ddi_walk_devs(). 384*7c478bd9Sstevel@tonic-gate */ 385*7c478bd9Sstevel@tonic-gate di_dfs(ddi_root_node(), get_neighbors, 0); 386*7c478bd9Sstevel@tonic-gate } 387*7c478bd9Sstevel@tonic-gate 388*7c478bd9Sstevel@tonic-gate /* 389*7c478bd9Sstevel@tonic-gate * Init and attach the root node. root node is the first one to be 390*7c478bd9Sstevel@tonic-gate * attached, so the process is somewhat "handcrafted". 391*7c478bd9Sstevel@tonic-gate */ 392*7c478bd9Sstevel@tonic-gate void 393*7c478bd9Sstevel@tonic-gate i_ddi_init_root() 394*7c478bd9Sstevel@tonic-gate { 395*7c478bd9Sstevel@tonic-gate extern int i_ndi_make_spec_children(dev_info_t *, uint_t); 396*7c478bd9Sstevel@tonic-gate 397*7c478bd9Sstevel@tonic-gate #ifdef DDI_PROP_DEBUG 398*7c478bd9Sstevel@tonic-gate (void) ddi_prop_debug(1); /* Enable property debugging */ 399*7c478bd9Sstevel@tonic-gate #endif /* DDI_PROP_DEBUG */ 400*7c478bd9Sstevel@tonic-gate 401*7c478bd9Sstevel@tonic-gate /* 402*7c478bd9Sstevel@tonic-gate * Initialize root node 403*7c478bd9Sstevel@tonic-gate */ 404*7c478bd9Sstevel@tonic-gate if (impl_ddi_sunbus_initchild(top_devinfo) != DDI_SUCCESS) 405*7c478bd9Sstevel@tonic-gate panic("Could not initialize root nexus"); 406*7c478bd9Sstevel@tonic-gate 407*7c478bd9Sstevel@tonic-gate /* 408*7c478bd9Sstevel@tonic-gate * Attach root node (no need to probe) 409*7c478bd9Sstevel@tonic-gate * Hold both devinfo and rootnex driver so they can't go away. 410*7c478bd9Sstevel@tonic-gate */ 411*7c478bd9Sstevel@tonic-gate DEVI(top_devinfo)->devi_ops = ndi_hold_driver(top_devinfo); 412*7c478bd9Sstevel@tonic-gate ASSERT(DEV_OPS_HELD(DEVI(top_devinfo)->devi_ops)); 413*7c478bd9Sstevel@tonic-gate DEVI(top_devinfo)->devi_instance = e_ddi_assign_instance(top_devinfo); 414*7c478bd9Sstevel@tonic-gate 415*7c478bd9Sstevel@tonic-gate DEVI_SET_ATTACHING(top_devinfo); 416*7c478bd9Sstevel@tonic-gate if (devi_attach(top_devinfo, DDI_ATTACH) != DDI_SUCCESS) 417*7c478bd9Sstevel@tonic-gate panic("Could not attach root nexus"); 418*7c478bd9Sstevel@tonic-gate DEVI_CLR_ATTACHING(top_devinfo); 419*7c478bd9Sstevel@tonic-gate 420*7c478bd9Sstevel@tonic-gate mutex_init(&global_vhci_lock, NULL, MUTEX_DEFAULT, NULL); 421*7c478bd9Sstevel@tonic-gate 422*7c478bd9Sstevel@tonic-gate ndi_hold_devi(top_devinfo); /* hold it forever */ 423*7c478bd9Sstevel@tonic-gate i_ddi_set_node_state(top_devinfo, DS_READY); 424*7c478bd9Sstevel@tonic-gate 425*7c478bd9Sstevel@tonic-gate /* 426*7c478bd9Sstevel@tonic-gate * Now, expand .conf children of root 427*7c478bd9Sstevel@tonic-gate */ 428*7c478bd9Sstevel@tonic-gate (void) i_ndi_make_spec_children(top_devinfo, 0); 429*7c478bd9Sstevel@tonic-gate 430*7c478bd9Sstevel@tonic-gate /* 431*7c478bd9Sstevel@tonic-gate * Must be set up before attaching root or pseudo drivers 432*7c478bd9Sstevel@tonic-gate */ 433*7c478bd9Sstevel@tonic-gate pm_init_locks(); 434*7c478bd9Sstevel@tonic-gate 435*7c478bd9Sstevel@tonic-gate /* 436*7c478bd9Sstevel@tonic-gate * Attach options dip 437*7c478bd9Sstevel@tonic-gate */ 438*7c478bd9Sstevel@tonic-gate options_dip = i_ddi_attach_pseudo_node("options"); 439*7c478bd9Sstevel@tonic-gate 440*7c478bd9Sstevel@tonic-gate /* 441*7c478bd9Sstevel@tonic-gate * Attach pseudo nexus and enumerate its children 442*7c478bd9Sstevel@tonic-gate */ 443*7c478bd9Sstevel@tonic-gate pseudo_dip = i_ddi_attach_pseudo_node(DEVI_PSEUDO_NEXNAME); 444*7c478bd9Sstevel@tonic-gate (void) i_ndi_make_spec_children(pseudo_dip, 0); 445*7c478bd9Sstevel@tonic-gate 446*7c478bd9Sstevel@tonic-gate /* 447*7c478bd9Sstevel@tonic-gate * Attach and hold clone dip 448*7c478bd9Sstevel@tonic-gate */ 449*7c478bd9Sstevel@tonic-gate clone_dip = i_ddi_attach_pseudo_node("clone"); 450*7c478bd9Sstevel@tonic-gate clone_major = ddi_driver_major(clone_dip); 451*7c478bd9Sstevel@tonic-gate mm_major = ddi_name_to_major("mm"); 452*7c478bd9Sstevel@tonic-gate 453*7c478bd9Sstevel@tonic-gate /* 454*7c478bd9Sstevel@tonic-gate * Attach scsi_vhci for MPXIO, this registers scsi vhci class 455*7c478bd9Sstevel@tonic-gate * with the MPXIO framework. 456*7c478bd9Sstevel@tonic-gate */ 457*7c478bd9Sstevel@tonic-gate scsi_vhci_dip = i_ddi_attach_pseudo_node("scsi_vhci"); 458*7c478bd9Sstevel@tonic-gate } 459