xref: /titanic_41/usr/src/uts/sun4/os/ddi_impl.c (revision 0b6016e6ff70af39f99c9cc28e0c2207c8f5413c)
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  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 /*
29  * sun4 specific DDI implementation
30  */
31 #include <sys/cpuvar.h>
32 #include <sys/ddi_subrdefs.h>
33 #include <sys/machsystm.h>
34 #include <sys/sunndi.h>
35 #include <sys/sysmacros.h>
36 #include <sys/ontrap.h>
37 #include <vm/seg_kmem.h>
38 #include <sys/membar.h>
39 #include <sys/dditypes.h>
40 #include <sys/ndifm.h>
41 #include <sys/fm/io/ddi.h>
42 #include <sys/ivintr.h>
43 #include <sys/bootconf.h>
44 #include <sys/conf.h>
45 #include <sys/ethernet.h>
46 #include <sys/idprom.h>
47 #include <sys/promif.h>
48 #include <sys/prom_plat.h>
49 #include <sys/systeminfo.h>
50 #include <sys/fpu/fpusystm.h>
51 #include <sys/vm.h>
52 #include <sys/fs/dv_node.h>
53 #include <sys/fs/snode.h>
54 #include <sys/ddi_isa.h>
55 
56 dev_info_t *get_intr_parent(dev_info_t *, dev_info_t *,
57     ddi_intr_handle_impl_t *);
58 #pragma weak get_intr_parent
59 
60 int process_intr_ops(dev_info_t *, dev_info_t *, ddi_intr_op_t,
61     ddi_intr_handle_impl_t *, void *);
62 #pragma weak process_intr_ops
63 
64 void cells_1275_copy(prop_1275_cell_t *, prop_1275_cell_t *, int32_t);
65     prop_1275_cell_t *cells_1275_cmp(prop_1275_cell_t *, prop_1275_cell_t *,
66     int32_t len);
67 #pragma weak cells_1275_copy
68 
69 /*
70  * Wrapper for ddi_prop_lookup_int_array().
71  * This is handy because it returns the prop length in
72  * bytes which is what most of the callers require.
73  */
74 
75 static int
76 get_prop_int_array(dev_info_t *di, char *pname, int **pval, uint_t *plen)
77 {
78 	int ret;
79 
80 	if ((ret = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, di,
81 	    DDI_PROP_DONTPASS, pname, pval, plen)) == DDI_PROP_SUCCESS) {
82 		*plen = (*plen) * (uint_t)sizeof (int);
83 	}
84 	return (ret);
85 }
86 
87 /*
88  * SECTION: DDI Node Configuration
89  */
90 
91 /*
92  * init_regspec_64:
93  *
94  * If the parent #size-cells is 2, convert the upa-style or
95  * safari-style reg property from 2-size cells to 1 size cell
96  * format, ignoring the size_hi, which must be zero for devices.
97  * (It won't be zero in the memory list properties in the memory
98  * nodes, but that doesn't matter here.)
99  */
100 struct ddi_parent_private_data *
101 init_regspec_64(dev_info_t *dip)
102 {
103 	struct ddi_parent_private_data *pd;
104 	dev_info_t *parent;
105 	int size_cells;
106 
107 	/*
108 	 * If there are no "reg"s in the child node, return.
109 	 */
110 	pd = ddi_get_parent_data(dip);
111 	if ((pd == NULL) || (pd->par_nreg == 0)) {
112 		return (pd);
113 	}
114 	parent = ddi_get_parent(dip);
115 
116 	size_cells = ddi_prop_get_int(DDI_DEV_T_ANY, parent,
117 	    DDI_PROP_DONTPASS, "#size-cells", 1);
118 
119 	if (size_cells != 1)  {
120 
121 		int n, j;
122 		struct regspec *irp;
123 		struct reg_64 {
124 			uint_t addr_hi, addr_lo, size_hi, size_lo;
125 		};
126 		struct reg_64 *r64_rp;
127 		struct regspec *rp;
128 		uint_t len = 0;
129 		int *reg_prop;
130 
131 		ASSERT(size_cells == 2);
132 
133 		/*
134 		 * We already looked the property up once before if
135 		 * pd is non-NULL.
136 		 */
137 		(void) ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip,
138 		    DDI_PROP_DONTPASS, OBP_REG, &reg_prop, &len);
139 		ASSERT(len != 0);
140 
141 		n = sizeof (struct reg_64) / sizeof (int);
142 		n = len / n;
143 
144 		/*
145 		 * We're allocating a buffer the size of the PROM's property,
146 		 * but we're only using a smaller portion when we assign it
147 		 * to a regspec.  We do this so that in the
148 		 * impl_ddi_sunbus_removechild function, we will
149 		 * always free the right amount of memory.
150 		 */
151 		irp = rp = (struct regspec *)reg_prop;
152 		r64_rp = (struct reg_64 *)pd->par_reg;
153 
154 		for (j = 0; j < n; ++j, ++rp, ++r64_rp) {
155 			ASSERT(r64_rp->size_hi == 0);
156 			rp->regspec_bustype = r64_rp->addr_hi;
157 			rp->regspec_addr = r64_rp->addr_lo;
158 			rp->regspec_size = r64_rp->size_lo;
159 		}
160 
161 		ddi_prop_free((void *)pd->par_reg);
162 		pd->par_nreg = n;
163 		pd->par_reg = irp;
164 	}
165 	return (pd);
166 }
167 
168 /*
169  * Create a ddi_parent_private_data structure from the ddi properties of
170  * the dev_info node.
171  *
172  * The "reg" is required if the driver wishes to create mappings on behalf
173  * of the device. The "reg" property is assumed to be a list of at least
174  * one triplet
175  *
176  *	<bustype, address, size>*1
177  *
178  * The "interrupt" property is no longer part of parent private data on
179  * sun4u. The interrupt parent is may not be the device tree parent.
180  *
181  * The "ranges" property describes the mapping of child addresses to parent
182  * addresses.
183  *
184  * N.B. struct rangespec is defined for the following default values:
185  *			parent  child
186  *	#address-cells	2	2
187  *	#size-cells	1	1
188  * This function doesn't deal with non-default cells and will not create
189  * ranges in such cases.
190  */
191 void
192 make_ddi_ppd(dev_info_t *child, struct ddi_parent_private_data **ppd)
193 {
194 	struct ddi_parent_private_data *pdptr;
195 	int *reg_prop, *rng_prop;
196 	uint_t reg_len = 0, rng_len = 0;
197 	dev_info_t *parent;
198 	int parent_addr_cells, parent_size_cells;
199 	int child_addr_cells, child_size_cells;
200 
201 	*ppd = pdptr = kmem_zalloc(sizeof (*pdptr), KM_SLEEP);
202 
203 	/*
204 	 * root node has no parent private data, so *ppd should
205 	 * be initialized for naming to work properly.
206 	 */
207 	if ((parent = ddi_get_parent(child)) == NULL)
208 		return;
209 
210 	/*
211 	 * Set reg field of parent data from "reg" property
212 	 */
213 	if ((get_prop_int_array(child, OBP_REG, &reg_prop, &reg_len)
214 	    == DDI_PROP_SUCCESS) && (reg_len != 0)) {
215 		pdptr->par_nreg = (int)(reg_len / sizeof (struct regspec));
216 		pdptr->par_reg = (struct regspec *)reg_prop;
217 	}
218 
219 	/*
220 	 * "ranges" property ...
221 	 *
222 	 * This function does not handle cases where #address-cells != 2
223 	 * and * min(parent, child) #size-cells != 1 (see bugid 4211124).
224 	 *
225 	 * Nexus drivers with such exceptions (e.g. pci ranges)
226 	 * should either create a separate function for handling
227 	 * ranges or not use parent private data to store ranges.
228 	 */
229 
230 	/* root node has no ranges */
231 	if ((parent = ddi_get_parent(child)) == NULL)
232 		return;
233 
234 	child_addr_cells = ddi_prop_get_int(DDI_DEV_T_ANY, child,
235 	    DDI_PROP_DONTPASS, "#address-cells", 2);
236 	child_size_cells = ddi_prop_get_int(DDI_DEV_T_ANY, child,
237 	    DDI_PROP_DONTPASS, "#size-cells", 1);
238 	parent_addr_cells = ddi_prop_get_int(DDI_DEV_T_ANY, parent,
239 	    DDI_PROP_DONTPASS, "#address-cells", 2);
240 	parent_size_cells = ddi_prop_get_int(DDI_DEV_T_ANY, parent,
241 	    DDI_PROP_DONTPASS, "#size-cells", 1);
242 	if (child_addr_cells != 2 || parent_addr_cells != 2 ||
243 	    (child_size_cells != 1 && parent_size_cells != 1)) {
244 		NDI_CONFIG_DEBUG((CE_NOTE, "!ranges not made in parent data; "
245 		    "#address-cells or #size-cells have non-default value"));
246 		return;
247 	}
248 
249 	if (get_prop_int_array(child, OBP_RANGES, &rng_prop, &rng_len)
250 	    == DDI_PROP_SUCCESS) {
251 		pdptr->par_nrng = rng_len / (int)(sizeof (struct rangespec));
252 		pdptr->par_rng = (struct rangespec *)rng_prop;
253 	}
254 }
255 
256 /*
257  * Free ddi_parent_private_data structure
258  */
259 void
260 impl_free_ddi_ppd(dev_info_t *dip)
261 {
262 	struct ddi_parent_private_data *pdptr = ddi_get_parent_data(dip);
263 
264 	if (pdptr == NULL)
265 		return;
266 
267 	if (pdptr->par_nrng != 0)
268 		ddi_prop_free((void *)pdptr->par_rng);
269 
270 	if (pdptr->par_nreg != 0)
271 		ddi_prop_free((void *)pdptr->par_reg);
272 
273 	kmem_free(pdptr, sizeof (*pdptr));
274 	ddi_set_parent_data(dip, NULL);
275 }
276 
277 /*
278  * Name a child of sun busses based on the reg spec.
279  * Handles the following properties:
280  *
281  *	Property	value
282  *	Name		type
283  *
284  *	reg		register spec
285  *	interrupts	new (bus-oriented) interrupt spec
286  *	ranges		range spec
287  *
288  * This may be called multiple times, independent of
289  * initchild calls.
290  */
291 static int
292 impl_sunbus_name_child(dev_info_t *child, char *name, int namelen)
293 {
294 	struct ddi_parent_private_data *pdptr;
295 	struct regspec *rp;
296 
297 	/*
298 	 * Fill in parent-private data and this function returns to us
299 	 * an indication if it used "registers" to fill in the data.
300 	 */
301 	if (ddi_get_parent_data(child) == NULL) {
302 		make_ddi_ppd(child, &pdptr);
303 		ddi_set_parent_data(child, pdptr);
304 	}
305 
306 	/*
307 	 * No reg property, return null string as address
308 	 * (e.g. root node)
309 	 */
310 	name[0] = '\0';
311 	if (sparc_pd_getnreg(child) == 0) {
312 		return (DDI_SUCCESS);
313 	}
314 
315 	rp = sparc_pd_getreg(child, 0);
316 	(void) snprintf(name, namelen, "%x,%x",
317 	    rp->regspec_bustype, rp->regspec_addr);
318 	return (DDI_SUCCESS);
319 }
320 
321 
322 /*
323  * Called from the bus_ctl op of some drivers.
324  * to implement the DDI_CTLOPS_INITCHILD operation.
325  *
326  * NEW drivers should NOT use this function, but should declare
327  * there own initchild/uninitchild handlers. (This function assumes
328  * the layout of the parent private data and the format of "reg",
329  * "ranges", "interrupts" properties and that #address-cells and
330  * #size-cells of the parent bus are defined to be default values.)
331  */
332 int
333 impl_ddi_sunbus_initchild(dev_info_t *child)
334 {
335 	char name[MAXNAMELEN];
336 
337 	(void) impl_sunbus_name_child(child, name, MAXNAMELEN);
338 	ddi_set_name_addr(child, name);
339 
340 	/*
341 	 * Try to merge .conf node. If successful, return failure to
342 	 * remove this child.
343 	 */
344 	if ((ndi_dev_is_persistent_node(child) == 0) &&
345 	    (ndi_merge_node(child, impl_sunbus_name_child) == DDI_SUCCESS)) {
346 		impl_ddi_sunbus_removechild(child);
347 		return (DDI_FAILURE);
348 	}
349 	return (DDI_SUCCESS);
350 }
351 
352 /*
353  * A better name for this function would be impl_ddi_sunbus_uninitchild()
354  * It does not remove the child, it uninitializes it, reclaiming the
355  * resources taken by impl_ddi_sunbus_initchild.
356  */
357 void
358 impl_ddi_sunbus_removechild(dev_info_t *dip)
359 {
360 	impl_free_ddi_ppd(dip);
361 	ddi_set_name_addr(dip, NULL);
362 	/*
363 	 * Strip the node to properly convert it back to prototype form
364 	 */
365 	impl_rem_dev_props(dip);
366 }
367 
368 /*
369  * SECTION: DDI Interrupt
370  */
371 
372 void
373 cells_1275_copy(prop_1275_cell_t *from, prop_1275_cell_t *to, int32_t len)
374 {
375 	int i;
376 	for (i = 0; i < len; i++)
377 		*to = *from;
378 }
379 
380 prop_1275_cell_t *
381 cells_1275_cmp(prop_1275_cell_t *cell1, prop_1275_cell_t *cell2, int32_t len)
382 {
383 	prop_1275_cell_t *match_cell = 0;
384 	int32_t i;
385 
386 	for (i = 0; i < len; i++)
387 		if (cell1[i] != cell2[i]) {
388 			match_cell = &cell1[i];
389 			break;
390 		}
391 
392 	return (match_cell);
393 }
394 
395 /*
396  * get_intr_parent() is a generic routine that process a 1275 interrupt
397  * map (imap) property.  This function returns a dev_info_t structure
398  * which claims ownership of the interrupt domain.
399  * It also returns the new interrupt translation within this new domain.
400  * If an interrupt-parent or interrupt-map property are not found,
401  * then we fallback to using the device tree's parent.
402  *
403  * imap entry format:
404  * <reg>,<interrupt>,<phandle>,<translated interrupt>
405  * reg - The register specification in the interrupts domain
406  * interrupt - The interrupt specification
407  * phandle - PROM handle of the device that owns the xlated interrupt domain
408  * translated interrupt - interrupt specifier in the parents domain
409  * note: <reg>,<interrupt> - The reg and interrupt can be combined to create
410  *	a unique entry called a unit interrupt specifier.
411  *
412  * Here's the processing steps:
413  * step1 - If the interrupt-parent property exists, create the ispec and
414  *	return the dip of the interrupt parent.
415  * step2 - Extract the interrupt-map property and the interrupt-map-mask
416  *	If these don't exist, just return the device tree parent.
417  * step3 - build up the unit interrupt specifier to match against the
418  *	interrupt map property
419  * step4 - Scan the interrupt-map property until a match is found
420  * step4a - Extract the interrupt parent
421  * step4b - Compare the unit interrupt specifier
422  */
423 dev_info_t *
424 get_intr_parent(dev_info_t *pdip, dev_info_t *dip, ddi_intr_handle_impl_t *hdlp)
425 {
426 	prop_1275_cell_t *imap, *imap_mask, *scan, *reg_p, *match_req;
427 	int32_t imap_sz, imap_cells, imap_scan_cells, imap_mask_sz,
428 	    addr_cells, intr_cells, reg_len, i, j;
429 	int32_t match_found = 0;
430 	dev_info_t *intr_parent_dip = NULL;
431 	uint32_t *intr = &hdlp->ih_vector;
432 	uint32_t nodeid;
433 #ifdef DEBUG
434 	static int debug = 0;
435 #endif
436 
437 	/*
438 	 * step1
439 	 * If we have an interrupt-parent property, this property represents
440 	 * the nodeid of our interrupt parent.
441 	 */
442 	if ((nodeid = ddi_getprop(DDI_DEV_T_ANY, dip, 0,
443 	    "interrupt-parent", -1)) != -1) {
444 		intr_parent_dip = e_ddi_nodeid_to_dip(nodeid);
445 		ASSERT(intr_parent_dip);
446 
447 		/*
448 		 * Attach the interrupt parent.
449 		 *
450 		 * N.B. e_ddi_nodeid_to_dip() isn't safe under DR.
451 		 *	Also, interrupt parent isn't held. This needs
452 		 *	to be revisited if DR-capable platforms implement
453 		 *	interrupt redirection.
454 		 */
455 		if (i_ddi_attach_node_hierarchy(intr_parent_dip)
456 		    != DDI_SUCCESS) {
457 			ndi_rele_devi(intr_parent_dip);
458 			return (NULL);
459 		}
460 
461 		return (intr_parent_dip);
462 	}
463 
464 	/*
465 	 * step2
466 	 * Get interrupt map structure from PROM property
467 	 */
468 	if (ddi_getlongprop(DDI_DEV_T_ANY, pdip, DDI_PROP_DONTPASS,
469 	    "interrupt-map", (caddr_t)&imap, &imap_sz)
470 	    != DDI_PROP_SUCCESS) {
471 		/*
472 		 * If we don't have an imap property, default to using the
473 		 * device tree.
474 		 */
475 
476 		ndi_hold_devi(pdip);
477 		return (pdip);
478 	}
479 
480 	/* Get the interrupt mask property */
481 	if (ddi_getlongprop(DDI_DEV_T_ANY, pdip, DDI_PROP_DONTPASS,
482 	    "interrupt-map-mask", (caddr_t)&imap_mask, &imap_mask_sz)
483 	    != DDI_PROP_SUCCESS) {
484 		/*
485 		 * If we don't find this property, we have to fail the request
486 		 * because the 1275 imap property wasn't defined correctly.
487 		 */
488 		ASSERT(intr_parent_dip == NULL);
489 		goto exit2;
490 	}
491 
492 	/* Get the address cell size */
493 	addr_cells = ddi_getprop(DDI_DEV_T_ANY, pdip, 0,
494 	    "#address-cells", 2);
495 
496 	/* Get the interrupts cell size */
497 	intr_cells = ddi_getprop(DDI_DEV_T_ANY, pdip, 0,
498 	    "#interrupt-cells", 1);
499 
500 	/*
501 	 * step3
502 	 * Now lets build up the unit interrupt specifier e.g. reg,intr
503 	 * and apply the imap mask.  match_req will hold this when we're
504 	 * through.
505 	 */
506 	if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "reg",
507 	    (caddr_t)&reg_p, &reg_len) != DDI_SUCCESS) {
508 		ASSERT(intr_parent_dip == NULL);
509 		goto exit3;
510 	}
511 
512 	match_req = kmem_alloc(CELLS_1275_TO_BYTES(addr_cells) +
513 	    CELLS_1275_TO_BYTES(intr_cells), KM_SLEEP);
514 
515 	for (i = 0; i < addr_cells; i++)
516 		match_req[i] = (reg_p[i] & imap_mask[i]);
517 
518 	for (j = 0; j < intr_cells; i++, j++)
519 		match_req[i] = (intr[j] & imap_mask[i]);
520 
521 	/* Calculate the imap size in cells */
522 	imap_cells = BYTES_TO_1275_CELLS(imap_sz);
523 
524 #ifdef DEBUG
525 	if (debug)
526 		prom_printf("reg cell size 0x%x, intr cell size 0x%x, "
527 		    "match_request 0x%p, imap 0x%p\n", addr_cells, intr_cells,
528 		    match_req, imap);
529 #endif
530 
531 	/*
532 	 * Scan the imap property looking for a match of the interrupt unit
533 	 * specifier.  This loop is rather complex since the data within the
534 	 * imap property may vary in size.
535 	 */
536 	for (scan = imap, imap_scan_cells = i = 0;
537 	    imap_scan_cells < imap_cells; scan += i, imap_scan_cells += i) {
538 		int new_intr_cells;
539 
540 		/* Set the index to the nodeid field */
541 		i = addr_cells + intr_cells;
542 
543 		/*
544 		 * step4a
545 		 * Translate the nodeid field to a dip
546 		 */
547 		ASSERT(intr_parent_dip == NULL);
548 		intr_parent_dip = e_ddi_nodeid_to_dip((uint_t)scan[i++]);
549 
550 		ASSERT(intr_parent_dip != 0);
551 #ifdef DEBUG
552 		if (debug)
553 			prom_printf("scan 0x%p\n", scan);
554 #endif
555 		/*
556 		 * The tmp_dip describes the new domain, get it's interrupt
557 		 * cell size
558 		 */
559 		new_intr_cells = ddi_getprop(DDI_DEV_T_ANY, intr_parent_dip, 0,
560 		    "#interrupts-cells", 1);
561 
562 		/*
563 		 * step4b
564 		 * See if we have a match on the interrupt unit specifier
565 		 */
566 		if (cells_1275_cmp(match_req, scan, addr_cells + intr_cells)
567 		    == 0) {
568 			uint32_t *intr;
569 
570 			match_found = 1;
571 
572 			/*
573 			 * If we have an imap parent whose not in our device
574 			 * tree path, we need to hold and install that driver.
575 			 */
576 			if (i_ddi_attach_node_hierarchy(intr_parent_dip)
577 			    != DDI_SUCCESS) {
578 				ndi_rele_devi(intr_parent_dip);
579 				intr_parent_dip = (dev_info_t *)NULL;
580 				goto exit4;
581 			}
582 
583 			/*
584 			 * We need to handcraft an ispec along with a bus
585 			 * interrupt value, so we can dup it into our
586 			 * standard ispec structure.
587 			 */
588 			/* Extract the translated interrupt information */
589 			intr = kmem_alloc(
590 			    CELLS_1275_TO_BYTES(new_intr_cells), KM_SLEEP);
591 
592 			for (j = 0; j < new_intr_cells; j++, i++)
593 				intr[j] = scan[i];
594 
595 			cells_1275_copy(intr, &hdlp->ih_vector, new_intr_cells);
596 
597 			kmem_free(intr, CELLS_1275_TO_BYTES(new_intr_cells));
598 
599 #ifdef DEBUG
600 			if (debug)
601 				prom_printf("dip 0x%p\n", intr_parent_dip);
602 #endif
603 			break;
604 		} else {
605 #ifdef DEBUG
606 			if (debug)
607 				prom_printf("dip 0x%p\n", intr_parent_dip);
608 #endif
609 			ndi_rele_devi(intr_parent_dip);
610 			intr_parent_dip = NULL;
611 			i += new_intr_cells;
612 		}
613 	}
614 
615 	/*
616 	 * If we haven't found our interrupt parent at this point, fallback
617 	 * to using the device tree.
618 	 */
619 	if (!match_found) {
620 		ndi_hold_devi(pdip);
621 		ASSERT(intr_parent_dip == NULL);
622 		intr_parent_dip = pdip;
623 	}
624 
625 	ASSERT(intr_parent_dip != NULL);
626 
627 exit4:
628 	kmem_free(reg_p, reg_len);
629 	kmem_free(match_req, CELLS_1275_TO_BYTES(addr_cells) +
630 	    CELLS_1275_TO_BYTES(intr_cells));
631 
632 exit3:
633 	kmem_free(imap_mask, imap_mask_sz);
634 
635 exit2:
636 	kmem_free(imap, imap_sz);
637 
638 	return (intr_parent_dip);
639 }
640 
641 /*
642  * process_intr_ops:
643  *
644  * Process the interrupt op via the interrupt parent.
645  */
646 int
647 process_intr_ops(dev_info_t *pdip, dev_info_t *rdip, ddi_intr_op_t op,
648     ddi_intr_handle_impl_t *hdlp, void *result)
649 {
650 	int		ret = DDI_FAILURE;
651 
652 	if (NEXUS_HAS_INTR_OP(pdip)) {
653 		ret = (*(DEVI(pdip)->devi_ops->devo_bus_ops->
654 		    bus_intr_op)) (pdip, rdip, op, hdlp, result);
655 	} else {
656 		cmn_err(CE_WARN, "Failed to process interrupt "
657 		    "for %s%d due to down-rev nexus driver %s%d",
658 		    ddi_get_name(rdip), ddi_get_instance(rdip),
659 		    ddi_get_name(pdip), ddi_get_instance(pdip));
660 	}
661 
662 	return (ret);
663 }
664 
665 /*ARGSUSED*/
666 uint_t
667 softlevel1(caddr_t arg)
668 {
669 	softint();
670 	return (1);
671 }
672 
673 /*
674  * indirection table, to save us some large switch statements
675  * NOTE: This must agree with "INTLEVEL_foo" constants in
676  *	<sys/avintr.h>
677  */
678 struct autovec *const vectorlist[] = { 0 };
679 
680 /*
681  * This value is exported here for the functions in avintr.c
682  */
683 const uint_t maxautovec = (sizeof (vectorlist) / sizeof (vectorlist[0]));
684 
685 /*
686  * Check for machine specific interrupt levels which cannot be reassigned by
687  * settrap(), sun4u version.
688  *
689  * sun4u does not support V8 SPARC "fast trap" handlers.
690  */
691 /*ARGSUSED*/
692 int
693 exclude_settrap(int lvl)
694 {
695 	return (1);
696 }
697 
698 /*
699  * Check for machine specific interrupt levels which cannot have interrupt
700  * handlers added. We allow levels 1 through 15; level 0 is nonsense.
701  */
702 /*ARGSUSED*/
703 int
704 exclude_level(int lvl)
705 {
706 	return ((lvl < 1) || (lvl > 15));
707 }
708 
709 /*
710  * Wrapper functions used by New DDI interrupt framework.
711  */
712 
713 /*
714  * i_ddi_intr_ops:
715  */
716 int
717 i_ddi_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t op,
718     ddi_intr_handle_impl_t *hdlp, void *result)
719 {
720 	dev_info_t	*pdip = ddi_get_parent(dip);
721 	int		ret = DDI_FAILURE;
722 
723 	/*
724 	 * The following check is required to address
725 	 * one of the test case of ADDI test suite.
726 	 */
727 	if (pdip == NULL)
728 		return (DDI_FAILURE);
729 
730 	if (hdlp->ih_type != DDI_INTR_TYPE_FIXED)
731 		return (process_intr_ops(pdip, rdip, op, hdlp, result));
732 
733 	if (hdlp->ih_vector == 0)
734 		hdlp->ih_vector = i_ddi_get_inum(rdip, hdlp->ih_inum);
735 
736 	if (hdlp->ih_pri == 0)
737 		hdlp->ih_pri = i_ddi_get_intr_pri(rdip, hdlp->ih_inum);
738 
739 	switch (op) {
740 	case DDI_INTROP_ADDISR:
741 	case DDI_INTROP_REMISR:
742 	case DDI_INTROP_ENABLE:
743 	case DDI_INTROP_DISABLE:
744 	case DDI_INTROP_BLOCKENABLE:
745 	case DDI_INTROP_BLOCKDISABLE:
746 		/*
747 		 * Try and determine our parent and possibly an interrupt
748 		 * translation. intr parent dip returned held
749 		 */
750 		if ((pdip = get_intr_parent(pdip, dip, hdlp)) == NULL)
751 			goto done;
752 	}
753 
754 	ret = process_intr_ops(pdip, rdip, op, hdlp, result);
755 
756 done:
757 	switch (op) {
758 	case DDI_INTROP_ADDISR:
759 	case DDI_INTROP_REMISR:
760 	case DDI_INTROP_ENABLE:
761 	case DDI_INTROP_DISABLE:
762 	case DDI_INTROP_BLOCKENABLE:
763 	case DDI_INTROP_BLOCKDISABLE:
764 		/* Release hold acquired in get_intr_parent() */
765 		if (pdip)
766 			ndi_rele_devi(pdip);
767 	}
768 
769 	hdlp->ih_vector = 0;
770 
771 	return (ret);
772 }
773 
774 /*
775  * i_ddi_add_ivintr:
776  */
777 /*ARGSUSED*/
778 int
779 i_ddi_add_ivintr(ddi_intr_handle_impl_t *hdlp)
780 {
781 	/* Sanity check the entry we're about to add */
782 	if (GET_IVINTR(hdlp->ih_vector)) {
783 		cmn_err(CE_WARN, "mondo 0x%x in use", hdlp->ih_vector);
784 		return (DDI_FAILURE);
785 	}
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, NULL) == 0);
796 
797 	return (DDI_SUCCESS);
798 }
799 
800 /*
801  * i_ddi_rem_ivintr:
802  */
803 /*ARGSUSED*/
804 void
805 i_ddi_rem_ivintr(ddi_intr_handle_impl_t *hdlp)
806 {
807 	rem_ivintr(hdlp->ih_vector, NULL);
808 }
809 
810 /*
811  * i_ddi_get_inum - Get the interrupt number property from the
812  * specified device. Note that this function is called only for
813  * the FIXED interrupt type.
814  */
815 uint32_t
816 i_ddi_get_inum(dev_info_t *dip, uint_t inumber)
817 {
818 	int32_t			intrlen, intr_cells, max_intrs;
819 	prop_1275_cell_t	*ip, intr_sz;
820 	uint32_t		intr = 0;
821 
822 	if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS |
823 	    DDI_PROP_CANSLEEP,
824 	    "interrupts", (caddr_t)&ip, &intrlen) == DDI_SUCCESS) {
825 
826 		intr_cells = ddi_getprop(DDI_DEV_T_ANY, dip, 0,
827 		    "#interrupt-cells", 1);
828 
829 		/* adjust for number of bytes */
830 		intr_sz = CELLS_1275_TO_BYTES(intr_cells);
831 
832 		/* Calculate the number of interrupts */
833 		max_intrs = intrlen / intr_sz;
834 
835 		if (inumber < max_intrs) {
836 			prop_1275_cell_t *intrp = ip;
837 
838 			/* Index into interrupt property */
839 			intrp += (inumber * intr_cells);
840 
841 			cells_1275_copy(intrp, &intr, intr_cells);
842 		}
843 
844 		kmem_free(ip, intrlen);
845 	}
846 
847 	return (intr);
848 }
849 
850 /*
851  * i_ddi_get_intr_pri - Get the interrupt-priorities property from
852  * the specified device. Note that this function is called only for
853  * the FIXED interrupt type.
854  */
855 uint32_t
856 i_ddi_get_intr_pri(dev_info_t *dip, uint_t inumber)
857 {
858 	uint32_t	*intr_prio_p;
859 	uint32_t	pri = 0;
860 	int32_t		i;
861 
862 	/*
863 	 * Use the "interrupt-priorities" property to determine the
864 	 * the pil/ipl for the interrupt handler.
865 	 */
866 	if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
867 	    "interrupt-priorities", (caddr_t)&intr_prio_p,
868 	    &i) == DDI_SUCCESS) {
869 		if (inumber < (i / sizeof (int32_t)))
870 			pri = intr_prio_p[inumber];
871 		kmem_free(intr_prio_p, i);
872 	}
873 
874 	return (pri);
875 }
876 
877 int
878 i_ddi_get_nintrs(dev_info_t *dip)
879 {
880 	int32_t intrlen;
881 	prop_1275_cell_t intr_sz;
882 	prop_1275_cell_t *ip;
883 	int32_t ret = 0;
884 
885 	if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS |
886 	    DDI_PROP_CANSLEEP,
887 	    "interrupts", (caddr_t)&ip, &intrlen) == DDI_SUCCESS) {
888 
889 		intr_sz = ddi_getprop(DDI_DEV_T_ANY, dip, 0,
890 		    "#interrupt-cells", 1);
891 		/* adjust for number of bytes */
892 		intr_sz = CELLS_1275_TO_BYTES(intr_sz);
893 
894 		ret = intrlen / intr_sz;
895 
896 		kmem_free(ip, intrlen);
897 	}
898 
899 	return (ret);
900 }
901 
902 /*
903  * i_ddi_add_softint - allocate and add a soft interrupt to the system
904  */
905 int
906 i_ddi_add_softint(ddi_softint_hdl_impl_t *hdlp)
907 {
908 	uint_t		rval;
909 
910 	if ((rval = add_softintr(hdlp->ih_pri, hdlp->ih_cb_func,
911 	    hdlp->ih_cb_arg1)) == 0) {
912 
913 		return (DDI_FAILURE);
914 	}
915 
916 	/* use uintptr_t to suppress the gcc warning */
917 	hdlp->ih_private = (void *)(uintptr_t)rval;
918 
919 	return (DDI_SUCCESS);
920 }
921 
922 void
923 i_ddi_remove_softint(ddi_softint_hdl_impl_t *hdlp)
924 {
925 	uint_t		intr_id;
926 
927 	/* disable */
928 	ASSERT(hdlp->ih_private != NULL);
929 
930 	/* use uintptr_t to suppress the gcc warning */
931 	intr_id = (uint_t)(uintptr_t)hdlp->ih_private;
932 
933 	rem_softintr(intr_id);
934 	hdlp->ih_private = NULL;
935 }
936 
937 int
938 i_ddi_trigger_softint(ddi_softint_hdl_impl_t *hdlp, void *arg2)
939 {
940 	uint_t		intr_id;
941 	int		ret;
942 
943 	ASSERT(hdlp != NULL);
944 	ASSERT(hdlp->ih_private != NULL);
945 
946 	/* use uintptr_t to suppress the gcc warning */
947 	intr_id = (uint_t)(uintptr_t)hdlp->ih_private;
948 
949 	/* update the vector table for the 2nd arg */
950 	ret = update_softint_arg2(intr_id, arg2);
951 	if (ret == DDI_SUCCESS)
952 		setsoftint(intr_id);
953 
954 	return (ret);
955 }
956 
957 /* ARGSUSED */
958 int
959 i_ddi_set_softint_pri(ddi_softint_hdl_impl_t *hdlp, uint_t old_pri)
960 {
961 	uint_t		intr_id;
962 	int		ret;
963 
964 	ASSERT(hdlp != NULL);
965 	ASSERT(hdlp->ih_private != NULL);
966 
967 	/* use uintptr_t to suppress the gcc warning */
968 	intr_id = (uint_t)(uintptr_t)hdlp->ih_private;
969 
970 	/* update the vector table for the new priority */
971 	ret = update_softint_pri(intr_id, hdlp->ih_pri);
972 
973 	return (ret);
974 }
975 
976 /*ARGSUSED*/
977 void
978 i_ddi_alloc_intr_phdl(ddi_intr_handle_impl_t *hdlp)
979 {
980 }
981 
982 /*ARGSUSED*/
983 void
984 i_ddi_free_intr_phdl(ddi_intr_handle_impl_t *hdlp)
985 {
986 }
987 
988 /*
989  * SECTION: DDI Memory/DMA
990  */
991 
992 static vmem_t *little_endian_arena;
993 static vmem_t *big_endian_arena;
994 
995 static void *
996 segkmem_alloc_le(vmem_t *vmp, size_t size, int flag)
997 {
998 	return (segkmem_xalloc(vmp, NULL, size, flag, HAT_STRUCTURE_LE,
999 	    segkmem_page_create, NULL));
1000 }
1001 
1002 static void *
1003 segkmem_alloc_be(vmem_t *vmp, size_t size, int flag)
1004 {
1005 	return (segkmem_xalloc(vmp, NULL, size, flag, HAT_STRUCTURE_BE,
1006 	    segkmem_page_create, NULL));
1007 }
1008 
1009 void
1010 ka_init(void)
1011 {
1012 	little_endian_arena = vmem_create("little_endian", NULL, 0, 1,
1013 	    segkmem_alloc_le, segkmem_free, heap_arena, 0, VM_SLEEP);
1014 	big_endian_arena = vmem_create("big_endian", NULL, 0, 1,
1015 	    segkmem_alloc_be, segkmem_free, heap_arena, 0, VM_SLEEP);
1016 }
1017 
1018 /*
1019  * Allocate from the system, aligned on a specific boundary.
1020  * The alignment, if non-zero, must be a power of 2.
1021  */
1022 static void *
1023 kalloca(size_t size, size_t align, int cansleep, uint_t endian_flags)
1024 {
1025 	size_t *addr, *raddr, rsize;
1026 	size_t hdrsize = 4 * sizeof (size_t);	/* must be power of 2 */
1027 
1028 	align = MAX(align, hdrsize);
1029 	ASSERT((align & (align - 1)) == 0);
1030 
1031 	/*
1032 	 * We need to allocate
1033 	 *    rsize = size + hdrsize + align - MIN(hdrsize, buffer_alignment)
1034 	 * bytes to be sure we have enough freedom to satisfy the request.
1035 	 * Since the buffer alignment depends on the request size, this is
1036 	 * not straightforward to use directly.
1037 	 *
1038 	 * kmem guarantees that any allocation of a 64-byte multiple will be
1039 	 * 64-byte aligned.  Since rounding up the request could add more
1040 	 * than we save, we compute the size with and without alignment, and
1041 	 * use the smaller of the two.
1042 	 */
1043 	rsize = size + hdrsize + align;
1044 
1045 	if (endian_flags == DDI_STRUCTURE_LE_ACC) {
1046 		raddr = vmem_alloc(little_endian_arena, rsize,
1047 		    cansleep ? VM_SLEEP : VM_NOSLEEP);
1048 	} else {
1049 		raddr = vmem_alloc(big_endian_arena, rsize,
1050 		    cansleep ? VM_SLEEP : VM_NOSLEEP);
1051 	}
1052 
1053 	if (raddr == NULL)
1054 		return (NULL);
1055 
1056 	addr = (size_t *)P2ROUNDUP((uintptr_t)raddr + hdrsize, align);
1057 	ASSERT((uintptr_t)addr + size - (uintptr_t)raddr <= rsize);
1058 
1059 	addr[-3] = (size_t)endian_flags;
1060 	addr[-2] = (size_t)raddr;
1061 	addr[-1] = rsize;
1062 
1063 	return (addr);
1064 }
1065 
1066 static void
1067 kfreea(void *addr)
1068 {
1069 	size_t *saddr = addr;
1070 
1071 	if (saddr[-3] == DDI_STRUCTURE_LE_ACC)
1072 		vmem_free(little_endian_arena, (void *)saddr[-2], saddr[-1]);
1073 	else
1074 		vmem_free(big_endian_arena, (void *)saddr[-2], saddr[-1]);
1075 }
1076 
1077 int
1078 i_ddi_mem_alloc(dev_info_t *dip, ddi_dma_attr_t *attr,
1079     size_t length, int cansleep, int streaming,
1080     ddi_device_acc_attr_t *accattrp,
1081     caddr_t *kaddrp, size_t *real_length, ddi_acc_hdl_t *handlep)
1082 {
1083 	caddr_t a;
1084 	int iomin, align;
1085 	uint_t endian_flags = DDI_NEVERSWAP_ACC;
1086 
1087 #if defined(lint)
1088 	*handlep = *handlep;
1089 #endif
1090 
1091 	/*
1092 	 * Check legality of arguments
1093 	 */
1094 	if (length == 0 || kaddrp == NULL || attr == NULL) {
1095 		return (DDI_FAILURE);
1096 	}
1097 	if (attr->dma_attr_minxfer == 0 || attr->dma_attr_align == 0 ||
1098 	    (attr->dma_attr_align & (attr->dma_attr_align - 1)) ||
1099 	    (attr->dma_attr_minxfer & (attr->dma_attr_minxfer - 1))) {
1100 		return (DDI_FAILURE);
1101 	}
1102 
1103 	/*
1104 	 * Drivers for 64-bit capable SBus devices will encode
1105 	 * the burtsizes for 64-bit xfers in the upper 16-bits.
1106 	 * For DMA alignment, we use the most restrictive
1107 	 * alignment of 32-bit and 64-bit xfers.
1108 	 */
1109 	iomin = (attr->dma_attr_burstsizes & 0xffff) |
1110 	    ((attr->dma_attr_burstsizes >> 16) & 0xffff);
1111 	/*
1112 	 * If a driver set burtsizes to 0, we give him byte alignment.
1113 	 * Otherwise align at the burtsizes boundary.
1114 	 */
1115 	if (iomin == 0)
1116 		iomin = 1;
1117 	else
1118 		iomin = 1 << (ddi_fls(iomin) - 1);
1119 	iomin = maxbit(iomin, attr->dma_attr_minxfer);
1120 	iomin = maxbit(iomin, attr->dma_attr_align);
1121 	iomin = ddi_iomin(dip, iomin, streaming);
1122 	if (iomin == 0)
1123 		return (DDI_FAILURE);
1124 
1125 	ASSERT((iomin & (iomin - 1)) == 0);
1126 	ASSERT(iomin >= attr->dma_attr_minxfer);
1127 	ASSERT(iomin >= attr->dma_attr_align);
1128 
1129 	length = P2ROUNDUP(length, iomin);
1130 	align = iomin;
1131 
1132 	if (accattrp != NULL)
1133 		endian_flags = accattrp->devacc_attr_endian_flags;
1134 
1135 	a = kalloca(length, align, cansleep, endian_flags);
1136 	if ((*kaddrp = a) == 0) {
1137 		return (DDI_FAILURE);
1138 	} else {
1139 		if (real_length) {
1140 			*real_length = length;
1141 		}
1142 		if (handlep) {
1143 			/*
1144 			 * assign handle information
1145 			 */
1146 			impl_acc_hdl_init(handlep);
1147 		}
1148 		return (DDI_SUCCESS);
1149 	}
1150 }
1151 
1152 /*
1153  * covert old DMA limits structure to DMA attribute structure
1154  * and continue
1155  */
1156 int
1157 i_ddi_mem_alloc_lim(dev_info_t *dip, ddi_dma_lim_t *limits,
1158     size_t length, int cansleep, int streaming,
1159     ddi_device_acc_attr_t *accattrp, caddr_t *kaddrp,
1160     uint_t *real_length, ddi_acc_hdl_t *ap)
1161 {
1162 	ddi_dma_attr_t dma_attr, *attrp;
1163 	size_t rlen;
1164 	int ret;
1165 
1166 	ASSERT(limits);
1167 	attrp = &dma_attr;
1168 	attrp->dma_attr_version = DMA_ATTR_V0;
1169 	attrp->dma_attr_addr_lo = (uint64_t)limits->dlim_addr_lo;
1170 	attrp->dma_attr_addr_hi = (uint64_t)limits->dlim_addr_hi;
1171 	attrp->dma_attr_count_max = (uint64_t)-1;
1172 	attrp->dma_attr_align = 1;
1173 	attrp->dma_attr_burstsizes = (uint_t)limits->dlim_burstsizes;
1174 	attrp->dma_attr_minxfer = (uint32_t)limits->dlim_minxfer;
1175 	attrp->dma_attr_maxxfer = (uint64_t)-1;
1176 	attrp->dma_attr_seg = (uint64_t)limits->dlim_cntr_max;
1177 	attrp->dma_attr_sgllen = 1;
1178 	attrp->dma_attr_granular = 1;
1179 	attrp->dma_attr_flags = 0;
1180 
1181 	ret = i_ddi_mem_alloc(dip, attrp, length, cansleep, streaming,
1182 	    accattrp, kaddrp, &rlen, ap);
1183 	if (ret == DDI_SUCCESS) {
1184 		if (real_length)
1185 			*real_length = (uint_t)rlen;
1186 	}
1187 	return (ret);
1188 }
1189 
1190 /* ARGSUSED */
1191 void
1192 i_ddi_mem_free(caddr_t kaddr, int stream)
1193 {
1194 	kfreea(kaddr);
1195 }
1196 
1197 /*
1198  * SECTION: DDI Data Access
1199  */
1200 
1201 static uintptr_t impl_acc_hdl_id = 0;
1202 
1203 /*
1204  * access handle allocator
1205  */
1206 ddi_acc_hdl_t *
1207 impl_acc_hdl_get(ddi_acc_handle_t hdl)
1208 {
1209 	/*
1210 	 * Extract the access handle address from the DDI implemented
1211 	 * access handle
1212 	 */
1213 	return (&((ddi_acc_impl_t *)hdl)->ahi_common);
1214 }
1215 
1216 ddi_acc_handle_t
1217 impl_acc_hdl_alloc(int (*waitfp)(caddr_t), caddr_t arg)
1218 {
1219 	ddi_acc_impl_t *hp;
1220 	on_trap_data_t *otp;
1221 	int sleepflag;
1222 
1223 	sleepflag = ((waitfp == (int (*)())KM_SLEEP) ? KM_SLEEP : KM_NOSLEEP);
1224 
1225 	/*
1226 	 * Allocate and initialize the data access handle and error status.
1227 	 */
1228 	if ((hp = kmem_zalloc(sizeof (ddi_acc_impl_t), sleepflag)) == NULL)
1229 		goto fail;
1230 	if ((hp->ahi_err = (ndi_err_t *)kmem_zalloc(
1231 	    sizeof (ndi_err_t), sleepflag)) == NULL) {
1232 		kmem_free(hp, sizeof (ddi_acc_impl_t));
1233 		goto fail;
1234 	}
1235 	if ((otp = (on_trap_data_t *)kmem_zalloc(
1236 	    sizeof (on_trap_data_t), sleepflag)) == NULL) {
1237 		kmem_free(hp->ahi_err, sizeof (ndi_err_t));
1238 		kmem_free(hp, sizeof (ddi_acc_impl_t));
1239 		goto fail;
1240 	}
1241 	hp->ahi_err->err_ontrap = otp;
1242 	hp->ahi_common.ah_platform_private = (void *)hp;
1243 
1244 	return ((ddi_acc_handle_t)hp);
1245 fail:
1246 	if ((waitfp != (int (*)())KM_SLEEP) &&
1247 	    (waitfp != (int (*)())KM_NOSLEEP))
1248 		ddi_set_callback(waitfp, arg, &impl_acc_hdl_id);
1249 	return (NULL);
1250 }
1251 
1252 void
1253 impl_acc_hdl_free(ddi_acc_handle_t handle)
1254 {
1255 	ddi_acc_impl_t *hp;
1256 
1257 	/*
1258 	 * The supplied (ddi_acc_handle_t) is actually a (ddi_acc_impl_t *),
1259 	 * because that's what we allocated in impl_acc_hdl_alloc() above.
1260 	 */
1261 	hp = (ddi_acc_impl_t *)handle;
1262 	if (hp) {
1263 		kmem_free(hp->ahi_err->err_ontrap, sizeof (on_trap_data_t));
1264 		kmem_free(hp->ahi_err, sizeof (ndi_err_t));
1265 		kmem_free(hp, sizeof (ddi_acc_impl_t));
1266 		if (impl_acc_hdl_id)
1267 			ddi_run_callback(&impl_acc_hdl_id);
1268 	}
1269 }
1270 
1271 #define	PCI_GET_MP_PFN(mp, page_no)	((mp)->dmai_ndvmapages == 1 ? \
1272 	(pfn_t)(mp)->dmai_iopte:(((pfn_t *)(mp)->dmai_iopte)[page_no]))
1273 
1274 /*
1275  * Function called after a dma fault occurred to find out whether the
1276  * fault address is associated with a driver that is able to handle faults
1277  * and recover from faults.
1278  */
1279 /* ARGSUSED */
1280 int
1281 impl_dma_check(dev_info_t *dip, const void *handle, const void *addr,
1282     const void *not_used)
1283 {
1284 	ddi_dma_impl_t *mp = (ddi_dma_impl_t *)handle;
1285 	pfn_t fault_pfn = mmu_btop(*(uint64_t *)addr);
1286 	pfn_t comp_pfn;
1287 
1288 	/*
1289 	 * The driver has to set DDI_DMA_FLAGERR to recover from dma faults.
1290 	 */
1291 	int page;
1292 
1293 	ASSERT(mp);
1294 	for (page = 0; page < mp->dmai_ndvmapages; page++) {
1295 		comp_pfn = PCI_GET_MP_PFN(mp, page);
1296 		if (fault_pfn == comp_pfn)
1297 			return (DDI_FM_NONFATAL);
1298 	}
1299 	return (DDI_FM_UNKNOWN);
1300 }
1301 
1302 /*
1303  * Function used to check if a given access handle owns the failing address.
1304  * Called by ndi_fmc_error, when we detect a PIO error.
1305  */
1306 /* ARGSUSED */
1307 static int
1308 impl_acc_check(dev_info_t *dip, const void *handle, const void *addr,
1309     const void *not_used)
1310 {
1311 	pfn_t pfn, fault_pfn;
1312 	ddi_acc_hdl_t *hp;
1313 
1314 	hp = impl_acc_hdl_get((ddi_acc_handle_t)handle);
1315 
1316 	ASSERT(hp);
1317 
1318 	if (addr != NULL) {
1319 		pfn = hp->ah_pfn;
1320 		fault_pfn = mmu_btop(*(uint64_t *)addr);
1321 		if (fault_pfn >= pfn && fault_pfn < (pfn + hp->ah_pnum))
1322 			return (DDI_FM_NONFATAL);
1323 	}
1324 	return (DDI_FM_UNKNOWN);
1325 }
1326 
1327 void
1328 impl_acc_err_init(ddi_acc_hdl_t *handlep)
1329 {
1330 	int fmcap;
1331 	ndi_err_t *errp;
1332 	on_trap_data_t *otp;
1333 	ddi_acc_impl_t *hp = (ddi_acc_impl_t *)handlep;
1334 
1335 	fmcap = ddi_fm_capable(handlep->ah_dip);
1336 
1337 	if (handlep->ah_acc.devacc_attr_version < DDI_DEVICE_ATTR_V1 ||
1338 	    !DDI_FM_ACC_ERR_CAP(fmcap)) {
1339 		handlep->ah_acc.devacc_attr_access = DDI_DEFAULT_ACC;
1340 	} else if (DDI_FM_ACC_ERR_CAP(fmcap)) {
1341 		if (handlep->ah_acc.devacc_attr_access == DDI_DEFAULT_ACC) {
1342 			i_ddi_drv_ereport_post(handlep->ah_dip, DVR_EFMCAP,
1343 			    NULL, DDI_NOSLEEP);
1344 		} else {
1345 			errp = hp->ahi_err;
1346 			otp = (on_trap_data_t *)errp->err_ontrap;
1347 			otp->ot_handle = (void *)(hp);
1348 			otp->ot_prot = OT_DATA_ACCESS;
1349 			if (handlep->ah_acc.devacc_attr_access ==
1350 			    DDI_CAUTIOUS_ACC)
1351 				otp->ot_trampoline =
1352 				    (uintptr_t)&i_ddi_caut_trampoline;
1353 			else
1354 				otp->ot_trampoline =
1355 				    (uintptr_t)&i_ddi_prot_trampoline;
1356 			errp->err_status = DDI_FM_OK;
1357 			errp->err_expected = DDI_FM_ERR_UNEXPECTED;
1358 			errp->err_cf = impl_acc_check;
1359 		}
1360 	}
1361 }
1362 
1363 void
1364 impl_acc_hdl_init(ddi_acc_hdl_t *handlep)
1365 {
1366 	ddi_acc_impl_t *hp;
1367 
1368 	ASSERT(handlep);
1369 
1370 	hp = (ddi_acc_impl_t *)handlep;
1371 
1372 	/*
1373 	 * check for SW byte-swapping
1374 	 */
1375 	hp->ahi_get8 = i_ddi_get8;
1376 	hp->ahi_put8 = i_ddi_put8;
1377 	hp->ahi_rep_get8 = i_ddi_rep_get8;
1378 	hp->ahi_rep_put8 = i_ddi_rep_put8;
1379 	if (handlep->ah_acc.devacc_attr_endian_flags & DDI_STRUCTURE_LE_ACC) {
1380 		hp->ahi_get16 = i_ddi_swap_get16;
1381 		hp->ahi_get32 = i_ddi_swap_get32;
1382 		hp->ahi_get64 = i_ddi_swap_get64;
1383 		hp->ahi_put16 = i_ddi_swap_put16;
1384 		hp->ahi_put32 = i_ddi_swap_put32;
1385 		hp->ahi_put64 = i_ddi_swap_put64;
1386 		hp->ahi_rep_get16 = i_ddi_swap_rep_get16;
1387 		hp->ahi_rep_get32 = i_ddi_swap_rep_get32;
1388 		hp->ahi_rep_get64 = i_ddi_swap_rep_get64;
1389 		hp->ahi_rep_put16 = i_ddi_swap_rep_put16;
1390 		hp->ahi_rep_put32 = i_ddi_swap_rep_put32;
1391 		hp->ahi_rep_put64 = i_ddi_swap_rep_put64;
1392 	} else {
1393 		hp->ahi_get16 = i_ddi_get16;
1394 		hp->ahi_get32 = i_ddi_get32;
1395 		hp->ahi_get64 = i_ddi_get64;
1396 		hp->ahi_put16 = i_ddi_put16;
1397 		hp->ahi_put32 = i_ddi_put32;
1398 		hp->ahi_put64 = i_ddi_put64;
1399 		hp->ahi_rep_get16 = i_ddi_rep_get16;
1400 		hp->ahi_rep_get32 = i_ddi_rep_get32;
1401 		hp->ahi_rep_get64 = i_ddi_rep_get64;
1402 		hp->ahi_rep_put16 = i_ddi_rep_put16;
1403 		hp->ahi_rep_put32 = i_ddi_rep_put32;
1404 		hp->ahi_rep_put64 = i_ddi_rep_put64;
1405 	}
1406 
1407 	/* Legacy fault flags and support */
1408 	hp->ahi_fault_check = i_ddi_acc_fault_check;
1409 	hp->ahi_fault_notify = i_ddi_acc_fault_notify;
1410 	hp->ahi_fault = 0;
1411 	impl_acc_err_init(handlep);
1412 }
1413 
1414 void
1415 i_ddi_acc_set_fault(ddi_acc_handle_t handle)
1416 {
1417 	ddi_acc_impl_t *hp = (ddi_acc_impl_t *)handle;
1418 
1419 	if (!hp->ahi_fault) {
1420 		hp->ahi_fault = 1;
1421 			(*hp->ahi_fault_notify)(hp);
1422 	}
1423 }
1424 
1425 void
1426 i_ddi_acc_clr_fault(ddi_acc_handle_t handle)
1427 {
1428 	ddi_acc_impl_t *hp = (ddi_acc_impl_t *)handle;
1429 
1430 	if (hp->ahi_fault) {
1431 		hp->ahi_fault = 0;
1432 			(*hp->ahi_fault_notify)(hp);
1433 	}
1434 }
1435 
1436 /* ARGSUSED */
1437 void
1438 i_ddi_acc_fault_notify(ddi_acc_impl_t *hp)
1439 {
1440 	/* Default version, does nothing */
1441 }
1442 
1443 /*
1444  * SECTION: Misc functions
1445  */
1446 
1447 /*
1448  * instance wrappers
1449  */
1450 /*ARGSUSED*/
1451 uint_t
1452 impl_assign_instance(dev_info_t *dip)
1453 {
1454 	return ((uint_t)-1);
1455 }
1456 
1457 /*ARGSUSED*/
1458 int
1459 impl_keep_instance(dev_info_t *dip)
1460 {
1461 	return (DDI_FAILURE);
1462 }
1463 
1464 /*ARGSUSED*/
1465 int
1466 impl_free_instance(dev_info_t *dip)
1467 {
1468 	return (DDI_FAILURE);
1469 }
1470 
1471 /*ARGSUSED*/
1472 int
1473 impl_check_cpu(dev_info_t *devi)
1474 {
1475 	return (DDI_SUCCESS);
1476 }
1477 
1478 
1479 static const char *nocopydevs[] = {
1480 	"SUNW,ffb",
1481 	"SUNW,afb",
1482 	NULL
1483 };
1484 
1485 /*
1486  * Perform a copy from a memory mapped device (whose devinfo pointer is devi)
1487  * separately mapped at devaddr in the kernel to a kernel buffer at kaddr.
1488  */
1489 /*ARGSUSED*/
1490 int
1491 e_ddi_copyfromdev(dev_info_t *devi,
1492     off_t off, const void *devaddr, void *kaddr, size_t len)
1493 {
1494 	const char **argv;
1495 
1496 	for (argv = nocopydevs; *argv; argv++)
1497 		if (strcmp(ddi_binding_name(devi), *argv) == 0) {
1498 			bzero(kaddr, len);
1499 			return (0);
1500 		}
1501 
1502 	bcopy(devaddr, kaddr, len);
1503 	return (0);
1504 }
1505 
1506 /*
1507  * Perform a copy to a memory mapped device (whose devinfo pointer is devi)
1508  * separately mapped at devaddr in the kernel from a kernel buffer at kaddr.
1509  */
1510 /*ARGSUSED*/
1511 int
1512 e_ddi_copytodev(dev_info_t *devi,
1513     off_t off, const void *kaddr, void *devaddr, size_t len)
1514 {
1515 	const char **argv;
1516 
1517 	for (argv = nocopydevs; *argv; argv++)
1518 		if (strcmp(ddi_binding_name(devi), *argv) == 0)
1519 			return (1);
1520 
1521 	bcopy(kaddr, devaddr, len);
1522 	return (0);
1523 }
1524 
1525 /*
1526  * Boot Configuration
1527  */
1528 idprom_t idprom;
1529 
1530 /*
1531  * Configure the hardware on the system.
1532  * Called before the rootfs is mounted
1533  */
1534 void
1535 configure(void)
1536 {
1537 	extern void i_ddi_init_root();
1538 
1539 	/* We better have released boot by this time! */
1540 	ASSERT(!bootops);
1541 
1542 	/*
1543 	 * Determine whether or not to use the fpu, V9 SPARC cpus
1544 	 * always have one. Could check for existence of a fp queue,
1545 	 * Ultra I, II and IIa do not have a fp queue.
1546 	 */
1547 	if (fpu_exists)
1548 		fpu_probe();
1549 	else
1550 		cmn_err(CE_CONT, "FPU not in use\n");
1551 
1552 #if 0 /* XXXQ - not necessary for sun4u */
1553 	/*
1554 	 * This following line fixes bugid 1041296; we need to do a
1555 	 * prom_nextnode(0) because this call ALSO patches the DMA+
1556 	 * bug in Campus-B and Phoenix. The prom uncaches the traptable
1557 	 * page as a side-effect of devr_next(0) (which prom_nextnode calls),
1558 	 * so this *must* be executed early on. (XXX This is untrue for sun4u)
1559 	 */
1560 	(void) prom_nextnode((pnode_t)0);
1561 #endif
1562 
1563 	/*
1564 	 * Initialize devices on the machine.
1565 	 * Uses configuration tree built by the PROMs to determine what
1566 	 * is present, and builds a tree of prototype dev_info nodes
1567 	 * corresponding to the hardware which identified itself.
1568 	 */
1569 	i_ddi_init_root();
1570 
1571 #ifdef	DDI_PROP_DEBUG
1572 	(void) ddi_prop_debug(1);	/* Enable property debugging */
1573 #endif	/* DDI_PROP_DEBUG */
1574 }
1575 
1576 /*
1577  * The "status" property indicates the operational status of a device.
1578  * If this property is present, the value is a string indicating the
1579  * status of the device as follows:
1580  *
1581  *	"okay"		operational.
1582  *	"disabled"	not operational, but might become operational.
1583  *	"fail"		not operational because a fault has been detected,
1584  *			and it is unlikely that the device will become
1585  *			operational without repair. no additional details
1586  *			are available.
1587  *	"fail-xxx"	not operational because a fault has been detected,
1588  *			and it is unlikely that the device will become
1589  *			operational without repair. "xxx" is additional
1590  *			human-readable information about the particular
1591  *			fault condition that was detected.
1592  *
1593  * The absence of this property means that the operational status is
1594  * unknown or okay.
1595  *
1596  * This routine checks the status property of the specified device node
1597  * and returns 0 if the operational status indicates failure, and 1 otherwise.
1598  *
1599  * The property may exist on plug-in cards the existed before IEEE 1275-1994.
1600  * And, in that case, the property may not even be a string. So we carefully
1601  * check for the value "fail", in the beginning of the string, noting
1602  * the property length.
1603  */
1604 int
1605 status_okay(int id, char *buf, int buflen)
1606 {
1607 	char status_buf[OBP_MAXPROPNAME];
1608 	char *bufp = buf;
1609 	int len = buflen;
1610 	int proplen;
1611 	static const char *status = "status";
1612 	static const char *fail = "fail";
1613 	size_t fail_len = strlen(fail);
1614 
1615 	/*
1616 	 * Get the proplen ... if it's smaller than "fail",
1617 	 * or doesn't exist ... then we don't care, since
1618 	 * the value can't begin with the char string "fail".
1619 	 *
1620 	 * NB: proplen, if it's a string, includes the NULL in the
1621 	 * the size of the property, and fail_len does not.
1622 	 */
1623 	proplen = prom_getproplen((pnode_t)id, (caddr_t)status);
1624 	if (proplen <= fail_len)	/* nonexistent or uninteresting len */
1625 		return (1);
1626 
1627 	/*
1628 	 * if a buffer was provided, use it
1629 	 */
1630 	if ((buf == (char *)NULL) || (buflen <= 0)) {
1631 		bufp = status_buf;
1632 		len = sizeof (status_buf);
1633 	}
1634 	*bufp = (char)0;
1635 
1636 	/*
1637 	 * Get the property into the buffer, to the extent of the buffer,
1638 	 * and in case the buffer is smaller than the property size,
1639 	 * NULL terminate the buffer. (This handles the case where
1640 	 * a buffer was passed in and the caller wants to print the
1641 	 * value, but the buffer was too small).
1642 	 */
1643 	(void) prom_bounded_getprop((pnode_t)id, (caddr_t)status,
1644 	    (caddr_t)bufp, len);
1645 	*(bufp + len - 1) = (char)0;
1646 
1647 	/*
1648 	 * If the value begins with the char string "fail",
1649 	 * then it means the node is failed. We don't care
1650 	 * about any other values. We assume the node is ok
1651 	 * although it might be 'disabled'.
1652 	 */
1653 	if (strncmp(bufp, fail, fail_len) == 0)
1654 		return (0);
1655 
1656 	return (1);
1657 }
1658 
1659 
1660 /*
1661  * We set the cpu type from the idprom, if we can.
1662  * Note that we just read out the contents of it, for the most part.
1663  */
1664 void
1665 setcputype(void)
1666 {
1667 	/*
1668 	 * We cache the idprom info early on so that we don't
1669 	 * rummage through the NVRAM unnecessarily later.
1670 	 */
1671 	(void) prom_getidprom((caddr_t)&idprom, sizeof (idprom));
1672 }
1673 
1674 /*
1675  *  Here is where we actually infer meanings to the members of idprom_t
1676  */
1677 void
1678 parse_idprom(void)
1679 {
1680 	if (idprom.id_format == IDFORM_1) {
1681 		uint_t i;
1682 
1683 		(void) localetheraddr((struct ether_addr *)idprom.id_ether,
1684 		    (struct ether_addr *)NULL);
1685 
1686 		i = idprom.id_machine << 24;
1687 		i = i + idprom.id_serial;
1688 		numtos((ulong_t)i, hw_serial);
1689 	} else
1690 		prom_printf("Invalid format code in IDprom.\n");
1691 }
1692 
1693 /*
1694  * Allow for implementation specific correction of PROM property values.
1695  */
1696 /*ARGSUSED*/
1697 void
1698 impl_fix_props(dev_info_t *dip, dev_info_t *ch_dip, char *name, int len,
1699     caddr_t buffer)
1700 {
1701 	/*
1702 	 * There are no adjustments needed in this implementation.
1703 	 */
1704 }
1705 
1706 /*
1707  * The following functions ready a cautious request to go up to the nexus
1708  * driver.  It is up to the nexus driver to decide how to process the request.
1709  * It may choose to call i_ddi_do_caut_get/put in this file, or do it
1710  * differently.
1711  */
1712 
1713 static void
1714 i_ddi_caut_getput_ctlops(
1715     ddi_acc_impl_t *hp, uint64_t host_addr, uint64_t dev_addr, size_t size,
1716     size_t repcount, uint_t flags, ddi_ctl_enum_t cmd)
1717 {
1718 	peekpoke_ctlops_t	cautacc_ctlops_arg;
1719 
1720 	cautacc_ctlops_arg.size = size;
1721 	cautacc_ctlops_arg.dev_addr = dev_addr;
1722 	cautacc_ctlops_arg.host_addr = host_addr;
1723 	cautacc_ctlops_arg.handle = (ddi_acc_handle_t)hp;
1724 	cautacc_ctlops_arg.repcount = repcount;
1725 	cautacc_ctlops_arg.flags = flags;
1726 
1727 	(void) ddi_ctlops(hp->ahi_common.ah_dip, hp->ahi_common.ah_dip, cmd,
1728 	    &cautacc_ctlops_arg, NULL);
1729 }
1730 
1731 uint8_t
1732 i_ddi_caut_get8(ddi_acc_impl_t *hp, uint8_t *addr)
1733 {
1734 	uint8_t value;
1735 	i_ddi_caut_getput_ctlops(hp, (uint64_t)&value, (uint64_t)addr,
1736 	    sizeof (uint8_t), 1, 0, DDI_CTLOPS_PEEK);
1737 
1738 	return (value);
1739 }
1740 
1741 uint16_t
1742 i_ddi_caut_get16(ddi_acc_impl_t *hp, uint16_t *addr)
1743 {
1744 	uint16_t value;
1745 	i_ddi_caut_getput_ctlops(hp, (uint64_t)&value, (uint64_t)addr,
1746 	    sizeof (uint16_t), 1, 0, DDI_CTLOPS_PEEK);
1747 
1748 	return (value);
1749 }
1750 
1751 uint32_t
1752 i_ddi_caut_get32(ddi_acc_impl_t *hp, uint32_t *addr)
1753 {
1754 	uint32_t value;
1755 	i_ddi_caut_getput_ctlops(hp, (uint64_t)&value, (uint64_t)addr,
1756 	    sizeof (uint32_t), 1, 0, DDI_CTLOPS_PEEK);
1757 
1758 	return (value);
1759 }
1760 
1761 uint64_t
1762 i_ddi_caut_get64(ddi_acc_impl_t *hp, uint64_t *addr)
1763 {
1764 	uint64_t value;
1765 	i_ddi_caut_getput_ctlops(hp, (uint64_t)&value, (uint64_t)addr,
1766 	    sizeof (uint64_t), 1, 0, DDI_CTLOPS_PEEK);
1767 
1768 	return (value);
1769 }
1770 
1771 void
1772 i_ddi_caut_put8(ddi_acc_impl_t *hp, uint8_t *addr, uint8_t value)
1773 {
1774 	i_ddi_caut_getput_ctlops(hp, (uint64_t)&value, (uint64_t)addr,
1775 	    sizeof (uint8_t), 1, 0, DDI_CTLOPS_POKE);
1776 }
1777 
1778 void
1779 i_ddi_caut_put16(ddi_acc_impl_t *hp, uint16_t *addr, uint16_t value)
1780 {
1781 	i_ddi_caut_getput_ctlops(hp, (uint64_t)&value, (uint64_t)addr,
1782 	    sizeof (uint16_t), 1, 0, DDI_CTLOPS_POKE);
1783 }
1784 
1785 void
1786 i_ddi_caut_put32(ddi_acc_impl_t *hp, uint32_t *addr, uint32_t value)
1787 {
1788 	i_ddi_caut_getput_ctlops(hp, (uint64_t)&value, (uint64_t)addr,
1789 	    sizeof (uint32_t), 1, 0, DDI_CTLOPS_POKE);
1790 }
1791 
1792 void
1793 i_ddi_caut_put64(ddi_acc_impl_t *hp, uint64_t *addr, uint64_t value)
1794 {
1795 	i_ddi_caut_getput_ctlops(hp, (uint64_t)&value, (uint64_t)addr,
1796 	    sizeof (uint64_t), 1, 0, DDI_CTLOPS_POKE);
1797 }
1798 
1799 void
1800 i_ddi_caut_rep_get8(ddi_acc_impl_t *hp, uint8_t *host_addr, uint8_t *dev_addr,
1801 	size_t repcount, uint_t flags)
1802 {
1803 	i_ddi_caut_getput_ctlops(hp, (uint64_t)host_addr, (uint64_t)dev_addr,
1804 	    sizeof (uint8_t), repcount, flags, DDI_CTLOPS_PEEK);
1805 }
1806 
1807 void
1808 i_ddi_caut_rep_get16(ddi_acc_impl_t *hp, uint16_t *host_addr,
1809     uint16_t *dev_addr, size_t repcount, uint_t flags)
1810 {
1811 	i_ddi_caut_getput_ctlops(hp, (uint64_t)host_addr, (uint64_t)dev_addr,
1812 	    sizeof (uint16_t), repcount, flags, DDI_CTLOPS_PEEK);
1813 }
1814 
1815 void
1816 i_ddi_caut_rep_get32(ddi_acc_impl_t *hp, uint32_t *host_addr,
1817     uint32_t *dev_addr, size_t repcount, uint_t flags)
1818 {
1819 	i_ddi_caut_getput_ctlops(hp, (uint64_t)host_addr, (uint64_t)dev_addr,
1820 	    sizeof (uint32_t), repcount, flags, DDI_CTLOPS_PEEK);
1821 }
1822 
1823 void
1824 i_ddi_caut_rep_get64(ddi_acc_impl_t *hp, uint64_t *host_addr,
1825     uint64_t *dev_addr, size_t repcount, uint_t flags)
1826 {
1827 	i_ddi_caut_getput_ctlops(hp, (uint64_t)host_addr, (uint64_t)dev_addr,
1828 	    sizeof (uint64_t), repcount, flags, DDI_CTLOPS_PEEK);
1829 }
1830 
1831 void
1832 i_ddi_caut_rep_put8(ddi_acc_impl_t *hp, uint8_t *host_addr, uint8_t *dev_addr,
1833 	size_t repcount, uint_t flags)
1834 {
1835 	i_ddi_caut_getput_ctlops(hp, (uint64_t)host_addr, (uint64_t)dev_addr,
1836 	    sizeof (uint8_t), repcount, flags, DDI_CTLOPS_POKE);
1837 }
1838 
1839 void
1840 i_ddi_caut_rep_put16(ddi_acc_impl_t *hp, uint16_t *host_addr,
1841     uint16_t *dev_addr, size_t repcount, uint_t flags)
1842 {
1843 	i_ddi_caut_getput_ctlops(hp, (uint64_t)host_addr, (uint64_t)dev_addr,
1844 	    sizeof (uint16_t), repcount, flags, DDI_CTLOPS_POKE);
1845 }
1846 
1847 void
1848 i_ddi_caut_rep_put32(ddi_acc_impl_t *hp, uint32_t *host_addr,
1849     uint32_t *dev_addr, size_t repcount, uint_t flags)
1850 {
1851 	i_ddi_caut_getput_ctlops(hp, (uint64_t)host_addr, (uint64_t)dev_addr,
1852 	    sizeof (uint32_t), repcount, flags, DDI_CTLOPS_POKE);
1853 }
1854 
1855 void
1856 i_ddi_caut_rep_put64(ddi_acc_impl_t *hp, uint64_t *host_addr,
1857     uint64_t *dev_addr, size_t repcount, uint_t flags)
1858 {
1859 	i_ddi_caut_getput_ctlops(hp, (uint64_t)host_addr, (uint64_t)dev_addr,
1860 	    sizeof (uint64_t), repcount, flags, DDI_CTLOPS_POKE);
1861 }
1862 
1863 /*
1864  * This is called only to process peek/poke when the DIP is NULL.
1865  * Assume that this is for memory, as nexi take care of device safe accesses.
1866  */
1867 int
1868 peekpoke_mem(ddi_ctl_enum_t cmd, peekpoke_ctlops_t *in_args)
1869 {
1870 	int err = DDI_SUCCESS;
1871 	on_trap_data_t otd;
1872 
1873 	/* Set up protected environment. */
1874 	if (!on_trap(&otd, OT_DATA_ACCESS)) {
1875 		uintptr_t tramp = otd.ot_trampoline;
1876 
1877 		if (cmd == DDI_CTLOPS_POKE) {
1878 			otd.ot_trampoline = (uintptr_t)&poke_fault;
1879 			err = do_poke(in_args->size, (void *)in_args->dev_addr,
1880 			    (void *)in_args->host_addr);
1881 		} else {
1882 			otd.ot_trampoline = (uintptr_t)&peek_fault;
1883 			err = do_peek(in_args->size, (void *)in_args->dev_addr,
1884 			    (void *)in_args->host_addr);
1885 		}
1886 		otd.ot_trampoline = tramp;
1887 	} else
1888 		err = DDI_FAILURE;
1889 
1890 	/* Take down protected environment. */
1891 	no_trap();
1892 
1893 	return (err);
1894 }
1895