Home | History | Annotate | Download | only in os
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 
     22 /*
     23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 /*
     28  * sun4 specific DDI implementation
     29  */
     30 #include <sys/cpuvar.h>
     31 #include <sys/ddi_subrdefs.h>
     32 #include <sys/machsystm.h>
     33 #include <sys/sunndi.h>
     34 #include <sys/sysmacros.h>
     35 #include <sys/ontrap.h>
     36 #include <vm/seg_kmem.h>
     37 #include <sys/membar.h>
     38 #include <sys/dditypes.h>
     39 #include <sys/ndifm.h>
     40 #include <sys/fm/io/ddi.h>
     41 #include <sys/ivintr.h>
     42 #include <sys/bootconf.h>
     43 #include <sys/conf.h>
     44 #include <sys/ethernet.h>
     45 #include <sys/idprom.h>
     46 #include <sys/promif.h>
     47 #include <sys/prom_plat.h>
     48 #include <sys/systeminfo.h>
     49 #include <sys/fpu/fpusystm.h>
     50 #include <sys/vm.h>
     51 #include <sys/fs/dv_node.h>
     52 #include <sys/fs/snode.h>
     53 #include <sys/ddi_isa.h>
     54 #include <sys/modhash.h>
     55 #include <sys/modctl.h>
     56 #include <sys/sunldi_impl.h>
     57 
     58 dev_info_t *get_intr_parent(dev_info_t *, dev_info_t *,
     59     ddi_intr_handle_impl_t *);
     60 #pragma weak get_intr_parent
     61 
     62 int process_intr_ops(dev_info_t *, dev_info_t *, ddi_intr_op_t,
     63     ddi_intr_handle_impl_t *, void *);
     64 #pragma weak process_intr_ops
     65 
     66 void cells_1275_copy(prop_1275_cell_t *, prop_1275_cell_t *, int32_t);
     67     prop_1275_cell_t *cells_1275_cmp(prop_1275_cell_t *, prop_1275_cell_t *,
     68     int32_t len);
     69 #pragma weak cells_1275_copy
     70 
     71 /*
     72  * Wrapper for ddi_prop_lookup_int_array().
     73  * This is handy because it returns the prop length in
     74  * bytes which is what most of the callers require.
     75  */
     76 
     77 static int
     78 get_prop_int_array(dev_info_t *di, char *pname, int **pval, uint_t *plen)
     79 {
     80 	int ret;
     81 
     82 	if ((ret = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, di,
     83 	    DDI_PROP_DONTPASS, pname, pval, plen)) == DDI_PROP_SUCCESS) {
     84 		*plen = (*plen) * (uint_t)sizeof (int);
     85 	}
     86 	return (ret);
     87 }
     88 
     89 /*
     90  * SECTION: DDI Node Configuration
     91  */
     92 
     93 /*
     94  * init_regspec_64:
     95  *
     96  * If the parent #size-cells is 2, convert the upa-style or
     97  * safari-style reg property from 2-size cells to 1 size cell
     98  * format, ignoring the size_hi, which must be zero for devices.
     99  * (It won't be zero in the memory list properties in the memory
    100  * nodes, but that doesn't matter here.)
    101  */
    102 struct ddi_parent_private_data *
    103 init_regspec_64(dev_info_t *dip)
    104 {
    105 	struct ddi_parent_private_data *pd;
    106 	dev_info_t *parent;
    107 	int size_cells;
    108 
    109 	/*
    110 	 * If there are no "reg"s in the child node, return.
    111 	 */
    112 	pd = ddi_get_parent_data(dip);
    113 	if ((pd == NULL) || (pd->par_nreg == 0)) {
    114 		return (pd);
    115 	}
    116 	parent = ddi_get_parent(dip);
    117 
    118 	size_cells = ddi_prop_get_int(DDI_DEV_T_ANY, parent,
    119 	    DDI_PROP_DONTPASS, "#size-cells", 1);
    120 
    121 	if (size_cells != 1)  {
    122 
    123 		int n, j;
    124 		struct regspec *irp;
    125 		struct reg_64 {
    126 			uint_t addr_hi, addr_lo, size_hi, size_lo;
    127 		};
    128 		struct reg_64 *r64_rp;
    129 		struct regspec *rp;
    130 		uint_t len = 0;
    131 		int *reg_prop;
    132 
    133 		ASSERT(size_cells == 2);
    134 
    135 		/*
    136 		 * We already looked the property up once before if
    137 		 * pd is non-NULL.
    138 		 */
    139 		(void) ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip,
    140 		    DDI_PROP_DONTPASS, OBP_REG, &reg_prop, &len);
    141 		ASSERT(len != 0);
    142 
    143 		n = sizeof (struct reg_64) / sizeof (int);
    144 		n = len / n;
    145 
    146 		/*
    147 		 * We're allocating a buffer the size of the PROM's property,
    148 		 * but we're only using a smaller portion when we assign it
    149 		 * to a regspec.  We do this so that in the
    150 		 * impl_ddi_sunbus_removechild function, we will
    151 		 * always free the right amount of memory.
    152 		 */
    153 		irp = rp = (struct regspec *)reg_prop;
    154 		r64_rp = (struct reg_64 *)pd->par_reg;
    155 
    156 		for (j = 0; j < n; ++j, ++rp, ++r64_rp) {
    157 			ASSERT(r64_rp->size_hi == 0);
    158 			rp->regspec_bustype = r64_rp->addr_hi;
    159 			rp->regspec_addr = r64_rp->addr_lo;
    160 			rp->regspec_size = r64_rp->size_lo;
    161 		}
    162 
    163 		ddi_prop_free((void *)pd->par_reg);
    164 		pd->par_nreg = n;
    165 		pd->par_reg = irp;
    166 	}
    167 	return (pd);
    168 }
    169 
    170 /*
    171  * Create a ddi_parent_private_data structure from the ddi properties of
    172  * the dev_info node.
    173  *
    174  * The "reg" is required if the driver wishes to create mappings on behalf
    175  * of the device. The "reg" property is assumed to be a list of at least
    176  * one triplet
    177  *
    178  *	<bustype, address, size>*1
    179  *
    180  * The "interrupt" property is no longer part of parent private data on
    181  * sun4u. The interrupt parent is may not be the device tree parent.
    182  *
    183  * The "ranges" property describes the mapping of child addresses to parent
    184  * addresses.
    185  *
    186  * N.B. struct rangespec is defined for the following default values:
    187  *			parent  child
    188  *	#address-cells	2	2
    189  *	#size-cells	1	1
    190  * This function doesn't deal with non-default cells and will not create
    191  * ranges in such cases.
    192  */
    193 void
    194 make_ddi_ppd(dev_info_t *child, struct ddi_parent_private_data **ppd)
    195 {
    196 	struct ddi_parent_private_data *pdptr;
    197 	int *reg_prop, *rng_prop;
    198 	uint_t reg_len = 0, rng_len = 0;
    199 	dev_info_t *parent;
    200 	int parent_addr_cells, parent_size_cells;
    201 	int child_addr_cells, child_size_cells;
    202 
    203 	*ppd = pdptr = kmem_zalloc(sizeof (*pdptr), KM_SLEEP);
    204 
    205 	/*
    206 	 * root node has no parent private data, so *ppd should
    207 	 * be initialized for naming to work properly.
    208 	 */
    209 	if ((parent = ddi_get_parent(child)) == NULL)
    210 		return;
    211 
    212 	/*
    213 	 * Set reg field of parent data from "reg" property
    214 	 */
    215 	if ((get_prop_int_array(child, OBP_REG, &reg_prop, &reg_len)
    216 	    == DDI_PROP_SUCCESS) && (reg_len != 0)) {
    217 		pdptr->par_nreg = (int)(reg_len / sizeof (struct regspec));
    218 		pdptr->par_reg = (struct regspec *)reg_prop;
    219 	}
    220 
    221 	/*
    222 	 * "ranges" property ...
    223 	 *
    224 	 * This function does not handle cases where #address-cells != 2
    225 	 * and * min(parent, child) #size-cells != 1 (see bugid 4211124).
    226 	 *
    227 	 * Nexus drivers with such exceptions (e.g. pci ranges)
    228 	 * should either create a separate function for handling
    229 	 * ranges or not use parent private data to store ranges.
    230 	 */
    231 
    232 	/* root node has no ranges */
    233 	if ((parent = ddi_get_parent(child)) == NULL)
    234 		return;
    235 
    236 	child_addr_cells = ddi_prop_get_int(DDI_DEV_T_ANY, child,
    237 	    DDI_PROP_DONTPASS, "#address-cells", 2);
    238 	child_size_cells = ddi_prop_get_int(DDI_DEV_T_ANY, child,
    239 	    DDI_PROP_DONTPASS, "#size-cells", 1);
    240 	parent_addr_cells = ddi_prop_get_int(DDI_DEV_T_ANY, parent,
    241 	    DDI_PROP_DONTPASS, "#address-cells", 2);
    242 	parent_size_cells = ddi_prop_get_int(DDI_DEV_T_ANY, parent,
    243 	    DDI_PROP_DONTPASS, "#size-cells", 1);
    244 	if (child_addr_cells != 2 || parent_addr_cells != 2 ||
    245 	    (child_size_cells != 1 && parent_size_cells != 1)) {
    246 		NDI_CONFIG_DEBUG((CE_NOTE, "!ranges not made in parent data; "
    247 		    "#address-cells or #size-cells have non-default value"));
    248 		return;
    249 	}
    250 
    251 	if (get_prop_int_array(child, OBP_RANGES, &rng_prop, &rng_len)
    252 	    == DDI_PROP_SUCCESS) {
    253 		pdptr->par_nrng = rng_len / (int)(sizeof (struct rangespec));
    254 		pdptr->par_rng = (struct rangespec *)rng_prop;
    255 	}
    256 }
    257 
    258 /*
    259  * Free ddi_parent_private_data structure
    260  */
    261 void
    262 impl_free_ddi_ppd(dev_info_t *dip)
    263 {
    264 	struct ddi_parent_private_data *pdptr = ddi_get_parent_data(dip);
    265 
    266 	if (pdptr == NULL)
    267 		return;
    268 
    269 	if (pdptr->par_nrng != 0)
    270 		ddi_prop_free((void *)pdptr->par_rng);
    271 
    272 	if (pdptr->par_nreg != 0)
    273 		ddi_prop_free((void *)pdptr->par_reg);
    274 
    275 	kmem_free(pdptr, sizeof (*pdptr));
    276 	ddi_set_parent_data(dip, NULL);
    277 }
    278 
    279 /*
    280  * Name a child of sun busses based on the reg spec.
    281  * Handles the following properties:
    282  *
    283  *	Property	value
    284  *	Name		type
    285  *
    286  *	reg		register spec
    287  *	interrupts	new (bus-oriented) interrupt spec
    288  *	ranges		range spec
    289  *
    290  * This may be called multiple times, independent of
    291  * initchild calls.
    292  */
    293 static int
    294 impl_sunbus_name_child(dev_info_t *child, char *name, int namelen)
    295 {
    296 	struct ddi_parent_private_data *pdptr;
    297 	struct regspec *rp;
    298 
    299 	/*
    300 	 * Fill in parent-private data and this function returns to us
    301 	 * an indication if it used "registers" to fill in the data.
    302 	 */
    303 	if (ddi_get_parent_data(child) == NULL) {
    304 		make_ddi_ppd(child, &pdptr);
    305 		ddi_set_parent_data(child, pdptr);
    306 	}
    307 
    308 	/*
    309 	 * No reg property, return null string as address
    310 	 * (e.g. root node)
    311 	 */
    312 	name[0] = '\0';
    313 	if (sparc_pd_getnreg(child) == 0) {
    314 		return (DDI_SUCCESS);
    315 	}
    316 
    317 	rp = sparc_pd_getreg(child, 0);
    318 	(void) snprintf(name, namelen, "%x,%x",
    319 	    rp->regspec_bustype, rp->regspec_addr);
    320 	return (DDI_SUCCESS);
    321 }
    322 
    323 
    324 /*
    325  * Called from the bus_ctl op of some drivers.
    326  * to implement the DDI_CTLOPS_INITCHILD operation.
    327  *
    328  * NEW drivers should NOT use this function, but should declare
    329  * there own initchild/uninitchild handlers. (This function assumes
    330  * the layout of the parent private data and the format of "reg",
    331  * "ranges", "interrupts" properties and that #address-cells and
    332  * #size-cells of the parent bus are defined to be default values.)
    333  */
    334 int
    335 impl_ddi_sunbus_initchild(dev_info_t *child)
    336 {
    337 	char name[MAXNAMELEN];
    338 
    339 	(void) impl_sunbus_name_child(child, name, MAXNAMELEN);
    340 	ddi_set_name_addr(child, name);
    341 
    342 	/*
    343 	 * Try to merge .conf node. If successful, return failure to
    344 	 * remove this child.
    345 	 */
    346 	if ((ndi_dev_is_persistent_node(child) == 0) &&
    347 	    (ndi_merge_node(child, impl_sunbus_name_child) == DDI_SUCCESS)) {
    348 		impl_ddi_sunbus_removechild(child);
    349 		return (DDI_FAILURE);
    350 	}
    351 	return (DDI_SUCCESS);
    352 }
    353 
    354 /*
    355  * A better name for this function would be impl_ddi_sunbus_uninitchild()
    356  * It does not remove the child, it uninitializes it, reclaiming the
    357  * resources taken by impl_ddi_sunbus_initchild.
    358  */
    359 void
    360 impl_ddi_sunbus_removechild(dev_info_t *dip)
    361 {
    362 	impl_free_ddi_ppd(dip);
    363 	ddi_set_name_addr(dip, NULL);
    364 	/*
    365 	 * Strip the node to properly convert it back to prototype form
    366 	 */
    367 	impl_rem_dev_props(dip);
    368 }
    369 
    370 /*
    371  * SECTION: DDI Interrupt
    372  */
    373 
    374 void
    375 cells_1275_copy(prop_1275_cell_t *from, prop_1275_cell_t *to, int32_t len)
    376 {
    377 	int i;
    378 	for (i = 0; i < len; i++)
    379 		*to = *from;
    380 }
    381 
    382 prop_1275_cell_t *
    383 cells_1275_cmp(prop_1275_cell_t *cell1, prop_1275_cell_t *cell2, int32_t len)
    384 {
    385 	prop_1275_cell_t *match_cell = 0;
    386 	int32_t i;
    387 
    388 	for (i = 0; i < len; i++)
    389 		if (cell1[i] != cell2[i]) {
    390 			match_cell = &cell1[i];
    391 			break;
    392 		}
    393 
    394 	return (match_cell);
    395 }
    396 
    397 /*
    398  * get_intr_parent() is a generic routine that process a 1275 interrupt
    399  * map (imap) property.  This function returns a dev_info_t structure
    400  * which claims ownership of the interrupt domain.
    401  * It also returns the new interrupt translation within this new domain.
    402  * If an interrupt-parent or interrupt-map property are not found,
    403  * then we fallback to using the device tree's parent.
    404  *
    405  * imap entry format:
    406  * <reg>,<interrupt>,<phandle>,<translated interrupt>
    407  * reg - The register specification in the interrupts domain
    408  * interrupt - The interrupt specification
    409  * phandle - PROM handle of the device that owns the xlated interrupt domain
    410  * translated interrupt - interrupt specifier in the parents domain
    411  * note: <reg>,<interrupt> - The reg and interrupt can be combined to create
    412  *	a unique entry called a unit interrupt specifier.
    413  *
    414  * Here's the processing steps:
    415  * step1 - If the interrupt-parent property exists, create the ispec and
    416  *	return the dip of the interrupt parent.
    417  * step2 - Extract the interrupt-map property and the interrupt-map-mask
    418  *	If these don't exist, just return the device tree parent.
    419  * step3 - build up the unit interrupt specifier to match against the
    420  *	interrupt map property
    421  * step4 - Scan the interrupt-map property until a match is found
    422  * step4a - Extract the interrupt parent
    423  * step4b - Compare the unit interrupt specifier
    424  */
    425 dev_info_t *
    426 get_intr_parent(dev_info_t *pdip, dev_info_t *dip, ddi_intr_handle_impl_t *hdlp)
    427 {
    428 	prop_1275_cell_t *imap, *imap_mask, *scan, *reg_p, *match_req;
    429 	int32_t imap_sz, imap_cells, imap_scan_cells, imap_mask_sz,
    430 	    addr_cells, intr_cells, reg_len, i, j;
    431 	int32_t match_found = 0;
    432 	dev_info_t *intr_parent_dip = NULL;
    433 	uint32_t *intr = &hdlp->ih_vector;
    434 	uint32_t nodeid;
    435 #ifdef DEBUG
    436 	static int debug = 0;
    437 #endif
    438 
    439 	/*
    440 	 * step1
    441 	 * If we have an interrupt-parent property, this property represents
    442 	 * the nodeid of our interrupt parent.
    443 	 */
    444 	if ((nodeid = ddi_getprop(DDI_DEV_T_ANY, dip, 0,
    445 	    "interrupt-parent", -1)) != -1) {
    446 		intr_parent_dip = e_ddi_nodeid_to_dip(nodeid);
    447 		ASSERT(intr_parent_dip);
    448 
    449 		/*
    450 		 * Attach the interrupt parent.
    451 		 *
    452 		 * N.B. e_ddi_nodeid_to_dip() isn't safe under DR.
    453 		 *	Also, interrupt parent isn't held. This needs
    454 		 *	to be revisited if DR-capable platforms implement
    455 		 *	interrupt redirection.
    456 		 */
    457 		if (i_ddi_attach_node_hierarchy(intr_parent_dip)
    458 		    != DDI_SUCCESS) {
    459 			ndi_rele_devi(intr_parent_dip);
    460 			return (NULL);
    461 		}
    462 
    463 		return (intr_parent_dip);
    464 	}
    465 
    466 	/*
    467 	 * step2
    468 	 * Get interrupt map structure from PROM property
    469 	 */
    470 	if (ddi_getlongprop(DDI_DEV_T_ANY, pdip, DDI_PROP_DONTPASS,
    471 	    "interrupt-map", (caddr_t)&imap, &imap_sz)
    472 	    != DDI_PROP_SUCCESS) {
    473 		/*
    474 		 * If we don't have an imap property, default to using the
    475 		 * device tree.
    476 		 */
    477 
    478 		ndi_hold_devi(pdip);
    479 		return (pdip);
    480 	}
    481 
    482 	/* Get the interrupt mask property */
    483 	if (ddi_getlongprop(DDI_DEV_T_ANY, pdip, DDI_PROP_DONTPASS,
    484 	    "interrupt-map-mask", (caddr_t)&imap_mask, &imap_mask_sz)
    485 	    != DDI_PROP_SUCCESS) {
    486 		/*
    487 		 * If we don't find this property, we have to fail the request
    488 		 * because the 1275 imap property wasn't defined correctly.
    489 		 */
    490 		ASSERT(intr_parent_dip == NULL);
    491 		goto exit2;
    492 	}
    493 
    494 	/* Get the address cell size */
    495 	addr_cells = ddi_getprop(DDI_DEV_T_ANY, pdip, 0,
    496 	    "#address-cells", 2);
    497 
    498 	/* Get the interrupts cell size */
    499 	intr_cells = ddi_getprop(DDI_DEV_T_ANY, pdip, 0,
    500 	    "#interrupt-cells", 1);
    501 
    502 	/*
    503 	 * step3
    504 	 * Now lets build up the unit interrupt specifier e.g. reg,intr
    505 	 * and apply the imap mask.  match_req will hold this when we're
    506 	 * through.
    507 	 */
    508 	if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "reg",
    509 	    (caddr_t)&reg_p, &reg_len) != DDI_SUCCESS) {
    510 		ASSERT(intr_parent_dip == NULL);
    511 		goto exit3;
    512 	}
    513 
    514 	match_req = kmem_alloc(CELLS_1275_TO_BYTES(addr_cells) +
    515 	    CELLS_1275_TO_BYTES(intr_cells), KM_SLEEP);
    516 
    517 	for (i = 0; i < addr_cells; i++)
    518 		match_req[i] = (reg_p[i] & imap_mask[i]);
    519 
    520 	for (j = 0; j < intr_cells; i++, j++)
    521 		match_req[i] = (intr[j] & imap_mask[i]);
    522 
    523 	/* Calculate the imap size in cells */
    524 	imap_cells = BYTES_TO_1275_CELLS(imap_sz);
    525 
    526 #ifdef DEBUG
    527 	if (debug)
    528 		prom_printf("reg cell size 0x%x, intr cell size 0x%x, "
    529 		    "match_request 0x%p, imap 0x%p\n", addr_cells, intr_cells,
    530 		    (void *)match_req, (void *)imap);
    531 #endif
    532 
    533 	/*
    534 	 * Scan the imap property looking for a match of the interrupt unit
    535 	 * specifier.  This loop is rather complex since the data within the
    536 	 * imap property may vary in size.
    537 	 */
    538 	for (scan = imap, imap_scan_cells = i = 0;
    539 	    imap_scan_cells < imap_cells; scan += i, imap_scan_cells += i) {
    540 		int new_intr_cells;
    541 
    542 		/* Set the index to the nodeid field */
    543 		i = addr_cells + intr_cells;
    544 
    545 		/*
    546 		 * step4a
    547 		 * Translate the nodeid field to a dip
    548 		 */
    549 		ASSERT(intr_parent_dip == NULL);
    550 		intr_parent_dip = e_ddi_nodeid_to_dip((uint_t)scan[i++]);
    551 
    552 		ASSERT(intr_parent_dip != 0);
    553 #ifdef DEBUG
    554 		if (debug)
    555 			prom_printf("scan 0x%p\n", (void *)scan);
    556 #endif
    557 		/*
    558 		 * The tmp_dip describes the new domain, get it's interrupt
    559 		 * cell size
    560 		 */
    561 		new_intr_cells = ddi_getprop(DDI_DEV_T_ANY, intr_parent_dip, 0,
    562 		    "#interrupts-cells", 1);
    563 
    564 		/*
    565 		 * step4b
    566 		 * See if we have a match on the interrupt unit specifier
    567 		 */
    568 		if (cells_1275_cmp(match_req, scan, addr_cells + intr_cells)
    569 		    == 0) {
    570 			uint32_t *intr;
    571 
    572 			match_found = 1;
    573 
    574 			/*
    575 			 * If we have an imap parent whose not in our device
    576 			 * tree path, we need to hold and install that driver.
    577 			 */
    578 			if (i_ddi_attach_node_hierarchy(intr_parent_dip)
    579 			    != DDI_SUCCESS) {
    580 				ndi_rele_devi(intr_parent_dip);
    581 				intr_parent_dip = (dev_info_t *)NULL;
    582 				goto exit4;
    583 			}
    584 
    585 			/*
    586 			 * We need to handcraft an ispec along with a bus
    587 			 * interrupt value, so we can dup it into our
    588 			 * standard ispec structure.
    589 			 */
    590 			/* Extract the translated interrupt information */
    591 			intr = kmem_alloc(
    592 			    CELLS_1275_TO_BYTES(new_intr_cells), KM_SLEEP);
    593 
    594 			for (j = 0; j < new_intr_cells; j++, i++)
    595 				intr[j] = scan[i];
    596 
    597 			cells_1275_copy(intr, &hdlp->ih_vector, new_intr_cells);
    598 
    599 			kmem_free(intr, CELLS_1275_TO_BYTES(new_intr_cells));
    600 
    601 #ifdef DEBUG
    602 			if (debug)
    603 				prom_printf("dip 0x%p\n",
    604 				    (void *)intr_parent_dip);
    605 #endif
    606 			break;
    607 		} else {
    608 #ifdef DEBUG
    609 			if (debug)
    610 				prom_printf("dip 0x%p\n",
    611 				    (void *)intr_parent_dip);
    612 #endif
    613 			ndi_rele_devi(intr_parent_dip);
    614 			intr_parent_dip = NULL;
    615 			i += new_intr_cells;
    616 		}
    617 	}
    618 
    619 	/*
    620 	 * If we haven't found our interrupt parent at this point, fallback
    621 	 * to using the device tree.
    622 	 */
    623 	if (!match_found) {
    624 		ndi_hold_devi(pdip);
    625 		ASSERT(intr_parent_dip == NULL);
    626 		intr_parent_dip = pdip;
    627 	}
    628 
    629 	ASSERT(intr_parent_dip != NULL);
    630 
    631 exit4:
    632 	kmem_free(reg_p, reg_len);
    633 	kmem_free(match_req, CELLS_1275_TO_BYTES(addr_cells) +
    634 	    CELLS_1275_TO_BYTES(intr_cells));
    635 
    636 exit3:
    637 	kmem_free(imap_mask, imap_mask_sz);
    638 
    639 exit2:
    640 	kmem_free(imap, imap_sz);
    641 
    642 	return (intr_parent_dip);
    643 }
    644 
    645 /*
    646  * process_intr_ops:
    647  *
    648  * Process the interrupt op via the interrupt parent.
    649  */
    650 int
    651 process_intr_ops(dev_info_t *pdip, dev_info_t *rdip, ddi_intr_op_t op,
    652     ddi_intr_handle_impl_t *hdlp, void *result)
    653 {
    654 	int		ret = DDI_FAILURE;
    655 
    656 	if (NEXUS_HAS_INTR_OP(pdip)) {
    657 		ret = (*(DEVI(pdip)->devi_ops->devo_bus_ops->
    658 		    bus_intr_op)) (pdip, rdip, op, hdlp, result);
    659 	} else {
    660 		cmn_err(CE_WARN, "Failed to process interrupt "
    661 		    "for %s%d due to down-rev nexus driver %s%d",
    662 		    ddi_get_name(rdip), ddi_get_instance(rdip),
    663 		    ddi_get_name(pdip), ddi_get_instance(pdip));
    664 	}
    665 
    666 	return (ret);
    667 }
    668 
    669 /*ARGSUSED*/
    670 uint_t
    671 softlevel1(caddr_t arg)
    672 {
    673 	softint();
    674 	return (1);
    675 }
    676 
    677 /*
    678  * indirection table, to save us some large switch statements
    679  * NOTE: This must agree with "INTLEVEL_foo" constants in
    680  *	<sys/avintr.h>
    681  */
    682 struct autovec *const vectorlist[] = { 0 };
    683 
    684 /*
    685  * This value is exported here for the functions in avintr.c
    686  */
    687 const uint_t maxautovec = (sizeof (vectorlist) / sizeof (vectorlist[0]));
    688 
    689 /*
    690  * Check for machine specific interrupt levels which cannot be reassigned by
    691  * settrap(), sun4u version.
    692  *
    693  * sun4u does not support V8 SPARC "fast trap" handlers.
    694  */
    695 /*ARGSUSED*/
    696 int
    697 exclude_settrap(int lvl)
    698 {
    699 	return (1);
    700 }
    701 
    702 /*
    703  * Check for machine specific interrupt levels which cannot have interrupt
    704  * handlers added. We allow levels 1 through 15; level 0 is nonsense.
    705  */
    706 /*ARGSUSED*/
    707 int
    708 exclude_level(int lvl)
    709 {
    710 	return ((lvl < 1) || (lvl > 15));
    711 }
    712 
    713 /*
    714  * Wrapper functions used by New DDI interrupt framework.
    715  */
    716 
    717 /*
    718  * i_ddi_intr_ops:
    719  */
    720 int
    721 i_ddi_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t op,
    722     ddi_intr_handle_impl_t *hdlp, void *result)
    723 {
    724 	dev_info_t	*pdip = ddi_get_parent(dip);
    725 	int		ret = DDI_FAILURE;
    726 
    727 	/*
    728 	 * The following check is required to address
    729 	 * one of the test case of ADDI test suite.
    730 	 */
    731 	if (pdip == NULL)
    732 		return (DDI_FAILURE);
    733 
    734 	if (hdlp->ih_type != DDI_INTR_TYPE_FIXED)
    735 		return (process_intr_ops(pdip, rdip, op, hdlp, result));
    736 
    737 	if (hdlp->ih_vector == 0)
    738 		hdlp->ih_vector = i_ddi_get_inum(rdip, hdlp->ih_inum);
    739 
    740 	if (hdlp->ih_pri == 0)
    741 		hdlp->ih_pri = i_ddi_get_intr_pri(rdip, hdlp->ih_inum);
    742 
    743 	switch (op) {
    744 	case DDI_INTROP_ADDISR:
    745 	case DDI_INTROP_REMISR:
    746 	case DDI_INTROP_GETTARGET:
    747 	case DDI_INTROP_SETTARGET:
    748 	case DDI_INTROP_ENABLE:
    749 	case DDI_INTROP_DISABLE:
    750 	case DDI_INTROP_BLOCKENABLE:
    751 	case DDI_INTROP_BLOCKDISABLE:
    752 		/*
    753 		 * Try and determine our parent and possibly an interrupt
    754 		 * translation. intr parent dip returned held
    755 		 */
    756 		if ((pdip = get_intr_parent(pdip, dip, hdlp)) == NULL)
    757 			goto done;
    758 	}
    759 
    760 	ret = process_intr_ops(pdip, rdip, op, hdlp, result);
    761 
    762 done:
    763 	switch (op) {
    764 	case DDI_INTROP_ADDISR:
    765 	case DDI_INTROP_REMISR:
    766 	case DDI_INTROP_ENABLE:
    767 	case DDI_INTROP_DISABLE:
    768 	case DDI_INTROP_BLOCKENABLE:
    769 	case DDI_INTROP_BLOCKDISABLE:
    770 		/* Release hold acquired in get_intr_parent() */
    771 		if (pdip)
    772 			ndi_rele_devi(pdip);
    773 	}
    774 
    775 	hdlp->ih_vector = 0;
    776 
    777 	return (ret);
    778 }
    779 
    780 /*
    781  * i_ddi_add_ivintr:
    782  */
    783 /*ARGSUSED*/
    784 int
    785 i_ddi_add_ivintr(ddi_intr_handle_impl_t *hdlp)
    786 {
    787 	/*
    788 	 * If the PIL was set and is valid use it, otherwise
    789 	 * default it to 1
    790 	 */
    791 	if ((hdlp->ih_pri < 1) || (hdlp->ih_pri > PIL_MAX))
    792 		hdlp->ih_pri = 1;
    793 
    794 	VERIFY(add_ivintr(hdlp->ih_vector, hdlp->ih_pri,
    795 	    (intrfunc)hdlp->ih_cb_func, hdlp->ih_cb_arg1,
    796 	    hdlp->ih_cb_arg2, NULL) == 0);
    797 
    798 	return (DDI_SUCCESS);
    799 }
    800 
    801 /*
    802  * i_ddi_rem_ivintr:
    803  */
    804 /*ARGSUSED*/
    805 void
    806 i_ddi_rem_ivintr(ddi_intr_handle_impl_t *hdlp)
    807 {
    808 	VERIFY(rem_ivintr(hdlp->ih_vector, hdlp->ih_pri) == 0);
    809 }
    810 
    811 /*
    812  * i_ddi_get_inum - Get the interrupt number property from the
    813  * specified device. Note that this function is called only for
    814  * the FIXED interrupt type.
    815  */
    816 uint32_t
    817 i_ddi_get_inum(dev_info_t *dip, uint_t inumber)
    818 {
    819 	int32_t			intrlen, intr_cells, max_intrs;
    820 	prop_1275_cell_t	*ip, intr_sz;
    821 	uint32_t		intr = 0;
    822 
    823 	if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS |
    824 	    DDI_PROP_CANSLEEP,
    825 	    "interrupts", (caddr_t)&ip, &intrlen) == DDI_SUCCESS) {
    826 
    827 		intr_cells = ddi_getprop(DDI_DEV_T_ANY, dip, 0,
    828 		    "#interrupt-cells", 1);
    829 
    830 		/* adjust for number of bytes */
    831 		intr_sz = CELLS_1275_TO_BYTES(intr_cells);
    832 
    833 		/* Calculate the number of interrupts */
    834 		max_intrs = intrlen / intr_sz;
    835 
    836 		if (inumber < max_intrs) {
    837 			prop_1275_cell_t *intrp = ip;
    838 
    839 			/* Index into interrupt property */
    840 			intrp += (inumber * intr_cells);
    841 
    842 			cells_1275_copy(intrp, &intr, intr_cells);
    843 		}
    844 
    845 		kmem_free(ip, intrlen);
    846 	}
    847 
    848 	return (intr);
    849 }
    850 
    851 /*
    852  * i_ddi_get_intr_pri - Get the interrupt-priorities property from
    853  * the specified device. Note that this function is called only for
    854  * the FIXED interrupt type.
    855  */
    856 uint32_t
    857 i_ddi_get_intr_pri(dev_info_t *dip, uint_t inumber)
    858 {
    859 	uint32_t	*intr_prio_p;
    860 	uint32_t	pri = 0;
    861 	int32_t		i;
    862 
    863 	/*
    864 	 * Use the "interrupt-priorities" property to determine the
    865 	 * the pil/ipl for the interrupt handler.
    866 	 */
    867 	if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
    868 	    "interrupt-priorities", (caddr_t)&intr_prio_p,
    869 	    &i) == DDI_SUCCESS) {
    870 		if (inumber < (i / sizeof (int32_t)))
    871 			pri = intr_prio_p[inumber];
    872 		kmem_free(intr_prio_p, i);
    873 	}
    874 
    875 	return (pri);
    876 }
    877 
    878 int
    879 i_ddi_get_intx_nintrs(dev_info_t *dip)
    880 {
    881 	int32_t intrlen;
    882 	prop_1275_cell_t intr_sz;
    883 	prop_1275_cell_t *ip;
    884 	int32_t ret = 0;
    885 
    886 	if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS |
    887 	    DDI_PROP_CANSLEEP,
    888 	    "interrupts", (caddr_t)&ip, &intrlen) == DDI_SUCCESS) {
    889 
    890 		intr_sz = ddi_getprop(DDI_DEV_T_ANY, dip, 0,
    891 		    "#interrupt-cells", 1);
    892 		/* adjust for number of bytes */
    893 		intr_sz = CELLS_1275_TO_BYTES(intr_sz);
    894 
    895 		ret = intrlen / intr_sz;
    896 
    897 		kmem_free(ip, intrlen);
    898 	}
    899 
    900 	return (ret);
    901 }
    902 
    903 /*
    904  * i_ddi_add_softint - allocate and add a software interrupt.
    905  *
    906  * NOTE: All software interrupts that are registered through DDI
    907  *	 should be triggered only on a single target or CPU.
    908  */
    909 int
    910 i_ddi_add_softint(ddi_softint_hdl_impl_t *hdlp)
    911 {
    912 	if ((hdlp->ih_private = (void *)add_softintr(hdlp->ih_pri,
    913 	    hdlp->ih_cb_func, hdlp->ih_cb_arg1, SOFTINT_ST)) == NULL)
    914 		return (DDI_FAILURE);
    915 
    916 	return (DDI_SUCCESS);
    917 }
    918 
    919 /*
    920  * i_ddi_remove_softint - remove and free a software interrupt.
    921  */
    922 void
    923 i_ddi_remove_softint(ddi_softint_hdl_impl_t *hdlp)
    924 {
    925 	ASSERT(hdlp->ih_private != NULL);
    926 
    927 	if (rem_softintr((uint64_t)hdlp->ih_private) == 0)
    928 		hdlp->ih_private = NULL;
    929 }
    930 
    931 /*
    932  * i_ddi_trigger_softint - trigger a software interrupt.
    933  */
    934 int
    935 i_ddi_trigger_softint(ddi_softint_hdl_impl_t *hdlp, void *arg2)
    936 {
    937 	int	ret;
    938 
    939 	ASSERT(hdlp->ih_private != NULL);
    940 
    941 	/* Update the second argument for the software interrupt */
    942 	if ((ret = update_softint_arg2((uint64_t)hdlp->ih_private, arg2)) == 0)
    943 		setsoftint((uint64_t)hdlp->ih_private);
    944 
    945 	return (ret ? DDI_EPENDING : DDI_SUCCESS);
    946 }
    947 
    948 /*
    949  * i_ddi_set_softint_pri - change software interrupt priority.
    950  */
    951 /* ARGSUSED */
    952 int
    953 i_ddi_set_softint_pri(ddi_softint_hdl_impl_t *hdlp, uint_t old_pri)
    954 {
    955 	int	ret;
    956 
    957 	ASSERT(hdlp->ih_private != NULL);
    958 
    959 	/* Update the interrupt priority for the software interrupt */
    960 	ret = update_softint_pri((uint64_t)hdlp->ih_private, hdlp->ih_pri);
    961 
    962 	return (ret ? DDI_FAILURE : DDI_SUCCESS);
    963 }
    964 
    965 /*ARGSUSED*/
    966 void
    967 i_ddi_alloc_intr_phdl(ddi_intr_handle_impl_t *hdlp)
    968 {
    969 }
    970 
    971 /*ARGSUSED*/
    972 void
    973 i_ddi_free_intr_phdl(ddi_intr_handle_impl_t *hdlp)
    974 {
    975 }
    976 
    977 /*
    978  * SECTION: DDI Memory/DMA
    979  */
    980 
    981 /* set HAT endianess attributes from ddi_device_acc_attr */
    982 void
    983 i_ddi_devacc_to_hatacc(ddi_device_acc_attr_t *devaccp, uint_t *hataccp)
    984 {
    985 	if (devaccp != NULL) {
    986 		if (devaccp->devacc_attr_endian_flags == DDI_STRUCTURE_LE_ACC) {
    987 			*hataccp &= ~HAT_ENDIAN_MASK;
    988 			*hataccp |= HAT_STRUCTURE_LE;
    989 		}
    990 	}
    991 }
    992 
    993 /*
    994  * Check if the specified cache attribute is supported on the platform.
    995  * This function must be called before i_ddi_cacheattr_to_hatacc().
    996  */
    997 boolean_t
    998 i_ddi_check_cache_attr(uint_t flags)
    999 {
   1000 	/*
   1001 	 * The cache attributes are mutually exclusive. Any combination of
   1002 	 * the attributes leads to a failure.
   1003 	 */
   1004 	uint_t cache_attr = IOMEM_CACHE_ATTR(flags);
   1005 	if ((cache_attr != 0) && ((cache_attr & (cache_attr - 1)) != 0))
   1006 		return (B_FALSE);
   1007 
   1008 	/*
   1009 	 * On the sparc architecture, only IOMEM_DATA_CACHED is meaningful,
   1010 	 * but others lead to a failure.
   1011 	 */
   1012 	if (cache_attr & IOMEM_DATA_CACHED)
   1013 		return (B_TRUE);
   1014 	else
   1015 		return (B_FALSE);
   1016 }
   1017 
   1018 /* set HAT cache attributes from the cache attributes */
   1019 void
   1020 i_ddi_cacheattr_to_hatacc(uint_t flags, uint_t *hataccp)
   1021 {
   1022 	uint_t cache_attr = IOMEM_CACHE_ATTR(flags);
   1023 	static char *fname = "i_ddi_cacheattr_to_hatacc";
   1024 #if defined(lint)
   1025 	*hataccp = *hataccp;
   1026 #endif
   1027 	/*
   1028 	 * set HAT attrs according to the cache attrs.
   1029 	 */
   1030 	switch (cache_attr) {
   1031 	/*
   1032 	 * The cache coherency is always maintained on SPARC, and
   1033 	 * nothing is required.
   1034 	 */
   1035 	case IOMEM_DATA_CACHED:
   1036 		break;
   1037 	/*
   1038 	 * Both IOMEM_DATA_UC_WRITE_COMBINED and IOMEM_DATA_UNCACHED are
   1039 	 * not supported on SPARC -- this case must not occur because the
   1040 	 * cache attribute is scrutinized before this function is called.
   1041 	 */
   1042 	case IOMEM_DATA_UNCACHED:
   1043 	case IOMEM_DATA_UC_WR_COMBINE:
   1044 	default:
   1045 		cmn_err(CE_WARN, "%s: cache_attr=0x%x is ignored.",
   1046 		    fname, cache_attr);
   1047 	}
   1048 }
   1049 
   1050 static vmem_t *little_endian_arena;
   1051 static vmem_t *big_endian_arena;
   1052 
   1053 static void *
   1054 segkmem_alloc_le(vmem_t *vmp, size_t size, int flag)
   1055 {
   1056 	return (segkmem_xalloc(vmp, NULL, size, flag, HAT_STRUCTURE_LE,
   1057 	    segkmem_page_create, NULL));
   1058 }
   1059 
   1060 static void *
   1061 segkmem_alloc_be(vmem_t *vmp, size_t size, int flag)
   1062 {
   1063 	return (segkmem_xalloc(vmp, NULL, size, flag, HAT_STRUCTURE_BE,
   1064 	    segkmem_page_create, NULL));
   1065 }
   1066 
   1067 void
   1068 ka_init(void)
   1069 {
   1070 	little_endian_arena = vmem_create("little_endian", NULL, 0, 1,
   1071 	    segkmem_alloc_le, segkmem_free, heap_arena, 0, VM_SLEEP);
   1072 	big_endian_arena = vmem_create("big_endian", NULL, 0, 1,
   1073 	    segkmem_alloc_be, segkmem_free, heap_arena, 0, VM_SLEEP);
   1074 }
   1075 
   1076 /*
   1077  * Allocate from the system, aligned on a specific boundary.
   1078  * The alignment, if non-zero, must be a power of 2.
   1079  */
   1080 static void *
   1081 kalloca(size_t size, size_t align, int cansleep, uint_t endian_flags)
   1082 {
   1083 	size_t *addr, *raddr, rsize;
   1084 	size_t hdrsize = 4 * sizeof (size_t);	/* must be power of 2 */
   1085 
   1086 	align = MAX(align, hdrsize);
   1087 	ASSERT((align & (align - 1)) == 0);
   1088 
   1089 	/*
   1090 	 * We need to allocate
   1091 	 *    rsize = size + hdrsize + align - MIN(hdrsize, buffer_alignment)
   1092 	 * bytes to be sure we have enough freedom to satisfy the request.
   1093 	 * Since the buffer alignment depends on the request size, this is
   1094 	 * not straightforward to use directly.
   1095 	 *
   1096 	 * kmem guarantees that any allocation of a 64-byte multiple will be
   1097 	 * 64-byte aligned.  Since rounding up the request could add more
   1098 	 * than we save, we compute the size with and without alignment, and
   1099 	 * use the smaller of the two.
   1100 	 */
   1101 	rsize = size + hdrsize + align;
   1102 
   1103 	if (endian_flags == DDI_STRUCTURE_LE_ACC) {
   1104 		raddr = vmem_alloc(little_endian_arena, rsize,
   1105 		    cansleep ? VM_SLEEP : VM_NOSLEEP);
   1106 	} else {
   1107 		raddr = vmem_alloc(big_endian_arena, rsize,
   1108 		    cansleep ? VM_SLEEP : VM_NOSLEEP);
   1109 	}
   1110 
   1111 	if (raddr == NULL)
   1112 		return (NULL);
   1113 
   1114 	addr = (size_t *)P2ROUNDUP((uintptr_t)raddr + hdrsize, align);
   1115 	ASSERT((uintptr_t)addr + size - (uintptr_t)raddr <= rsize);
   1116 
   1117 	addr[-3] = (size_t)endian_flags;
   1118 	addr[-2] = (size_t)raddr;
   1119 	addr[-1] = rsize;
   1120 
   1121 	return (addr);
   1122 }
   1123 
   1124 static void
   1125 kfreea(void *addr)
   1126 {
   1127 	size_t *saddr = addr;
   1128 
   1129 	if (saddr[-3] == DDI_STRUCTURE_LE_ACC)
   1130 		vmem_free(little_endian_arena, (void *)saddr[-2], saddr[-1]);
   1131 	else
   1132 		vmem_free(big_endian_arena, (void *)saddr[-2], saddr[-1]);
   1133 }
   1134 
   1135 int
   1136 i_ddi_mem_alloc(dev_info_t *dip, ddi_dma_attr_t *attr,
   1137     size_t length, int cansleep, int flags,
   1138     ddi_device_acc_attr_t *accattrp,
   1139     caddr_t *kaddrp, size_t *real_length, ddi_acc_hdl_t *handlep)
   1140 {
   1141 	caddr_t a;
   1142 	int iomin, align, streaming;
   1143 	uint_t endian_flags = DDI_NEVERSWAP_ACC;
   1144 
   1145 #if defined(lint)
   1146 	*handlep = *handlep;
   1147 #endif
   1148 
   1149 	/*
   1150 	 * Check legality of arguments
   1151 	 */
   1152 	if (length == 0 || kaddrp == NULL || attr == NULL) {
   1153 		return (DDI_FAILURE);
   1154 	}
   1155 
   1156 	if (attr->dma_attr_minxfer == 0 || attr->dma_attr_align == 0 ||
   1157 	    (attr->dma_attr_align & (attr->dma_attr_align - 1)) ||
   1158 	    (attr->dma_attr_minxfer & (attr->dma_attr_minxfer - 1))) {
   1159 		return (DDI_FAILURE);
   1160 	}
   1161 
   1162 	/*
   1163 	 * check if a streaming sequential xfer is requested.
   1164 	 */
   1165 	streaming = (flags & DDI_DMA_STREAMING) ? 1 : 0;
   1166 
   1167 	/*
   1168 	 * Drivers for 64-bit capable SBus devices will encode
   1169 	 * the burtsizes for 64-bit xfers in the upper 16-bits.
   1170 	 * For DMA alignment, we use the most restrictive
   1171 	 * alignment of 32-bit and 64-bit xfers.
   1172 	 */
   1173 	iomin = (attr->dma_attr_burstsizes & 0xffff) |
   1174 	    ((attr->dma_attr_burstsizes >> 16) & 0xffff);
   1175 	/*
   1176 	 * If a driver set burtsizes to 0, we give him byte alignment.
   1177 	 * Otherwise align at the burtsizes boundary.
   1178 	 */
   1179 	if (iomin == 0)
   1180 		iomin = 1;
   1181 	else
   1182 		iomin = 1 << (ddi_fls(iomin) - 1);
   1183 	iomin = maxbit(iomin, attr->dma_attr_minxfer);
   1184 	iomin = maxbit(iomin, attr->dma_attr_align);
   1185 	iomin = ddi_iomin(dip, iomin, streaming);
   1186 	if (iomin == 0)
   1187 		return (DDI_FAILURE);
   1188 
   1189 	ASSERT((iomin & (iomin - 1)) == 0);
   1190 	ASSERT(iomin >= attr->dma_attr_minxfer);
   1191 	ASSERT(iomin >= attr->dma_attr_align);
   1192 
   1193 	length = P2ROUNDUP(length, iomin);
   1194 	align = iomin;
   1195 
   1196 	if (accattrp != NULL)
   1197 		endian_flags = accattrp->devacc_attr_endian_flags;
   1198 
   1199 	a = kalloca(length, align, cansleep, endian_flags);
   1200 	if ((*kaddrp = a) == 0) {
   1201 		return (DDI_FAILURE);
   1202 	} else {
   1203 		if (real_length) {
   1204 			*real_length = length;
   1205 		}
   1206 		if (handlep) {
   1207 			/*
   1208 			 * assign handle information
   1209 			 */
   1210 			impl_acc_hdl_init(handlep);
   1211 		}
   1212 		return (DDI_SUCCESS);
   1213 	}
   1214 }
   1215 
   1216 /*
   1217  * covert old DMA limits structure to DMA attribute structure
   1218  * and continue
   1219  */
   1220 int
   1221 i_ddi_mem_alloc_lim(dev_info_t *dip, ddi_dma_lim_t *limits,
   1222     size_t length, int cansleep, int streaming,
   1223     ddi_device_acc_attr_t *accattrp, caddr_t *kaddrp,
   1224     uint_t *real_length, ddi_acc_hdl_t *ap)
   1225 {
   1226 	ddi_dma_attr_t dma_attr, *attrp;
   1227 	size_t rlen;
   1228 	int ret;
   1229 
   1230 	ASSERT(limits);
   1231 	attrp = &dma_attr;
   1232 	attrp->dma_attr_version = DMA_ATTR_V0;
   1233 	attrp->dma_attr_addr_lo = (uint64_t)limits->dlim_addr_lo;
   1234 	attrp->dma_attr_addr_hi = (uint64_t)limits->dlim_addr_hi;
   1235 	attrp->dma_attr_count_max = (uint64_t)-1;
   1236 	attrp->dma_attr_align = 1;
   1237 	attrp->dma_attr_burstsizes = (uint_t)limits->dlim_burstsizes;
   1238 	attrp->dma_attr_minxfer = (uint32_t)limits->dlim_minxfer;
   1239 	attrp->dma_attr_maxxfer = (uint64_t)-1;
   1240 	attrp->dma_attr_seg = (uint64_t)limits->dlim_cntr_max;
   1241 	attrp->dma_attr_sgllen = 1;
   1242 	attrp->dma_attr_granular = 1;
   1243 	attrp->dma_attr_flags = 0;
   1244 
   1245 	ret = i_ddi_mem_alloc(dip, attrp, length, cansleep, streaming,
   1246 	    accattrp, kaddrp, &rlen, ap);
   1247 	if (ret == DDI_SUCCESS) {
   1248 		if (real_length)
   1249 			*real_length = (uint_t)rlen;
   1250 	}
   1251 	return (ret);
   1252 }
   1253 
   1254 /* ARGSUSED */
   1255 void
   1256 i_ddi_mem_free(caddr_t kaddr, ddi_acc_hdl_t *ap)
   1257 {
   1258 	kfreea(kaddr);
   1259 }
   1260 
   1261 /*
   1262  * SECTION: DDI Data Access
   1263  */
   1264 
   1265 static uintptr_t impl_acc_hdl_id = 0;
   1266 
   1267 /*
   1268  * access handle allocator
   1269  */
   1270 ddi_acc_hdl_t *
   1271 impl_acc_hdl_get(ddi_acc_handle_t hdl)
   1272 {
   1273 	/*
   1274 	 * Extract the access handle address from the DDI implemented
   1275 	 * access handle
   1276 	 */
   1277 	return (&((ddi_acc_impl_t *)hdl)->ahi_common);
   1278 }
   1279 
   1280 ddi_acc_handle_t
   1281 impl_acc_hdl_alloc(int (*waitfp)(caddr_t), caddr_t arg)
   1282 {
   1283 	ddi_acc_impl_t *hp;
   1284 	on_trap_data_t *otp;
   1285 	int sleepflag;
   1286 
   1287 	sleepflag = ((waitfp == (int (*)())KM_SLEEP) ? KM_SLEEP : KM_NOSLEEP);
   1288 
   1289 	/*
   1290 	 * Allocate and initialize the data access handle and error status.
   1291 	 */
   1292 	if ((hp = kmem_zalloc(sizeof (ddi_acc_impl_t), sleepflag)) == NULL)
   1293 		goto fail;
   1294 	if ((hp->ahi_err = (ndi_err_t *)kmem_zalloc(
   1295 	    sizeof (ndi_err_t), sleepflag)) == NULL) {
   1296 		kmem_free(hp, sizeof (ddi_acc_impl_t));
   1297 		goto fail;
   1298 	}
   1299 	if ((otp = (on_trap_data_t *)kmem_zalloc(
   1300 	    sizeof (on_trap_data_t), sleepflag)) == NULL) {
   1301 		kmem_free(hp->ahi_err, sizeof (ndi_err_t));
   1302 		kmem_free(hp, sizeof (ddi_acc_impl_t));
   1303 		goto fail;
   1304 	}
   1305 	hp->ahi_err->err_ontrap = otp;
   1306 	hp->ahi_common.ah_platform_private = (void *)hp;
   1307 
   1308 	return ((ddi_acc_handle_t)hp);
   1309 fail:
   1310 	if ((waitfp != (int (*)())KM_SLEEP) &&
   1311 	    (waitfp != (int (*)())KM_NOSLEEP))
   1312 		ddi_set_callback(waitfp, arg, &impl_acc_hdl_id);
   1313 	return (NULL);
   1314 }
   1315 
   1316 void
   1317 impl_acc_hdl_free(ddi_acc_handle_t handle)
   1318 {
   1319 	ddi_acc_impl_t *hp;
   1320 
   1321 	/*
   1322 	 * The supplied (ddi_acc_handle_t) is actually a (ddi_acc_impl_t *),
   1323 	 * because that's what we allocated in impl_acc_hdl_alloc() above.
   1324 	 */
   1325 	hp = (ddi_acc_impl_t *)handle;
   1326 	if (hp) {
   1327 		kmem_free(hp->ahi_err->err_ontrap, sizeof (on_trap_data_t));
   1328 		kmem_free(hp->ahi_err, sizeof (ndi_err_t));
   1329 		kmem_free(hp, sizeof (ddi_acc_impl_t));
   1330 		if (impl_acc_hdl_id)
   1331 			ddi_run_callback(&impl_acc_hdl_id);
   1332 	}
   1333 }
   1334 
   1335 #define	PCI_GET_MP_PFN(mp, page_no)	((mp)->dmai_ndvmapages == 1 ? \
   1336 	(pfn_t)(mp)->dmai_iopte:(((pfn_t *)(mp)->dmai_iopte)[page_no]))
   1337 
   1338 /*
   1339  * Function called after a dma fault occurred to find out whether the
   1340  * fault address is associated with a driver that is able to handle faults
   1341  * and recover from faults.
   1342  */
   1343 /* ARGSUSED */
   1344 int
   1345 impl_dma_check(dev_info_t *dip, const void *handle, const void *addr,
   1346     const void *not_used)
   1347 {
   1348 	ddi_dma_impl_t *mp = (ddi_dma_impl_t *)handle;
   1349 	pfn_t fault_pfn = mmu_btop(*(uint64_t *)addr);
   1350 	pfn_t comp_pfn;
   1351 
   1352 	/*
   1353 	 * The driver has to set DDI_DMA_FLAGERR to recover from dma faults.
   1354 	 */
   1355 	int page;
   1356 
   1357 	ASSERT(mp);
   1358 	for (page = 0; page < mp->dmai_ndvmapages; page++) {
   1359 		comp_pfn = PCI_GET_MP_PFN(mp, page);
   1360 		if (fault_pfn == comp_pfn)
   1361 			return (DDI_FM_NONFATAL);
   1362 	}
   1363 	return (DDI_FM_UNKNOWN);
   1364 }
   1365 
   1366 /*
   1367  * Function used to check if a given access handle owns the failing address.
   1368  * Called by ndi_fmc_error, when we detect a PIO error.
   1369  */
   1370 /* ARGSUSED */
   1371 static int
   1372 impl_acc_check(dev_info_t *dip, const void *handle, const void *addr,
   1373     const void *not_used)
   1374 {
   1375 	pfn_t pfn, fault_pfn;
   1376 	ddi_acc_hdl_t *hp;
   1377 
   1378 	hp = impl_acc_hdl_get((ddi_acc_handle_t)handle);
   1379 
   1380 	ASSERT(hp);
   1381 
   1382 	if (addr != NULL) {
   1383 		pfn = hp->ah_pfn;
   1384 		fault_pfn = mmu_btop(*(uint64_t *)addr);
   1385 		if (fault_pfn >= pfn && fault_pfn < (pfn + hp->ah_pnum))
   1386 			return (DDI_FM_NONFATAL);
   1387 	}
   1388 	return (DDI_FM_UNKNOWN);
   1389 }
   1390 
   1391 void
   1392 impl_acc_err_init(ddi_acc_hdl_t *handlep)
   1393 {
   1394 	int fmcap;
   1395 	ndi_err_t *errp;
   1396 	on_trap_data_t *otp;
   1397 	ddi_acc_impl_t *hp = (ddi_acc_impl_t *)handlep;
   1398 
   1399 	fmcap = ddi_fm_capable(handlep->ah_dip);
   1400 
   1401 	if (handlep->ah_acc.devacc_attr_version < DDI_DEVICE_ATTR_V1 ||
   1402 	    !DDI_FM_ACC_ERR_CAP(fmcap)) {
   1403 		handlep->ah_acc.devacc_attr_access = DDI_DEFAULT_ACC;
   1404 	} else if (DDI_FM_ACC_ERR_CAP(fmcap)) {
   1405 		if (handlep->ah_acc.devacc_attr_access == DDI_DEFAULT_ACC) {
   1406 			i_ddi_drv_ereport_post(handlep->ah_dip, DVR_EFMCAP,
   1407 			    NULL, DDI_NOSLEEP);
   1408 		} else {
   1409 			errp = hp->ahi_err;
   1410 			otp = (on_trap_data_t *)errp->err_ontrap;
   1411 			otp->ot_handle = (void *)(hp);
   1412 			otp->ot_prot = OT_DATA_ACCESS;
   1413 			if (handlep->ah_acc.devacc_attr_access ==
   1414 			    DDI_CAUTIOUS_ACC)
   1415 				otp->ot_trampoline =
   1416 				    (uintptr_t)&i_ddi_caut_trampoline;
   1417 			else
   1418 				otp->ot_trampoline =
   1419 				    (uintptr_t)&i_ddi_prot_trampoline;
   1420 			errp->err_status = DDI_FM_OK;
   1421 			errp->err_expected = DDI_FM_ERR_UNEXPECTED;
   1422 			errp->err_cf = impl_acc_check;
   1423 		}
   1424 	}
   1425 }
   1426 
   1427 void
   1428 impl_acc_hdl_init(ddi_acc_hdl_t *handlep)
   1429 {
   1430 	ddi_acc_impl_t *hp;
   1431 
   1432 	ASSERT(handlep);
   1433 
   1434 	hp = (ddi_acc_impl_t *)handlep;
   1435 
   1436 	/*
   1437 	 * check for SW byte-swapping
   1438 	 */
   1439 	hp->ahi_get8 = i_ddi_get8;
   1440 	hp->ahi_put8 = i_ddi_put8;
   1441 	hp->ahi_rep_get8 = i_ddi_rep_get8;
   1442 	hp->ahi_rep_put8 = i_ddi_rep_put8;
   1443 	if (handlep->ah_acc.devacc_attr_endian_flags & DDI_STRUCTURE_LE_ACC) {
   1444 		hp->ahi_get16 = i_ddi_swap_get16;
   1445 		hp->ahi_get32 = i_ddi_swap_get32;
   1446 		hp->ahi_get64 = i_ddi_swap_get64;
   1447 		hp->ahi_put16 = i_ddi_swap_put16;
   1448 		hp->ahi_put32 = i_ddi_swap_put32;
   1449 		hp->ahi_put64 = i_ddi_swap_put64;
   1450 		hp->ahi_rep_get16 = i_ddi_swap_rep_get16;
   1451 		hp->ahi_rep_get32 = i_ddi_swap_rep_get32;
   1452 		hp->ahi_rep_get64 = i_ddi_swap_rep_get64;
   1453 		hp->ahi_rep_put16 = i_ddi_swap_rep_put16;
   1454 		hp->ahi_rep_put32 = i_ddi_swap_rep_put32;
   1455 		hp->ahi_rep_put64 = i_ddi_swap_rep_put64;
   1456 	} else {
   1457 		hp->ahi_get16 = i_ddi_get16;
   1458 		hp->ahi_get32 = i_ddi_get32;
   1459 		hp->ahi_get64 = i_ddi_get64;
   1460 		hp->ahi_put16 = i_ddi_put16;
   1461 		hp->ahi_put32 = i_ddi_put32;
   1462 		hp->ahi_put64 = i_ddi_put64;
   1463 		hp->ahi_rep_get16 = i_ddi_rep_get16;
   1464 		hp->ahi_rep_get32 = i_ddi_rep_get32;
   1465 		hp->ahi_rep_get64 = i_ddi_rep_get64;
   1466 		hp->ahi_rep_put16 = i_ddi_rep_put16;
   1467 		hp->ahi_rep_put32 = i_ddi_rep_put32;
   1468 		hp->ahi_rep_put64 = i_ddi_rep_put64;
   1469 	}
   1470 
   1471 	/* Legacy fault flags and support */
   1472 	hp->ahi_fault_check = i_ddi_acc_fault_check;
   1473 	hp->ahi_fault_notify = i_ddi_acc_fault_notify;
   1474 	hp->ahi_fault = 0;
   1475 	impl_acc_err_init(handlep);
   1476 }
   1477 
   1478 void
   1479 i_ddi_acc_set_fault(ddi_acc_handle_t handle)
   1480 {
   1481 	ddi_acc_impl_t *hp = (ddi_acc_impl_t *)handle;
   1482 
   1483 	if (!hp->ahi_fault) {
   1484 		hp->ahi_fault = 1;
   1485 			(*hp->ahi_fault_notify)(hp);
   1486 	}
   1487 }
   1488 
   1489 void
   1490 i_ddi_acc_clr_fault(ddi_acc_handle_t handle)
   1491 {
   1492 	ddi_acc_impl_t *hp = (ddi_acc_impl_t *)handle;
   1493 
   1494 	if (hp->ahi_fault) {
   1495 		hp->ahi_fault = 0;
   1496 			(*hp->ahi_fault_notify)(hp);
   1497 	}
   1498 }
   1499 
   1500 /* ARGSUSED */
   1501 void
   1502 i_ddi_acc_fault_notify(ddi_acc_impl_t *hp)
   1503 {
   1504 	/* Default version, does nothing */
   1505 }
   1506 
   1507 /*
   1508  * SECTION: Misc functions
   1509  */
   1510 
   1511 /*
   1512  * instance wrappers
   1513  */
   1514 /*ARGSUSED*/
   1515 uint_t
   1516 impl_assign_instance(dev_info_t *dip)
   1517 {
   1518 	return ((uint_t)-1);
   1519 }
   1520 
   1521 /*ARGSUSED*/
   1522 int
   1523 impl_keep_instance(dev_info_t *dip)
   1524 {
   1525 	return (DDI_FAILURE);
   1526 }
   1527 
   1528 /*ARGSUSED*/
   1529 int
   1530 impl_free_instance(dev_info_t *dip)
   1531 {
   1532 	return (DDI_FAILURE);
   1533 }
   1534 
   1535 /*ARGSUSED*/
   1536 int
   1537 impl_check_cpu(dev_info_t *devi)
   1538 {
   1539 	return (DDI_SUCCESS);
   1540 }
   1541 
   1542 
   1543 static const char *nocopydevs[] = {
   1544 	"SUNW,ffb",
   1545 	"SUNW,afb",
   1546 	NULL
   1547 };
   1548 
   1549 /*
   1550  * Perform a copy from a memory mapped device (whose devinfo pointer is devi)
   1551  * separately mapped at devaddr in the kernel to a kernel buffer at kaddr.
   1552  */
   1553 /*ARGSUSED*/
   1554 int
   1555 e_ddi_copyfromdev(dev_info_t *devi,
   1556     off_t off, const void *devaddr, void *kaddr, size_t len)
   1557 {
   1558 	const char **argv;
   1559 
   1560 	for (argv = nocopydevs; *argv; argv++)
   1561 		if (strcmp(ddi_binding_name(devi), *argv) == 0) {
   1562 			bzero(kaddr, len);
   1563 			return (0);
   1564 		}
   1565 
   1566 	bcopy(devaddr, kaddr, len);
   1567 	return (0);
   1568 }
   1569 
   1570 /*
   1571  * Perform a copy to a memory mapped device (whose devinfo pointer is devi)
   1572  * separately mapped at devaddr in the kernel from a kernel buffer at kaddr.
   1573  */
   1574 /*ARGSUSED*/
   1575 int
   1576 e_ddi_copytodev(dev_info_t *devi,
   1577     off_t off, const void *kaddr, void *devaddr, size_t len)
   1578 {
   1579 	const char **argv;
   1580 
   1581 	for (argv = nocopydevs; *argv; argv++)
   1582 		if (strcmp(ddi_binding_name(devi), *argv) == 0)
   1583 			return (1);
   1584 
   1585 	bcopy(kaddr, devaddr, len);
   1586 	return (0);
   1587 }
   1588 
   1589 /*
   1590  * Boot Configuration
   1591  */
   1592 idprom_t idprom;
   1593 
   1594 /*
   1595  * Configure the hardware on the system.
   1596  * Called before the rootfs is mounted
   1597  */
   1598 void
   1599 configure(void)
   1600 {
   1601 	extern void i_ddi_init_root();
   1602 
   1603 	/* We better have released boot by this time! */
   1604 	ASSERT(!bootops);
   1605 
   1606 	/*
   1607 	 * Determine whether or not to use the fpu, V9 SPARC cpus
   1608 	 * always have one. Could check for existence of a fp queue,
   1609 	 * Ultra I, II and IIa do not have a fp queue.
   1610 	 */
   1611 	if (fpu_exists)
   1612 		fpu_probe();
   1613 	else
   1614 		cmn_err(CE_CONT, "FPU not in use\n");
   1615 
   1616 #if 0 /* XXXQ - not necessary for sun4u */
   1617 	/*
   1618 	 * This following line fixes bugid 1041296; we need to do a
   1619 	 * prom_nextnode(0) because this call ALSO patches the DMA+
   1620 	 * bug in Campus-B and Phoenix. The prom uncaches the traptable
   1621 	 * page as a side-effect of devr_next(0) (which prom_nextnode calls),
   1622 	 * so this *must* be executed early on. (XXX This is untrue for sun4u)
   1623 	 */
   1624 	(void) prom_nextnode((pnode_t)0);
   1625 #endif
   1626 
   1627 	/*
   1628 	 * Initialize devices on the machine.
   1629 	 * Uses configuration tree built by the PROMs to determine what
   1630 	 * is present, and builds a tree of prototype dev_info nodes
   1631 	 * corresponding to the hardware which identified itself.
   1632 	 */
   1633 	i_ddi_init_root();
   1634 
   1635 #ifdef	DDI_PROP_DEBUG
   1636 	(void) ddi_prop_debug(1);	/* Enable property debugging */
   1637 #endif	/* DDI_PROP_DEBUG */
   1638 }
   1639 
   1640 /*
   1641  * The "status" property indicates the operational status of a device.
   1642  * If this property is present, the value is a string indicating the
   1643  * status of the device as follows:
   1644  *
   1645  *	"okay"		operational.
   1646  *	"disabled"	not operational, but might become operational.
   1647  *	"fail"		not operational because a fault has been detected,
   1648  *			and it is unlikely that the device will become
   1649  *			operational without repair. no additional details
   1650  *			are available.
   1651  *	"fail-xxx"	not operational because a fault has been detected,
   1652  *			and it is unlikely that the device will become
   1653  *			operational without repair. "xxx" is additional
   1654  *			human-readable information about the particular
   1655  *			fault condition that was detected.
   1656  *
   1657  * The absence of this property means that the operational status is
   1658  * unknown or okay.
   1659  *
   1660  * This routine checks the status property of the specified device node
   1661  * and returns 0 if the operational status indicates failure, and 1 otherwise.
   1662  *
   1663  * The property may exist on plug-in cards the existed before IEEE 1275-1994.
   1664  * And, in that case, the property may not even be a string. So we carefully
   1665  * check for the value "fail", in the beginning of the string, noting
   1666  * the property length.
   1667  */
   1668 int
   1669 status_okay(int id, char *buf, int buflen)
   1670 {
   1671 	char status_buf[OBP_MAXPROPNAME];
   1672 	char *bufp = buf;
   1673 	int len = buflen;
   1674 	int proplen;
   1675 	static const char *status = "status";
   1676 	static const char *fail = "fail";
   1677 	size_t fail_len = strlen(fail);
   1678 
   1679 	/*
   1680 	 * Get the proplen ... if it's smaller than "fail",
   1681 	 * or doesn't exist ... then we don't care, since
   1682 	 * the value can't begin with the char string "fail".
   1683 	 *
   1684 	 * NB: proplen, if it's a string, includes the NULL in the
   1685 	 * the size of the property, and fail_len does not.
   1686 	 */
   1687 	proplen = prom_getproplen((pnode_t)id, (caddr_t)status);
   1688 	if (proplen <= fail_len)	/* nonexistent or uninteresting len */
   1689 		return (1);
   1690 
   1691 	/*
   1692 	 * if a buffer was provided, use it
   1693 	 */
   1694 	if ((buf == (char *)NULL) || (buflen <= 0)) {
   1695 		bufp = status_buf;
   1696 		len = sizeof (status_buf);
   1697 	}
   1698 	*bufp = (char)0;
   1699 
   1700 	/*
   1701 	 * Get the property into the buffer, to the extent of the buffer,
   1702 	 * and in case the buffer is smaller than the property size,
   1703 	 * NULL terminate the buffer. (This handles the case where
   1704 	 * a buffer was passed in and the caller wants to print the
   1705 	 * value, but the buffer was too small).
   1706 	 */
   1707 	(void) prom_bounded_getprop((pnode_t)id, (caddr_t)status,
   1708 	    (caddr_t)bufp, len);
   1709 	*(bufp + len - 1) = (char)0;
   1710 
   1711 	/*
   1712 	 * If the value begins with the char string "fail",
   1713 	 * then it means the node is failed. We don't care
   1714 	 * about any other values. We assume the node is ok
   1715 	 * although it might be 'disabled'.
   1716 	 */
   1717 	if (strncmp(bufp, fail, fail_len) == 0)
   1718 		return (0);
   1719 
   1720 	return (1);
   1721 }
   1722 
   1723 
   1724 /*
   1725  * We set the cpu type from the idprom, if we can.
   1726  * Note that we just read out the contents of it, for the most part.
   1727  */
   1728 void
   1729 setcputype(void)
   1730 {
   1731 	/*
   1732 	 * We cache the idprom info early on so that we don't
   1733 	 * rummage through the NVRAM unnecessarily later.
   1734 	 */
   1735 	(void) prom_getidprom((caddr_t)&idprom, sizeof (idprom));
   1736 }
   1737 
   1738 /*
   1739  *  Here is where we actually infer meanings to the members of idprom_t
   1740  */
   1741 void
   1742 parse_idprom(void)
   1743 {
   1744 	if (idprom.id_format == IDFORM_1) {
   1745 		(void) localetheraddr((struct ether_addr *)idprom.id_ether,
   1746 		    (struct ether_addr *)NULL);
   1747 		(void) snprintf(hw_serial, HW_HOSTID_LEN, "%u",
   1748 		    (idprom.id_machine << 24) + idprom.id_serial);
   1749 	} else
   1750 		prom_printf("Invalid format code in IDprom.\n");
   1751 }
   1752 
   1753 /*
   1754  * Allow for implementation specific correction of PROM property values.
   1755  */
   1756 /*ARGSUSED*/
   1757 void
   1758 impl_fix_props(dev_info_t *dip, dev_info_t *ch_dip, char *name, int len,
   1759     caddr_t buffer)
   1760 {
   1761 	/*
   1762 	 * There are no adjustments needed in this implementation.
   1763 	 */
   1764 }
   1765 
   1766 /*
   1767  * The following functions ready a cautious request to go up to the nexus
   1768  * driver.  It is up to the nexus driver to decide how to process the request.
   1769  * It may choose to call i_ddi_do_caut_get/put in this file, or do it
   1770  * differently.
   1771  */
   1772 
   1773 static void
   1774 i_ddi_caut_getput_ctlops(
   1775     ddi_acc_impl_t *hp, uint64_t host_addr, uint64_t dev_addr, size_t size,
   1776     size_t repcount, uint_t flags, ddi_ctl_enum_t cmd)
   1777 {
   1778 	peekpoke_ctlops_t	cautacc_ctlops_arg;
   1779 
   1780 	cautacc_ctlops_arg.size = size;
   1781 	cautacc_ctlops_arg.dev_addr = dev_addr;
   1782 	cautacc_ctlops_arg.host_addr = host_addr;
   1783 	cautacc_ctlops_arg.handle = (ddi_acc_handle_t)hp;
   1784 	cautacc_ctlops_arg.repcount = repcount;
   1785 	cautacc_ctlops_arg.flags = flags;
   1786 
   1787 	(void) ddi_ctlops(hp->ahi_common.ah_dip, hp->ahi_common.ah_dip, cmd,
   1788 	    &cautacc_ctlops_arg, NULL);
   1789 }
   1790 
   1791 uint8_t
   1792 i_ddi_caut_get8(ddi_acc_impl_t *hp, uint8_t *addr)
   1793 {
   1794 	uint8_t value;
   1795 	i_ddi_caut_getput_ctlops(hp, (uint64_t)&value, (uint64_t)addr,
   1796 	    sizeof (uint8_t), 1, 0, DDI_CTLOPS_PEEK);
   1797 
   1798 	return (value);
   1799 }
   1800 
   1801 uint16_t
   1802 i_ddi_caut_get16(ddi_acc_impl_t *hp, uint16_t *addr)
   1803 {
   1804 	uint16_t value;
   1805 	i_ddi_caut_getput_ctlops(hp, (uint64_t)&value, (uint64_t)addr,
   1806 	    sizeof (uint16_t), 1, 0, DDI_CTLOPS_PEEK);
   1807 
   1808 	return (value);
   1809 }
   1810 
   1811 uint32_t
   1812 i_ddi_caut_get32(ddi_acc_impl_t *hp, uint32_t *addr)
   1813 {
   1814 	uint32_t value;
   1815 	i_ddi_caut_getput_ctlops(hp, (uint64_t)&value, (uint64_t)addr,
   1816 	    sizeof (uint32_t), 1, 0, DDI_CTLOPS_PEEK);
   1817 
   1818 	return (value);
   1819 }
   1820 
   1821 uint64_t
   1822 i_ddi_caut_get64(ddi_acc_impl_t *hp, uint64_t *addr)
   1823 {
   1824 	uint64_t value;
   1825 	i_ddi_caut_getput_ctlops(hp, (uint64_t)&value, (uint64_t)addr,
   1826 	    sizeof (uint64_t), 1, 0, DDI_CTLOPS_PEEK);
   1827 
   1828 	return (value);
   1829 }
   1830 
   1831 void
   1832 i_ddi_caut_put8(ddi_acc_impl_t *hp, uint8_t *addr, uint8_t value)
   1833 {
   1834 	i_ddi_caut_getput_ctlops(hp, (uint64_t)&value, (uint64_t)addr,
   1835 	    sizeof (uint8_t), 1, 0, DDI_CTLOPS_POKE);
   1836 }
   1837 
   1838 void
   1839 i_ddi_caut_put16(ddi_acc_impl_t *hp, uint16_t *addr, uint16_t value)
   1840 {
   1841 	i_ddi_caut_getput_ctlops(hp, (uint64_t)&value, (uint64_t)addr,
   1842 	    sizeof (uint16_t), 1, 0, DDI_CTLOPS_POKE);
   1843 }
   1844 
   1845 void
   1846 i_ddi_caut_put32(ddi_acc_impl_t *hp, uint32_t *addr, uint32_t value)
   1847 {
   1848 	i_ddi_caut_getput_ctlops(hp, (uint64_t)&value, (uint64_t)addr,
   1849 	    sizeof (uint32_t), 1, 0, DDI_CTLOPS_POKE);
   1850 }
   1851 
   1852 void
   1853 i_ddi_caut_put64(ddi_acc_impl_t *hp, uint64_t *addr, uint64_t value)
   1854 {
   1855 	i_ddi_caut_getput_ctlops(hp, (uint64_t)&value, (uint64_t)addr,
   1856 	    sizeof (uint64_t), 1, 0, DDI_CTLOPS_POKE);
   1857 }
   1858 
   1859 void
   1860 i_ddi_caut_rep_get8(ddi_acc_impl_t *hp, uint8_t *host_addr, uint8_t *dev_addr,
   1861 	size_t repcount, uint_t flags)
   1862 {
   1863 	i_ddi_caut_getput_ctlops(hp, (uint64_t)host_addr, (uint64_t)dev_addr,
   1864 	    sizeof (uint8_t), repcount, flags, DDI_CTLOPS_PEEK);
   1865 }
   1866 
   1867 void
   1868 i_ddi_caut_rep_get16(ddi_acc_impl_t *hp, uint16_t *host_addr,
   1869     uint16_t *dev_addr, size_t repcount, uint_t flags)
   1870 {
   1871 	i_ddi_caut_getput_ctlops(hp, (uint64_t)host_addr, (uint64_t)dev_addr,
   1872 	    sizeof (uint16_t), repcount, flags, DDI_CTLOPS_PEEK);
   1873 }
   1874 
   1875 void
   1876 i_ddi_caut_rep_get32(ddi_acc_impl_t *hp, uint32_t *host_addr,
   1877     uint32_t *dev_addr, size_t repcount, uint_t flags)
   1878 {
   1879 	i_ddi_caut_getput_ctlops(hp, (uint64_t)host_addr, (uint64_t)dev_addr,
   1880 	    sizeof (uint32_t), repcount, flags, DDI_CTLOPS_PEEK);
   1881 }
   1882 
   1883 void
   1884 i_ddi_caut_rep_get64(ddi_acc_impl_t *hp, uint64_t *host_addr,
   1885     uint64_t *dev_addr, size_t repcount, uint_t flags)
   1886 {
   1887 	i_ddi_caut_getput_ctlops(hp, (uint64_t)host_addr, (uint64_t)dev_addr,
   1888 	    sizeof (uint64_t), repcount, flags, DDI_CTLOPS_PEEK);
   1889 }
   1890 
   1891 void
   1892 i_ddi_caut_rep_put8(ddi_acc_impl_t *hp, uint8_t *host_addr, uint8_t *dev_addr,
   1893 	size_t repcount, uint_t flags)
   1894 {
   1895 	i_ddi_caut_getput_ctlops(hp, (uint64_t)host_addr, (uint64_t)dev_addr,
   1896 	    sizeof (uint8_t), repcount, flags, DDI_CTLOPS_POKE);
   1897 }
   1898 
   1899 void
   1900 i_ddi_caut_rep_put16(ddi_acc_impl_t *hp, uint16_t *host_addr,
   1901     uint16_t *dev_addr, size_t repcount, uint_t flags)
   1902 {
   1903 	i_ddi_caut_getput_ctlops(hp, (uint64_t)host_addr, (uint64_t)dev_addr,
   1904 	    sizeof (uint16_t), repcount, flags, DDI_CTLOPS_POKE);
   1905 }
   1906 
   1907 void
   1908 i_ddi_caut_rep_put32(ddi_acc_impl_t *hp, uint32_t *host_addr,
   1909     uint32_t *dev_addr, size_t repcount, uint_t flags)
   1910 {
   1911 	i_ddi_caut_getput_ctlops(hp, (uint64_t)host_addr, (uint64_t)dev_addr,
   1912 	    sizeof (uint32_t), repcount, flags, DDI_CTLOPS_POKE);
   1913 }
   1914 
   1915 void
   1916 i_ddi_caut_rep_put64(ddi_acc_impl_t *hp, uint64_t *host_addr,
   1917     uint64_t *dev_addr, size_t repcount, uint_t flags)
   1918 {
   1919 	i_ddi_caut_getput_ctlops(hp, (uint64_t)host_addr, (uint64_t)dev_addr,
   1920 	    sizeof (uint64_t), repcount, flags, DDI_CTLOPS_POKE);
   1921 }
   1922 
   1923 /*
   1924  * This is called only to process peek/poke when the DIP is NULL.
   1925  * Assume that this is for memory, as nexi take care of device safe accesses.
   1926  */
   1927 int
   1928 peekpoke_mem(ddi_ctl_enum_t cmd, peekpoke_ctlops_t *in_args)
   1929 {
   1930 	int err = DDI_SUCCESS;
   1931 	on_trap_data_t otd;
   1932 
   1933 	/* Set up protected environment. */
   1934 	if (!on_trap(&otd, OT_DATA_ACCESS)) {
   1935 		uintptr_t tramp = otd.ot_trampoline;
   1936 
   1937 		if (cmd == DDI_CTLOPS_POKE) {
   1938 			otd.ot_trampoline = (uintptr_t)&poke_fault;
   1939 			err = do_poke(in_args->size, (void *)in_args->dev_addr,
   1940 			    (void *)in_args->host_addr);
   1941 		} else {
   1942 			otd.ot_trampoline = (uintptr_t)&peek_fault;
   1943 			err = do_peek(in_args->size, (void *)in_args->dev_addr,
   1944 			    (void *)in_args->host_addr);
   1945 		}
   1946 		otd.ot_trampoline = tramp;
   1947 	} else
   1948 		err = DDI_FAILURE;
   1949 
   1950 	/* Take down protected environment. */
   1951 	no_trap();
   1952 
   1953 	return (err);
   1954 }
   1955 
   1956 /*
   1957  * Platform independent DR routines
   1958  */
   1959 
   1960 static int
   1961 ndi2errno(int n)
   1962 {
   1963 	int err = 0;
   1964 
   1965 	switch (n) {
   1966 		case NDI_NOMEM:
   1967 			err = ENOMEM;
   1968 			break;
   1969 		case NDI_BUSY:
   1970 			err = EBUSY;
   1971 			break;
   1972 		case NDI_FAULT:
   1973 			err = EFAULT;
   1974 			break;
   1975 		case NDI_FAILURE:
   1976 			err = EIO;
   1977 			break;
   1978 		case NDI_SUCCESS:
   1979 			break;
   1980 		case NDI_BADHANDLE:
   1981 		default:
   1982 			err = EINVAL;
   1983 			break;
   1984 	}
   1985 	return (err);
   1986 }
   1987 
   1988 /*
   1989  * Prom tree node list
   1990  */
   1991 struct ptnode {
   1992 	pnode_t		nodeid;
   1993 	struct ptnode	*next;
   1994 };
   1995 
   1996 /*
   1997  * Prom tree walk arg
   1998  */
   1999 struct pta {
   2000 	dev_info_t	*pdip;
   2001 	devi_branch_t	*bp;
   2002 	uint_t		flags;
   2003 	dev_info_t	*fdip;
   2004 	struct ptnode	*head;
   2005 };
   2006 
   2007 static void
   2008 visit_node(pnode_t nodeid, struct pta *ap)
   2009 {
   2010 	struct ptnode	**nextp;
   2011 	int		(*select)(pnode_t, void *, uint_t);
   2012 
   2013 	ASSERT(nodeid != OBP_NONODE && nodeid != OBP_BADNODE);
   2014 
   2015 	select = ap->bp->create.prom_branch_select;
   2016 
   2017 	ASSERT(select);
   2018 
   2019 	if (select(nodeid, ap->bp->arg, 0) == DDI_SUCCESS) {
   2020 
   2021 		for (nextp = &ap->head; *nextp; nextp = &(*nextp)->next)
   2022 			;
   2023 
   2024 		*nextp = kmem_zalloc(sizeof (struct ptnode), KM_SLEEP);
   2025 
   2026 		(*nextp)->nodeid = nodeid;
   2027 	}
   2028 
   2029 	if ((ap->flags & DEVI_BRANCH_CHILD) == DEVI_BRANCH_CHILD)
   2030 		return;
   2031 
   2032 	nodeid = prom_childnode(nodeid);
   2033 	while (nodeid != OBP_NONODE && nodeid != OBP_BADNODE) {
   2034 		visit_node(nodeid, ap);
   2035 		nodeid = prom_nextnode(nodeid);
   2036 	}
   2037 }
   2038 
   2039 /*
   2040  * NOTE: The caller of this function must check for device contracts
   2041  * or LDI callbacks against this dip before setting the dip offline.
   2042  */
   2043 static int
   2044 set_infant_dip_offline(dev_info_t *dip, void *arg)
   2045 {
   2046 	char	*path = (char *)arg;
   2047 
   2048 	ASSERT(dip);
   2049 	ASSERT(arg);
   2050 
   2051 	if (i_ddi_node_state(dip) >= DS_ATTACHED) {
   2052 		(void) ddi_pathname(dip, path);
   2053 		cmn_err(CE_WARN, "Attempt to set offline flag on attached "
   2054 		    "node: %s", path);
   2055 		return (DDI_FAILURE);
   2056 	}
   2057 
   2058 	mutex_enter(&(DEVI(dip)->devi_lock));
   2059 	if (!DEVI_IS_DEVICE_OFFLINE(dip))
   2060 		DEVI_SET_DEVICE_OFFLINE(dip);
   2061 	mutex_exit(&(DEVI(dip)->devi_lock));
   2062 
   2063 	return (DDI_SUCCESS);
   2064 }
   2065 
   2066 typedef struct result {
   2067 	char	*path;
   2068 	int	result;
   2069 } result_t;
   2070 
   2071 static int
   2072 dip_set_offline(dev_info_t *dip, void *arg)
   2073 {
   2074 	int end;
   2075 	result_t *resp = (result_t *)arg;
   2076 
   2077 	ASSERT(dip);
   2078 	ASSERT(resp);
   2079 
   2080 	/*
   2081 	 * We stop the walk if e_ddi_offline_notify() returns
   2082 	 * failure, because this implies that one or more consumers
   2083 	 * (either LDI or contract based) has blocked the offline.
   2084 	 * So there is no point in conitnuing the walk
   2085 	 */
   2086 	if (e_ddi_offline_notify(dip) == DDI_FAILURE) {
   2087 		resp->result = DDI_FAILURE;
   2088 		return (DDI_WALK_TERMINATE);
   2089 	}
   2090 
   2091 	/*
   2092 	 * If set_infant_dip_offline() returns failure, it implies
   2093 	 * that we failed to set a particular dip offline. This
   2094 	 * does not imply that the offline as a whole should fail.
   2095 	 * We want to do the best we can, so we continue the walk.
   2096 	 */
   2097 	if (set_infant_dip_offline(dip, resp->path) == DDI_SUCCESS)
   2098 		end = DDI_SUCCESS;
   2099 	else
   2100 		end = DDI_FAILURE;
   2101 
   2102 	e_ddi_offline_finalize(dip, end);
   2103 
   2104 	return (DDI_WALK_CONTINUE);
   2105 }
   2106 
   2107 /*
   2108  * The call to e_ddi_offline_notify() exists for the
   2109  * unlikely error case that a branch we are trying to
   2110  * create already exists and has device contracts or LDI
   2111  * event callbacks against it.
   2112  *
   2113  * We allow create to succeed for such branches only if
   2114  * no constraints block the offline.
   2115  */
   2116 static int
   2117 branch_set_offline(dev_info_t *dip, char *path)
   2118 {
   2119 	int		circ;
   2120 	int		end;
   2121 	result_t	res;
   2122 
   2123 
   2124 	if (e_ddi_offline_notify(dip) == DDI_FAILURE) {
   2125 		return (DDI_FAILURE);
   2126 	}
   2127 
   2128 	if (set_infant_dip_offline(dip, path) == DDI_SUCCESS)
   2129 		end = DDI_SUCCESS;
   2130 	else
   2131 		end = DDI_FAILURE;
   2132 
   2133 	e_ddi_offline_finalize(dip, end);
   2134 
   2135 	if (end == DDI_FAILURE)
   2136 		return (DDI_FAILURE);
   2137 
   2138 	res.result = DDI_SUCCESS;
   2139 	res.path = path;
   2140 
   2141 	ndi_devi_enter(dip, &circ);
   2142 	ddi_walk_devs(ddi_get_child(dip), dip_set_offline, &res);
   2143 	ndi_devi_exit(dip, circ);
   2144 
   2145 	return (res.result);
   2146 }
   2147 
   2148 /*ARGSUSED*/
   2149 static int
   2150 create_prom_branch(void *arg, int has_changed)
   2151 {
   2152 	int		circ;
   2153 	int		exists, rv;
   2154 	pnode_t		nodeid;
   2155 	struct ptnode	*tnp;
   2156 	dev_info_t	*dip;
   2157 	struct pta	*ap = arg;
   2158 	devi_branch_t	*bp;
   2159 	char		*path;
   2160 
   2161 	ASSERT(ap);
   2162 	ASSERT(ap->fdip == NULL);
   2163 	ASSERT(ap->pdip && ndi_dev_is_prom_node(ap->pdip));
   2164 
   2165 	bp = ap->bp;
   2166 
   2167 	nodeid = ddi_get_nodeid(ap->pdip);
   2168 	if (nodeid == OBP_NONODE || nodeid == OBP_BADNODE) {
   2169 		cmn_err(CE_WARN, "create_prom_branch: invalid "
   2170 		    "nodeid: 0x%x", nodeid);
   2171 		return (EINVAL);
   2172 	}
   2173 
   2174 	ap->head = NULL;
   2175 
   2176 	nodeid = prom_childnode(nodeid);
   2177 	while (nodeid != OBP_NONODE && nodeid != OBP_BADNODE) {
   2178 		visit_node(nodeid, ap);
   2179 		nodeid = prom_nextnode(nodeid);
   2180 	}
   2181 
   2182 	if (ap->head == NULL)
   2183 		return (ENODEV);
   2184 
   2185 	path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
   2186 	rv = 0;
   2187 	while ((tnp = ap->head) != NULL) {
   2188 		ap->head = tnp->next;
   2189 
   2190 		ndi_devi_enter(ap->pdip, &circ);
   2191 
   2192 		/*
   2193 		 * Check if the branch already exists.
   2194 		 */
   2195 		exists = 0;
   2196 		dip = e_ddi_nodeid_to_dip(tnp->nodeid);
   2197 		if (dip != NULL) {
   2198 			exists = 1;
   2199 
   2200 			/* Parent is held busy, so release hold */
   2201 			ndi_rele_devi(dip);
   2202 #ifdef	DEBUG
   2203 			cmn_err(CE_WARN, "create_prom_branch: dip(%p) exists"
   2204 			    " for nodeid 0x%x", (void *)dip, tnp->nodeid);
   2205 #endif
   2206 		} else {
   2207 			dip = i_ddi_create_branch(ap->pdip, tnp->nodeid);
   2208 		}
   2209 
   2210 		kmem_free(tnp, sizeof (struct ptnode));
   2211 
   2212 		/*
   2213 		 * Hold the branch if it is not already held
   2214 		 */
   2215 		if (dip && !exists) {
   2216 			e_ddi_branch_hold(dip);
   2217 		}
   2218 
   2219 		ASSERT(dip == NULL || e_ddi_branch_held(dip));
   2220 
   2221 		/*
   2222 		 * Set all dips in the newly created branch offline so that
   2223 		 * only a "configure" operation can attach
   2224 		 * the branch
   2225 		 */
   2226 		if (dip == NULL || branch_set_offline(dip, path)
   2227 		    == DDI_FAILURE) {
   2228 			ndi_devi_exit(ap->pdip, circ);
   2229 			rv = EIO;
   2230 			continue;
   2231 		}
   2232 
   2233 		ASSERT(ddi_get_parent(dip) == ap->pdip);
   2234 
   2235 		ndi_devi_exit(ap->pdip, circ);
   2236 
   2237 		if (ap->flags & DEVI_BRANCH_CONFIGURE) {
   2238 			int error = e_ddi_branch_configure(dip, &ap->fdip, 0);
   2239 			if (error && rv == 0)
   2240 				rv = error;
   2241 		}
   2242 
   2243 		/*
   2244 		 * Invoke devi_branch_callback() (if it exists) only for
   2245 		 * newly created branches
   2246 		 */
   2247 		if (bp->devi_branch_callback && !exists)
   2248 			bp->devi_branch_callback(dip, bp->arg, 0);
   2249 	}
   2250 
   2251 	kmem_free(path, MAXPATHLEN);
   2252 
   2253 	return (rv);
   2254 }
   2255 
   2256 static int
   2257 sid_node_create(dev_info_t *pdip, devi_branch_t *bp, dev_info_t **rdipp)
   2258 {
   2259 	int			rv, circ, len;
   2260 	int			i, flags, ret;
   2261 	dev_info_t		*dip;
   2262 	char			*nbuf;
   2263 	char			*path;
   2264 	static const char	*noname = "<none>";
   2265 
   2266 	ASSERT(pdip);
   2267 	ASSERT(DEVI_BUSY_OWNED(pdip));
   2268 
   2269 	flags = 0;
   2270 
   2271 	/*
   2272 	 * Creating the root of a branch ?
   2273 	 */
   2274 	if (rdipp) {
   2275 		*rdipp = NULL;
   2276 		flags = DEVI_BRANCH_ROOT;
   2277 	}
   2278 
   2279 	ndi_devi_alloc_sleep(pdip, (char *)noname, DEVI_SID_NODEID, &dip);
   2280 	rv = bp->create.sid_branch_create(dip, bp->arg, flags);
   2281 
   2282 	nbuf = kmem_alloc(OBP_MAXDRVNAME, KM_SLEEP);
   2283 
   2284 	if (rv == DDI_WALK_ERROR) {
   2285 		cmn_err(CE_WARN, "e_ddi_branch_create: Error setting"
   2286 		    " properties on devinfo node %p",  (void *)dip);
   2287 		goto fail;
   2288 	}
   2289 
   2290 	len = OBP_MAXDRVNAME;
   2291 	if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip,
   2292 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "name", nbuf, &len)
   2293 	    != DDI_PROP_SUCCESS) {
   2294 		cmn_err(CE_WARN, "e_ddi_branch_create: devinfo node %p has"
   2295 		    "no name property", (void *)dip);
   2296 		goto fail;
   2297 	}
   2298 
   2299 	ASSERT(i_ddi_node_state(dip) == DS_PROTO);
   2300 	if (ndi_devi_set_nodename(dip, nbuf, 0) != NDI_SUCCESS) {
   2301 		cmn_err(CE_WARN, "e_ddi_branch_create: cannot set name (%s)"
   2302 		    " for devinfo node %p", nbuf, (void *)dip);
   2303 		goto fail;
   2304 	}
   2305 
   2306 	kmem_free(nbuf, OBP_MAXDRVNAME);
   2307 
   2308 	/*
   2309 	 * Ignore bind failures just like boot does
   2310 	 */
   2311 	(void) ndi_devi_bind_driver(dip, 0);
   2312 
   2313 	switch (rv) {
   2314 	case DDI_WALK_CONTINUE:
   2315 	case DDI_WALK_PRUNESIB:
   2316 		ndi_devi_enter(dip, &circ);
   2317 
   2318 		i = DDI_WALK_CONTINUE;
   2319 		for (; i == DDI_WALK_CONTINUE; ) {
   2320 			i = sid_node_create(dip, bp, NULL);
   2321 		}
   2322 
   2323 		ASSERT(i == DDI_WALK_ERROR || i == DDI_WALK_PRUNESIB);
   2324 		if (i == DDI_WALK_ERROR)
   2325 			rv = i;
   2326 		/*
   2327 		 * If PRUNESIB stop creating siblings
   2328 		 * of dip's child. Subsequent walk behavior
   2329 		 * is determined by rv returned by dip.
   2330 		 */
   2331 
   2332 		ndi_devi_exit(dip, circ);
   2333 		break;
   2334 	case DDI_WALK_TERMINATE:
   2335 		/*
   2336 		 * Don't create children and ask our parent
   2337 		 * to not create siblings either.
   2338 		 */
   2339 		rv = DDI_WALK_PRUNESIB;
   2340 		break;
   2341 	case DDI_WALK_PRUNECHILD:
   2342 		/*
   2343 		 * Don't create children, but ask parent to continue
   2344 		 * with siblings.
   2345 		 */
   2346 		rv = DDI_WALK_CONTINUE;
   2347 		break;
   2348 	default:
   2349 		ASSERT(0);
   2350 		break;
   2351 	}
   2352 
   2353 	if (rdipp)
   2354 		*rdipp = dip;
   2355 
   2356 	/*
   2357 	 * Set device offline - only the "configure" op should cause an attach.
   2358 	 * Note that it is safe to set the dip offline without checking
   2359 	 * for either device contract or layered driver (LDI) based constraints
   2360 	 * since there cannot be any contracts or LDI opens of this device.
   2361 	 * This is because this node is a newly created dip with the parent busy
   2362 	 * held, so no other thread can come in and attach this dip. A dip that
   2363 	 * has never been attached cannot have contracts since by definition
   2364 	 * a device contract (an agreement between a process and a device minor
   2365 	 * node) can only be created against a device that has minor nodes
   2366 	 * i.e is attached. Similarly an LDI open will only succeed if the
   2367 	 * dip is attached. We assert below that the dip is not attached.
   2368 	 */
   2369 	ASSERT(i_ddi_node_state(dip) < DS_ATTACHED);
   2370 	path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
   2371 	ret = set_infant_dip_offline(dip, path);
   2372 	ASSERT(ret == DDI_SUCCESS);
   2373 	kmem_free(path, MAXPATHLEN);
   2374 
   2375 	return (rv);
   2376 fail:
   2377 	(void) ndi_devi_free(dip);
   2378 	kmem_free(nbuf, OBP_MAXDRVNAME);
   2379 	return (DDI_WALK_ERROR);
   2380 }
   2381 
   2382 static int
   2383 create_sid_branch(
   2384 	dev_info_t	*pdip,
   2385 	devi_branch_t	*bp,
   2386 	dev_info_t	**dipp,
   2387 	uint_t		flags)
   2388 {
   2389 	int		rv = 0, state = DDI_WALK_CONTINUE;
   2390 	dev_info_t	*rdip;
   2391 
   2392 	while (state == DDI_WALK_CONTINUE) {
   2393 		int	circ;
   2394 
   2395 		ndi_devi_enter(pdip, &circ);
   2396 
   2397 		state = sid_node_create(pdip, bp, &rdip);
   2398 		if (rdip == NULL) {
   2399 			ndi_devi_exit(pdip, circ);
   2400 			ASSERT(state == DDI_WALK_ERROR);
   2401 			break;
   2402 		}
   2403 
   2404 		e_ddi_branch_hold(rdip);
   2405 
   2406 		ndi_devi_exit(pdip, circ);
   2407 
   2408 		if (flags & DEVI_BRANCH_CONFIGURE) {
   2409 			int error = e_ddi_branch_configure(rdip, dipp, 0);
   2410 			if (error && rv == 0)
   2411 				rv = error;
   2412 		}
   2413 
   2414 		/*
   2415 		 * devi_branch_callback() is optional
   2416 		 */
   2417 		if (bp->devi_branch_callback)
   2418 			bp->devi_branch_callback(rdip, bp->arg, 0);
   2419 	}
   2420 
   2421 	ASSERT(state == DDI_WALK_ERROR || state == DDI_WALK_PRUNESIB);
   2422 
   2423 	return (state == DDI_WALK_ERROR ? EIO : rv);
   2424 }
   2425 
   2426 int
   2427 e_ddi_branch_create(
   2428 	dev_info_t	*pdip,
   2429 	devi_branch_t	*bp,
   2430 	dev_info_t	**dipp,
   2431 	uint_t		flags)
   2432 {
   2433 	int prom_devi, sid_devi, error;
   2434 
   2435 	if (pdip == NULL || bp == NULL || bp->type == 0)
   2436 		return (EINVAL);
   2437 
   2438 	prom_devi = (bp->type == DEVI_BRANCH_PROM) ? 1 : 0;
   2439 	sid_devi = (bp->type == DEVI_BRANCH_SID) ? 1 : 0;
   2440 
   2441 	if (prom_devi && bp->create.prom_branch_select == NULL)
   2442 		return (EINVAL);
   2443 	else if (sid_devi && bp->create.sid_branch_create == NULL)
   2444 		return (EINVAL);
   2445 	else if (!prom_devi && !sid_devi)
   2446 		return (EINVAL);
   2447 
   2448 	if (flags & DEVI_BRANCH_EVENT)
   2449 		return (EINVAL);
   2450 
   2451 	if (prom_devi) {
   2452 		struct pta pta = {0};
   2453 
   2454 		pta.pdip = pdip;
   2455 		pta.bp = bp;
   2456 		pta.flags = flags;
   2457 
   2458 		error = prom_tree_access(create_prom_branch, &pta, NULL);
   2459 
   2460 		if (dipp)
   2461 			*dipp = pta.fdip;
   2462 		else if (pta.fdip)
   2463 			ndi_rele_devi(pta.fdip);
   2464 	} else {
   2465 		error = create_sid_branch(pdip, bp, dipp, flags);
   2466 	}
   2467 
   2468 	return (error);
   2469 }
   2470 
   2471 int
   2472 e_ddi_branch_configure(dev_info_t *rdip, dev_info_t **dipp, uint_t flags)
   2473 {
   2474 	int		rv;
   2475 	char		*devnm;
   2476 	dev_info_t	*pdip;
   2477 
   2478 	if (dipp)
   2479 		*dipp = NULL;
   2480 
   2481 	if (rdip == NULL || flags != 0 || (flags & DEVI_BRANCH_EVENT))
   2482 		return (EINVAL);
   2483 
   2484 	pdip = ddi_get_parent(rdip);
   2485 
   2486 	ndi_hold_devi(pdip);
   2487 
   2488 	if (!e_ddi_branch_held(rdip)) {
   2489 		ndi_rele_devi(pdip);
   2490 		cmn_err(CE_WARN, "e_ddi_branch_configure: "
   2491 		    "dip(%p) not held", (void *)rdip);
   2492 		return (EINVAL);
   2493 	}
   2494 
   2495 	if (i_ddi_node_state(rdip) < DS_INITIALIZED) {
   2496 		/*
   2497 		 * First attempt to bind a driver. If we fail, return
   2498 		 * success (On some platforms, dips for some device
   2499 		 * types (CPUs) may not have a driver)
   2500 		 */
   2501 		if (ndi_devi_bind_driver(rdip, 0) != NDI_SUCCESS) {
   2502 			ndi_rele_devi(pdip);
   2503 			return (0);
   2504 		}
   2505 
   2506 		if (ddi_initchild(pdip, rdip) != DDI_SUCCESS) {
   2507 			rv = NDI_FAILURE;
   2508 			goto out;
   2509 		}
   2510 	}
   2511 
   2512 	ASSERT(i_ddi_node_state(rdip) >= DS_INITIALIZED);
   2513 
   2514 	devnm = kmem_alloc(MAXNAMELEN + 1, KM_SLEEP);
   2515 
   2516 	(void) ddi_deviname(rdip, devnm);
   2517 
   2518 	if ((rv = ndi_devi_config_one(pdip, devnm+1, &rdip,
   2519 	    NDI_DEVI_ONLINE | NDI_CONFIG)) == NDI_SUCCESS) {
   2520 		/* release hold from ndi_devi_config_one() */
   2521 		ndi_rele_devi(rdip);
   2522 	}
   2523 
   2524 	kmem_free(devnm, MAXNAMELEN + 1);
   2525 out:
   2526 	if (rv != NDI_SUCCESS && dipp && rdip) {
   2527 		ndi_hold_devi(rdip);
   2528 		*dipp = rdip;
   2529 	}
   2530 	ndi_rele_devi(pdip);
   2531 	return (ndi2errno(rv));
   2532 }
   2533 
   2534 void
   2535 e_ddi_branch_hold(dev_info_t *rdip)
   2536 {
   2537 	if (e_ddi_branch_held(rdip)) {
   2538 		cmn_err(CE_WARN, "e_ddi_branch_hold: branch already held");
   2539 		return;
   2540 	}
   2541 
   2542 	mutex_enter(&DEVI(rdip)->devi_lock);
   2543 	if ((DEVI(rdip)->devi_flags & DEVI_BRANCH_HELD) == 0) {
   2544 		DEVI(rdip)->devi_flags |= DEVI_BRANCH_HELD;
   2545 		DEVI(rdip)->devi_ref++;
   2546 	}
   2547 	ASSERT(DEVI(rdip)->devi_ref > 0);
   2548 	mutex_exit(&DEVI(rdip)->devi_lock);
   2549 }
   2550 
   2551 int
   2552 e_ddi_branch_held(dev_info_t *rdip)
   2553 {
   2554 	int rv = 0;
   2555 
   2556 	mutex_enter(&DEVI(rdip)->devi_lock);
   2557 	if ((DEVI(rdip)->devi_flags & DEVI_BRANCH_HELD) &&
   2558 	    DEVI(rdip)->devi_ref > 0) {
   2559 		rv = 1;
   2560 	}
   2561 	mutex_exit(&DEVI(rdip)->devi_lock);
   2562 
   2563 	return (rv);
   2564 }
   2565 void
   2566 e_ddi_branch_rele(dev_info_t *rdip)
   2567 {
   2568 	mutex_enter(&DEVI(rdip)->devi_lock);
   2569 	DEVI(rdip)->devi_flags &= ~DEVI_BRANCH_HELD;
   2570 	DEVI(rdip)->devi_ref--;
   2571 	mutex_exit(&DEVI(rdip)->devi_lock);
   2572 }
   2573 
   2574 int
   2575 e_ddi_branch_unconfigure(
   2576 	dev_info_t *rdip,
   2577 	dev_info_t **dipp,
   2578 	uint_t flags)
   2579 {
   2580 	int	circ, rv;
   2581 	int	destroy;
   2582 	char	*devnm;
   2583 	uint_t	nflags;
   2584 	dev_info_t *pdip;
   2585 
   2586 	if (dipp)
   2587 		*dipp = NULL;
   2588 
   2589 	if (rdip == NULL)
   2590 		return (EINVAL);
   2591 
   2592 	pdip = ddi_get_parent(rdip);
   2593 
   2594 	ASSERT(pdip);
   2595 
   2596 	/*
   2597 	 * Check if caller holds pdip busy - can cause deadlocks during
   2598 	 * devfs_clean()
   2599 	 */
   2600 	if (DEVI_BUSY_OWNED(pdip)) {
   2601 		cmn_err(CE_WARN, "e_ddi_branch_unconfigure: failed: parent"
   2602 		    " devinfo node(%p) is busy held", (void *)pdip);
   2603 		return (EINVAL);
   2604 	}
   2605 
   2606 	destroy = (flags & DEVI_BRANCH_DESTROY) ? 1 : 0;
   2607 
   2608 	devnm = kmem_alloc(MAXNAMELEN + 1, KM_SLEEP);
   2609 
   2610 	ndi_devi_enter(pdip, &circ);
   2611 	(void) ddi_deviname(rdip, devnm);
   2612 	ndi_devi_exit(pdip, circ);
   2613 
   2614 	/*
   2615 	 * ddi_deviname() returns a component name with / prepended.
   2616 	 */
   2617 	(void) devfs_clean(pdip, devnm + 1, DV_CLEAN_FORCE);
   2618 
   2619 	ndi_devi_enter(pdip, &circ);
   2620 
   2621 	/*
   2622 	 * Recreate device name as it may have changed state (init/uninit)
   2623 	 * when parent busy lock was dropped for devfs_clean()
   2624 	 */
   2625 	(void) ddi_deviname(rdip, devnm);
   2626 
   2627 	if (!e_ddi_branch_held(rdip)) {
   2628 		kmem_free(devnm, MAXNAMELEN + 1);
   2629 		ndi_devi_exit(pdip, circ);
   2630 		cmn_err(CE_WARN, "e_ddi_%s_branch: dip(%p) not held",
   2631 		    destroy ? "destroy" : "unconfigure", (void *)rdip);
   2632 		return (EINVAL);
   2633 	}
   2634 
   2635 	/*
   2636 	 * Release hold on the branch. This is ok since we are holding the
   2637 	 * parent busy. If rdip is not removed, we must do a hold on the
   2638 	 * branch before returning.
   2639 	 */
   2640 	e_ddi_branch_rele(rdip);
   2641 
   2642 	nflags = NDI_DEVI_OFFLINE;
   2643 	if (destroy || (flags & DEVI_BRANCH_DESTROY)) {
   2644 		nflags |= NDI_DEVI_REMOVE;
   2645 		destroy = 1;
   2646 	} else {
   2647 		nflags |= NDI_UNCONFIG;		/* uninit but don't remove */
   2648 	}
   2649 
   2650 	if (flags & DEVI_BRANCH_EVENT)
   2651 		nflags |= NDI_POST_EVENT;
   2652 
   2653 	if (i_ddi_devi_attached(pdip) &&
   2654 	    (i_ddi_node_state(rdip) >= DS_INITIALIZED)) {
   2655 		rv = ndi_devi_unconfig_one(pdip, devnm+1, dipp, nflags);
   2656 	} else {
   2657 		rv = e_ddi_devi_unconfig(rdip, dipp, nflags);
   2658 		if (rv == NDI_SUCCESS) {
   2659 			ASSERT(!destroy || ddi_get_child(rdip) == NULL);
   2660 			rv = ndi_devi_offline(rdip, nflags);
   2661 		}
   2662 	}
   2663 
   2664 	if (!destroy || rv != NDI_SUCCESS) {
   2665 		/* The dip still exists, so do a hold */
   2666 		e_ddi_branch_hold(rdip);
   2667 	}
   2668 out:
   2669 	kmem_free(devnm, MAXNAMELEN + 1);
   2670 	ndi_devi_exit(pdip, circ);
   2671 	return (ndi2errno(rv));
   2672 }
   2673 
   2674 int
   2675 e_ddi_branch_destroy(dev_info_t *rdip, dev_info_t **dipp, uint_t flag)
   2676 {
   2677 	return (e_ddi_branch_unconfigure(rdip, dipp,
   2678 	    flag|DEVI_BRANCH_DESTROY));
   2679 }
   2680 
   2681 /*
   2682  * Number of chains for hash table
   2683  */
   2684 #define	NUMCHAINS	17
   2685 
   2686 /*
   2687  * Devinfo busy arg
   2688  */
   2689 struct devi_busy {
   2690 	int dv_total;
   2691 	int s_total;
   2692 	mod_hash_t *dv_hash;
   2693 	mod_hash_t *s_hash;
   2694 	int (*callback)(dev_info_t *, void *, uint_t);
   2695 	void *arg;
   2696 };
   2697 
   2698 static int
   2699 visit_dip(dev_info_t *dip, void *arg)
   2700 {
   2701 	uintptr_t sbusy, dvbusy, ref;
   2702 	struct devi_busy *bsp = arg;
   2703 
   2704 	ASSERT(bsp->callback);
   2705 
   2706 	/*
   2707 	 * A dip cannot be busy if its reference count is 0
   2708 	 */
   2709 	if ((ref = e_ddi_devi_holdcnt(dip)) == 0) {
   2710 		return (bsp->callback(dip, bsp->arg, 0));
   2711 	}
   2712 
   2713 	if (mod_hash_find(bsp->dv_hash, dip, (mod_hash_val_t *)&dvbusy))
   2714 		dvbusy = 0;
   2715 
   2716 	/*
   2717 	 * To catch device opens currently maintained on specfs common snodes.
   2718 	 */
   2719 	if (mod_hash_find(bsp->s_hash, dip, (mod_hash_val_t *)&sbusy))
   2720 		sbusy = 0;
   2721 
   2722 #ifdef	DEBUG
   2723 	if (ref < sbusy || ref < dvbusy) {
   2724 		cmn_err(CE_WARN, "dip(%p): sopen = %lu, dvopen = %lu "
   2725 		    "dip ref = %lu\n", (void *)dip, sbusy, dvbusy, ref);
   2726 	}
   2727 #endif
   2728 
   2729 	dvbusy = (sbusy > dvbusy) ? sbusy : dvbusy;
   2730 
   2731 	return (bsp->callback(dip, bsp->arg, dvbusy));
   2732 }
   2733 
   2734 static int
   2735 visit_snode(struct snode *sp, void *arg)
   2736 {
   2737 	uintptr_t sbusy;
   2738 	dev_info_t *dip;
   2739 	int count;
   2740 	struct devi_busy *bsp = arg;
   2741 
   2742 	ASSERT(sp);
   2743 
   2744 	/*
   2745 	 * The stable lock is held. This prevents
   2746 	 * the snode and its associated dip from
   2747 	 * going away.
   2748 	 */
   2749 	dip = NULL;
   2750 	count = spec_devi_open_count(sp, &dip);
   2751 
   2752 	if (count <= 0)
   2753 		return (DDI_WALK_CONTINUE);
   2754 
   2755 	ASSERT(dip);
   2756 
   2757 	if (mod_hash_remove(bsp->s_hash, dip, (mod_hash_val_t *)&sbusy))
   2758 		sbusy = count;
   2759 	else
   2760 		sbusy += count;
   2761 
   2762 	if (mod_hash_insert(bsp->s_hash, dip, (mod_hash_val_t)sbusy)) {
   2763 		cmn_err(CE_WARN, "%s: s_hash insert failed: dip=0x%p, "
   2764 		    "sbusy = %lu", "e_ddi_branch_referenced",
   2765 		    (void *)dip, sbusy);
   2766 	}
   2767 
   2768 	bsp->s_total += count;
   2769 
   2770 	return (DDI_WALK_CONTINUE);
   2771 }
   2772 
   2773 static void
   2774 visit_dvnode(struct dv_node *dv, void *arg)
   2775 {
   2776 	uintptr_t dvbusy;
   2777 	uint_t count;
   2778 	struct vnode *vp;
   2779 	struct devi_busy *bsp = arg;
   2780 
   2781 	ASSERT(dv && dv->dv_devi);
   2782 
   2783 	vp = DVTOV(dv);
   2784 
   2785 	mutex_enter(&vp->v_lock);
   2786 	count = vp->v_count;
   2787 	mutex_exit(&vp->v_lock);
   2788 
   2789 	if (!count)
   2790 		return;
   2791 
   2792 	if (mod_hash_remove(bsp->dv_hash, dv->dv_devi,
   2793 	    (mod_hash_val_t *)&dvbusy))
   2794 		dvbusy = count;
   2795 	else
   2796 		dvbusy += count;
   2797 
   2798 	if (mod_hash_insert(bsp->dv_hash, dv->dv_devi,
   2799 	    (mod_hash_val_t)dvbusy)) {
   2800 		cmn_err(CE_WARN, "%s: dv_hash insert failed: dip=0x%p, "
   2801 		    "dvbusy=%lu", "e_ddi_branch_referenced",
   2802 		    (void *)dv->dv_devi, dvbusy);
   2803 	}
   2804 
   2805 	bsp->dv_total += count;
   2806 }
   2807 
   2808 /*
   2809  * Returns reference count on success or -1 on failure.
   2810  */
   2811 int
   2812 e_ddi_branch_referenced(
   2813 	dev_info_t *rdip,
   2814 	int (*callback)(dev_info_t *dip, void *arg, uint_t ref),
   2815 	void *arg)
   2816 {
   2817 	int circ;
   2818 	char *path;
   2819 	dev_info_t *pdip;
   2820 	struct devi_busy bsa = {0};
   2821 
   2822 	ASSERT(rdip);
   2823 
   2824 	path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
   2825 
   2826 	ndi_hold_devi(rdip);
   2827 
   2828 	pdip = ddi_get_parent(rdip);
   2829 
   2830 	ASSERT(pdip);
   2831 
   2832 	/*
   2833 	 * Check if caller holds pdip busy - can cause deadlocks during
   2834 	 * devfs_walk()
   2835 	 */
   2836 	if (!e_ddi_branch_held(rdip) || DEVI_BUSY_OWNED(pdip)) {
   2837 		cmn_err(CE_WARN, "e_ddi_branch_referenced: failed: "
   2838 		    "devinfo branch(%p) not held or parent busy held",
   2839 		    (void *)rdip);
   2840 		ndi_rele_devi(rdip);
   2841 		kmem_free(path, MAXPATHLEN);
   2842 		return (-1);
   2843 	}
   2844 
   2845 	ndi_devi_enter(pdip, &circ);
   2846 	(void) ddi_pathname(rdip, path);
   2847 	ndi_devi_exit(pdip, circ);
   2848 
   2849 	bsa.dv_hash = mod_hash_create_ptrhash("dv_node busy hash", NUMCHAINS,
   2850 	    mod_hash_null_valdtor, sizeof (struct dev_info));
   2851 
   2852 	bsa.s_hash = mod_hash_create_ptrhash("snode busy hash", NUMCHAINS,
   2853 	    mod_hash_null_valdtor, sizeof (struct snode));
   2854 
   2855 	if (devfs_walk(path, visit_dvnode, &bsa)) {
   2856 		cmn_err(CE_WARN, "e_ddi_branch_referenced: "
   2857 		    "devfs walk failed for: %s", path);
   2858 		kmem_free(path, MAXPATHLEN);
   2859 		bsa.s_total = bsa.dv_total = -1;
   2860 		goto out;
   2861 	}
   2862 
   2863 	kmem_free(path, MAXPATHLEN);
   2864 
   2865 	/*
   2866 	 * Walk the snode table to detect device opens, which are currently
   2867 	 * maintained on specfs common snodes.
   2868 	 */
   2869 	spec_snode_walk(visit_snode, &bsa);
   2870 
   2871 	if (callback == NULL)
   2872 		goto out;
   2873 
   2874 	bsa.callback = callback;
   2875 	bsa.arg = arg;
   2876 
   2877 	if (visit_dip(rdip, &bsa) == DDI_WALK_CONTINUE) {
   2878 		ndi_devi_enter(rdip, &circ);
   2879 		ddi_walk_devs(ddi_get_child(rdip), visit_dip, &bsa);
   2880 		ndi_devi_exit(rdip, circ);
   2881 	}
   2882 
   2883 out:
   2884 	ndi_rele_devi(rdip);
   2885 	mod_hash_destroy_ptrhash(bsa.s_hash);
   2886 	mod_hash_destroy_ptrhash(bsa.dv_hash);
   2887 	return (bsa.s_total > bsa.dv_total ? bsa.s_total : bsa.dv_total);
   2888 }
   2889