xref: /titanic_44/usr/src/uts/sun4u/io/pci/pci_util.c (revision 1a70ae910542068519a7b96bdc56dd5ba30b6bff)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  * PCI nexus utility routines:
31  *	property and config routines for attach()
32  *	reg/intr/range/assigned-address property routines for bus_map()
33  *	init_child()
34  *	fault handling
35  */
36 
37 #include <sys/types.h>
38 #include <sys/kmem.h>
39 #include <sys/async.h>
40 #include <sys/sysmacros.h>
41 #include <sys/sunddi.h>
42 #include <sys/sunndi.h>
43 #include <sys/fm/protocol.h>
44 #include <sys/fm/io/pci.h>
45 #include <sys/fm/util.h>
46 #include <sys/ddi_impldefs.h>
47 #include <sys/pci/pci_obj.h>
48 
49 /*LINTLIBRARY*/
50 
51 /*
52  * get_pci_properties
53  *
54  * This function is called from the attach routine to get the key
55  * properties of the pci nodes.
56  *
57  * used by: pci_attach()
58  *
59  * return value: DDI_FAILURE on failure
60  */
61 int
62 get_pci_properties(pci_t *pci_p, dev_info_t *dip)
63 {
64 	int i;
65 
66 	/*
67 	 * Get the device's port id.
68 	 */
69 	if ((pci_p->pci_id = (uint32_t)pci_get_portid(dip)) == -1u) {
70 		cmn_err(CE_WARN, "%s%d: no portid property\n",
71 			ddi_driver_name(dip), ddi_get_instance(dip));
72 		return (DDI_FAILURE);
73 	}
74 
75 	/*
76 	 * Get the bus-ranges property.
77 	 */
78 	i = sizeof (pci_p->pci_bus_range);
79 	if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
80 	    "bus-range", (caddr_t)&pci_p->pci_bus_range, &i) != DDI_SUCCESS) {
81 		cmn_err(CE_WARN, "%s%d: no bus-range property\n",
82 		    ddi_driver_name(dip), ddi_get_instance(dip));
83 		return (DDI_FAILURE);
84 	}
85 	DEBUG2(DBG_ATTACH, dip, "get_pci_properties: bus-range (%x,%x)\n",
86 		pci_p->pci_bus_range.lo, pci_p->pci_bus_range.hi);
87 
88 	/*
89 	 * disable streaming cache if necessary, this must be done
90 	 * before PBM is configured.
91 	 */
92 	if (ddi_prop_exists(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
93 			"no-streaming-cache")) {
94 		pci_stream_buf_enable = 0;
95 		pci_stream_buf_exists = 0;
96 	}
97 
98 	/*
99 	 * Get the ranges property.
100 	 */
101 	if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "ranges",
102 		(caddr_t)&pci_p->pci_ranges, &pci_p->pci_ranges_length) !=
103 		DDI_SUCCESS) {
104 
105 		cmn_err(CE_WARN, "%s%d: no ranges property\n",
106 			ddi_driver_name(dip), ddi_get_instance(dip));
107 		return (DDI_FAILURE);
108 	}
109 	pci_fix_ranges(pci_p->pci_ranges,
110 		pci_p->pci_ranges_length / sizeof (pci_ranges_t));
111 
112 	/*
113 	 * Determine the number upa slot interrupts.
114 	 */
115 	pci_p->pci_numproxy = pci_get_numproxy(pci_p->pci_dip);
116 	DEBUG1(DBG_ATTACH, dip, "get_pci_properties: numproxy=%d\n",
117 	    pci_p->pci_numproxy);
118 
119 	pci_p->pci_thermal_interrupt =
120 		ddi_getprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
121 				"thermal-interrupt", -1);
122 	DEBUG1(DBG_ATTACH, dip, "get_pci_properties: thermal_interrupt=%d\n",
123 	    pci_p->pci_thermal_interrupt);
124 	return (DDI_SUCCESS);
125 }
126 
127 /*
128  * free_pci_properties:
129  *
130  * This routine frees the memory used to cache the
131  * "ranges" properties of the pci bus device node.
132  *
133  * used by: pci_detach()
134  *
135  * return value: none
136  */
137 void
138 free_pci_properties(pci_t *pci_p)
139 {
140 	kmem_free(pci_p->pci_ranges, pci_p->pci_ranges_length);
141 }
142 
143 /*
144  * pci_reloc_reg
145  *
146  * If the "reg" entry (*pci_rp) is relocatable, lookup "assigned-addresses"
147  * property to fetch corresponding relocated address.
148  *
149  * used by: pci_map()
150  *
151  * return value:
152  *
153  *	DDI_SUCCESS		- on success
154  *	DDI_ME_INVAL		- regspec is invalid
155  */
156 int
157 pci_reloc_reg(dev_info_t *dip, dev_info_t *rdip, pci_t *pci_p,
158 	pci_regspec_t *rp)
159 {
160 	int assign_len, assign_entries, i;
161 	pci_regspec_t *assign_p;
162 	register uint32_t phys_hi = rp->pci_phys_hi;
163 	register uint32_t mask = PCI_REG_ADDR_M | PCI_CONF_ADDR_MASK;
164 	register uint32_t phys_addr = phys_hi & mask;
165 
166 	DEBUG5(DBG_MAP | DBG_CONT, dip, "\tpci_reloc_reg fr: %x.%x.%x %x.%x\n",
167 		rp->pci_phys_hi, rp->pci_phys_mid, rp->pci_phys_low,
168 		rp->pci_size_hi, rp->pci_size_low);
169 
170 	if ((phys_hi & PCI_RELOCAT_B) || !(phys_hi & PCI_ADDR_MASK))
171 		return (DDI_SUCCESS);
172 
173 	if (pci_p->hotplug_capable == B_FALSE) {	/* validate bus # */
174 		uint32_t bus = PCI_REG_BUS_G(phys_hi);
175 		if (bus < pci_p->pci_bus_range.lo ||
176 		    bus > pci_p->pci_bus_range.hi) {
177 			DEBUG1(DBG_MAP | DBG_CONT, dip, "bad bus# (%x)\n", bus);
178 			return (DDI_ME_INVAL);
179 		}
180 	}
181 
182 	/* phys_mid must be 0 regardless space type. */
183 	if (rp->pci_phys_mid != 0 || rp->pci_size_hi != 0) {
184 		DEBUG0(DBG_MAP | DBG_CONT, pci_p->pci_dip,
185 			"phys_mid or size_hi not 0\n");
186 		return (DDI_ME_INVAL);
187 	}
188 
189 	if (ddi_getlongprop(DDI_DEV_T_ANY, rdip, DDI_PROP_DONTPASS,
190 		"assigned-addresses", (caddr_t)&assign_p, &assign_len))
191 		return (DDI_ME_INVAL);
192 
193 	assign_entries = assign_len / sizeof (pci_regspec_t);
194 	for (i = 0; i < assign_entries; i++, assign_p++) {
195 		if ((assign_p->pci_phys_hi & mask) == phys_addr) {
196 			rp->pci_phys_low += assign_p->pci_phys_low;
197 			break;
198 		}
199 	}
200 	kmem_free(assign_p - i, assign_len);
201 	DEBUG5(DBG_MAP | DBG_CONT, dip, "\tpci_reloc_reg to: %x.%x.%x %x.%x\n",
202 		rp->pci_phys_hi, rp->pci_phys_mid, rp->pci_phys_low,
203 		rp->pci_size_hi, rp->pci_size_low);
204 	return (i < assign_entries ? DDI_SUCCESS : DDI_ME_INVAL);
205 }
206 
207 /*
208  * use "ranges" to translate relocated pci regspec into parent space
209  */
210 int
211 pci_xlate_reg(pci_t *pci_p, pci_regspec_t *pci_rp, struct regspec *new_rp)
212 {
213 	int n;
214 	pci_ranges_t *rng_p = pci_p->pci_ranges;
215 	int rng_n = pci_p->pci_ranges_length / sizeof (pci_ranges_t);
216 
217 	uint32_t space_type = PCI_REG_ADDR_G(pci_rp->pci_phys_hi);
218 	uint32_t reg_end, reg_begin = pci_rp->pci_phys_low;
219 	uint32_t sz = pci_rp->pci_size_low;
220 
221 	uint32_t rng_begin, rng_end;
222 
223 	if (space_type == PCI_REG_ADDR_G(PCI_ADDR_CONFIG)) {
224 		if (reg_begin > PCI_CONF_HDR_SIZE)
225 			return (DDI_ME_INVAL);
226 		sz = sz ? MIN(sz, PCI_CONF_HDR_SIZE) : PCI_CONF_HDR_SIZE;
227 		reg_begin += pci_rp->pci_phys_hi;
228 	}
229 	reg_end = reg_begin + sz - 1;
230 
231 	for (n = 0; n < rng_n; n++, rng_p++) {
232 		if (space_type != PCI_REG_ADDR_G(rng_p->child_high))
233 			continue;	/* not the same space type */
234 
235 		rng_begin = rng_p->child_low;
236 		if (space_type == PCI_REG_ADDR_G(PCI_ADDR_CONFIG))
237 			rng_begin += rng_p->child_high;
238 
239 		rng_end = rng_begin + rng_p->size_low - 1;
240 		if (reg_begin >= rng_begin && reg_end <= rng_end)
241 			break;
242 	}
243 	if (n >= rng_n)
244 		return (DDI_ME_REGSPEC_RANGE);
245 
246 	new_rp->regspec_addr = reg_begin - rng_begin + rng_p->parent_low;
247 	new_rp->regspec_bustype = rng_p->parent_high;
248 	new_rp->regspec_size = sz;
249 	DEBUG4(DBG_MAP | DBG_CONT, pci_p->pci_dip,
250 		"\tpci_xlate_reg: entry %d new_rp %x.%x %x\n",
251 		n, new_rp->regspec_bustype, new_rp->regspec_addr, sz);
252 
253 	return (DDI_SUCCESS);
254 }
255 
256 
257 /*
258  * report_dev
259  *
260  * This function is called from our control ops routine on a
261  * DDI_CTLOPS_REPORTDEV request.
262  *
263  * The display format is
264  *
265  *	<name><inst> at <pname><pinst> device <dev> function <func>
266  *
267  * where
268  *
269  *	<name>		this device's name property
270  *	<inst>		this device's instance number
271  *	<name>		parent device's name property
272  *	<inst>		parent device's instance number
273  *	<dev>		this device's device number
274  *	<func>		this device's function number
275  */
276 int
277 report_dev(dev_info_t *dip)
278 {
279 	if (dip == (dev_info_t *)0)
280 		return (DDI_FAILURE);
281 	cmn_err(CE_CONT, "?PCI-device: %s@%s, %s%d\n",
282 	    ddi_node_name(dip), ddi_get_name_addr(dip),
283 	    ddi_driver_name(dip),
284 	    ddi_get_instance(dip));
285 	return (DDI_SUCCESS);
286 }
287 
288 
289 /*
290  * reg property for pcimem nodes that covers the entire address
291  * space for the node:  config, io, or memory.
292  */
293 pci_regspec_t pci_pcimem_reg[3] =
294 {
295 	{PCI_ADDR_CONFIG,			0, 0, 0, 0x800000	},
296 	{(uint_t)(PCI_ADDR_IO|PCI_RELOCAT_B),	0, 0, 0, PCI_IO_SIZE	},
297 	{(uint_t)(PCI_ADDR_MEM32|PCI_RELOCAT_B), 0, 0, 0, PCI_MEM_SIZE	}
298 };
299 
300 /*
301  * name_child
302  *
303  * This function is called from init_child to name a node. It is
304  * also passed as a callback for node merging functions.
305  *
306  * return value: DDI_SUCCESS, DDI_FAILURE
307  */
308 static int
309 name_child(dev_info_t *child, char *name, int namelen)
310 {
311 	pci_regspec_t *pci_rp;
312 	int reglen;
313 	uint_t func;
314 	char **unit_addr;
315 	uint_t n;
316 
317 	/*
318 	 * Set the address portion of the node name based on
319 	 * unit-address property, if it exists.
320 	 * The interpretation of the unit-address is DD[,F]
321 	 * where DD is the device id and F is the function.
322 	 */
323 	if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, child,
324 	    DDI_PROP_DONTPASS, "unit-address", &unit_addr, &n) ==
325 	    DDI_PROP_SUCCESS) {
326 		if (n != 1 || *unit_addr == NULL || **unit_addr == 0) {
327 			cmn_err(CE_WARN, "unit-address property in %s.conf"
328 			    " not well-formed", ddi_driver_name(child));
329 			ddi_prop_free(unit_addr);
330 			return (DDI_FAILURE);
331 		}
332 		(void) snprintf(name, namelen, "%s", *unit_addr);
333 		ddi_prop_free(unit_addr);
334 		return (DDI_SUCCESS);
335 	}
336 
337 	/*
338 	 * The unit-address property is does not exist. Set the address
339 	 * portion of the node name based on the function and device number.
340 	 */
341 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS,
342 	    "reg", (int **)&pci_rp, (uint_t *)&reglen) == DDI_SUCCESS) {
343 		if (((reglen * sizeof (int)) % sizeof (pci_regspec_t)) != 0) {
344 			cmn_err(CE_WARN, "reg property not well-formed");
345 			return (DDI_FAILURE);
346 		}
347 
348 		func = PCI_REG_FUNC_G(pci_rp[0].pci_phys_hi);
349 		if (func != 0)
350 			(void) snprintf(name, namelen, "%x,%x",
351 				PCI_REG_DEV_G(pci_rp[0].pci_phys_hi), func);
352 		else
353 			(void) snprintf(name, namelen, "%x",
354 				PCI_REG_DEV_G(pci_rp[0].pci_phys_hi));
355 		ddi_prop_free(pci_rp);
356 		return (DDI_SUCCESS);
357 	}
358 
359 	cmn_err(CE_WARN, "cannot name pci child '%s'", ddi_node_name(child));
360 	return (DDI_FAILURE);
361 }
362 
363 int
364 uninit_child(pci_t *pci_p, dev_info_t *child)
365 {
366 	DEBUG2(DBG_CTLOPS, pci_p->pci_dip,
367 	    "DDI_CTLOPS_UNINITCHILD: arg=%s%d\n",
368 	    ddi_driver_name(child), ddi_get_instance(child));
369 
370 
371 	(void) pm_uninit_child(child);
372 
373 	ddi_set_name_addr(child, NULL);
374 	ddi_remove_minor_node(child, NULL);
375 	impl_rem_dev_props(child);
376 
377 	DEBUG0(DBG_PWR, ddi_get_parent(child), "\n\n");
378 
379 	/*
380 	 * Handle chip specific post-uninit-child tasks.
381 	 */
382 	pci_post_uninit_child(pci_p);
383 
384 	return (DDI_SUCCESS);
385 }
386 
387 /*
388  * init_child
389  *
390  * This function is called from our control ops routine on a
391  * DDI_CTLOPS_INITCHILD request.  It builds and sets the device's
392  * parent private data area.
393  *
394  * used by: pci_ctlops()
395  *
396  * return value: none
397  */
398 int
399 init_child(pci_t *pci_p, dev_info_t *child)
400 {
401 	pci_regspec_t *pci_rp;
402 	char name[10];
403 	ddi_acc_handle_t config_handle;
404 	uint16_t command_preserve, command;
405 	uint8_t bcr;
406 	uint8_t header_type, min_gnt;
407 	uint16_t latency_timer;
408 	uint_t n;
409 	int i, no_config;
410 
411 	/*
412 	 * The following is a special case for pcimem nodes.
413 	 * For these nodes we create a reg property with a
414 	 * single entry that covers the entire address space
415 	 * for the node (config, io or memory).
416 	 */
417 	if (strcmp(ddi_driver_name(child), "pcimem") == 0) {
418 		(void) ddi_prop_create(DDI_DEV_T_NONE, child,
419 		    DDI_PROP_CANSLEEP, "reg", (caddr_t)pci_pcimem_reg,
420 		    sizeof (pci_pcimem_reg));
421 		ddi_set_name_addr(child, "0");
422 		ddi_set_parent_data(child, NULL);
423 		return (DDI_SUCCESS);
424 	}
425 
426 	/*
427 	 * Check whether the node has config space or is a hard decode
428 	 * node (possibly created by a driver.conf file).
429 	 */
430 	no_config = ddi_prop_get_int(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS,
431 	    "no-config", 0);
432 
433 	/*
434 	 * Pseudo nodes indicate a prototype node with per-instance
435 	 * properties to be merged into the real h/w device node.
436 	 * However, do not merge if the no-config property is set
437 	 * (see PSARC 2000/088).
438 	 */
439 	if ((ndi_dev_is_persistent_node(child) == 0) && (no_config == 0)) {
440 		extern int pci_allow_pseudo_children;
441 
442 		if (ddi_getlongprop(DDI_DEV_T_ANY, child,
443 		    DDI_PROP_DONTPASS, "reg", (caddr_t)&pci_rp, &i) ==
444 		    DDI_SUCCESS) {
445 			cmn_err(CE_WARN, "cannot merge prototype from %s.conf",
446 			    ddi_driver_name(child));
447 			kmem_free(pci_rp, i);
448 			return (DDI_NOT_WELL_FORMED);
449 		}
450 		/*
451 		 * Name the child
452 		 */
453 		if (name_child(child, name, 10) != DDI_SUCCESS)
454 			return (DDI_FAILURE);
455 
456 		ddi_set_name_addr(child, name);
457 		ddi_set_parent_data(child, NULL);
458 
459 		/*
460 		 * Try to merge the properties from this prototype
461 		 * node into real h/w nodes.
462 		 */
463 		if (ndi_merge_node(child, name_child) == DDI_SUCCESS) {
464 			/*
465 			 * Merged ok - return failure to remove the node.
466 			 */
467 			ddi_set_name_addr(child, NULL);
468 			return (DDI_FAILURE);
469 		}
470 
471 		/* workaround for ddivs to run under PCI */
472 		if (pci_allow_pseudo_children)
473 			return (DDI_SUCCESS);
474 
475 		cmn_err(CE_WARN, "!%s@%s: %s.conf properties not merged",
476 		    ddi_driver_name(child), ddi_get_name_addr(child),
477 		    ddi_driver_name(child));
478 		ddi_set_name_addr(child, NULL);
479 		return (DDI_NOT_WELL_FORMED);
480 	}
481 
482 	if (name_child(child, name, 10) != DDI_SUCCESS)
483 		return (DDI_FAILURE);
484 	ddi_set_name_addr(child, name);
485 
486 	if (no_config != 0) {
487 		/*
488 		 * There is no config space so there's nothing more to do.
489 		 */
490 		return (DDI_SUCCESS);
491 	}
492 
493 	if (pm_init_child(child) != DDI_SUCCESS)
494 		return (DDI_FAILURE);
495 
496 
497 	/*
498 	 * If configuration registers were previously saved by
499 	 * child (before it went to D3), then let the child do the
500 	 * restore to set up the config regs as it'll first need to
501 	 * power the device out of D3.
502 	 */
503 	if (ddi_prop_exists(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS,
504 	    "config-regs-saved-by-child") == 1) {
505 		DEBUG0(DBG_PWR, child,
506 		    "INITCHILD: config regs to be restored by child\n");
507 
508 		return (DDI_SUCCESS);
509 	}
510 
511 	DEBUG2(DBG_PWR, ddi_get_parent(child),
512 	    "INITCHILD: config regs setup for %s@%s\n",
513 	    ddi_node_name(child), ddi_get_name_addr(child));
514 
515 	/*
516 	 * Map the child configuration space to for initialization.
517 	 * We assume the obp will do the following in the devices
518 	 * config space:
519 	 *
520 	 *	Set the latency-timer register to values appropriate
521 	 *	for the devices on the bus (based on other devices
522 	 *	MIN_GNT and MAX_LAT registers.
523 	 *
524 	 *	Set the fast back-to-back enable bit in the command
525 	 *	register if it's supported and all devices on the bus
526 	 *	have the capability.
527 	 *
528 	 */
529 	if (pci_config_setup(child, &config_handle) != DDI_SUCCESS) {
530 		(void) pm_uninit_child(child);
531 		ddi_set_name_addr(child, NULL);
532 
533 		return (DDI_FAILURE);
534 	}
535 
536 	/*
537 	 * Determine the configuration header type.
538 	 */
539 	header_type = pci_config_get8(config_handle, PCI_CONF_HEADER);
540 	DEBUG2(DBG_INIT_CLD, pci_p->pci_dip, "%s: header_type=%x\n",
541 	    ddi_driver_name(child), header_type);
542 
543 	/*
544 	 * Support for "command-preserve" property.  Note that we
545 	 * add PCI_COMM_BACK2BACK_ENAB to the bits to be preserved
546 	 * since the obp will set this if the device supports and
547 	 * all targets on the same bus support it.  Since psycho
548 	 * doesn't support PCI_COMM_BACK2BACK_ENAB, it will never
549 	 * be set.  This is just here in case future revs do support
550 	 * PCI_COMM_BACK2BACK_ENAB.
551 	 */
552 	command_preserve =
553 	    ddi_prop_get_int(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS,
554 		"command-preserve", 0);
555 	DEBUG2(DBG_INIT_CLD, pci_p->pci_dip, "%s: command-preserve=%x\n",
556 	    ddi_driver_name(child), command_preserve);
557 	command = pci_config_get16(config_handle, PCI_CONF_COMM);
558 	command &= (command_preserve | PCI_COMM_BACK2BACK_ENAB);
559 	command |= (pci_command_default & ~command_preserve);
560 	pci_config_put16(config_handle, PCI_CONF_COMM, command);
561 	command = pci_config_get16(config_handle, PCI_CONF_COMM);
562 	DEBUG2(DBG_INIT_CLD, pci_p->pci_dip, "%s: command=%x\n",
563 	    ddi_driver_name(child),
564 	    pci_config_get16(config_handle, PCI_CONF_COMM));
565 
566 	/*
567 	 * If the device has a bus control register then program it
568 	 * based on the settings in the command register.
569 	 */
570 	if ((header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_ONE) {
571 		bcr = pci_config_get8(config_handle, PCI_BCNF_BCNTRL);
572 		if (pci_command_default & PCI_COMM_PARITY_DETECT)
573 			bcr |= PCI_BCNF_BCNTRL_PARITY_ENABLE;
574 		if (pci_command_default & PCI_COMM_SERR_ENABLE)
575 			bcr |= PCI_BCNF_BCNTRL_SERR_ENABLE;
576 		bcr |= PCI_BCNF_BCNTRL_MAST_AB_MODE;
577 		pci_config_put8(config_handle, PCI_BCNF_BCNTRL, bcr);
578 	}
579 
580 	/*
581 	 * Initialize cache-line-size configuration register if needed.
582 	 */
583 	if (pci_set_cache_line_size_register &&
584 	    ddi_getprop(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS,
585 		"cache-line-size", 0) == 0) {
586 
587 		pci_config_put8(config_handle, PCI_CONF_CACHE_LINESZ,
588 		    PCI_CACHE_LINE_SIZE);
589 		n = pci_config_get8(config_handle, PCI_CONF_CACHE_LINESZ);
590 		if (n != 0)
591 			(void) ndi_prop_update_int(DDI_DEV_T_NONE, child,
592 			    "cache-line-size", n);
593 	}
594 
595 	/*
596 	 * Initialize latency timer registers if needed.
597 	 */
598 	if (pci_set_latency_timer_register &&
599 	    ddi_getprop(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS,
600 		"latency-timer", 0) == 0) {
601 
602 		latency_timer = pci_latency_timer;
603 		if ((header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_ONE) {
604 			pci_config_put8(config_handle, PCI_BCNF_LATENCY_TIMER,
605 			    latency_timer);
606 		} else {
607 			min_gnt = pci_config_get8(config_handle,
608 			    PCI_CONF_MIN_G);
609 			DEBUG2(DBG_INIT_CLD, pci_p->pci_dip, "%s: min_gnt=%x\n",
610 			    ddi_driver_name(child), min_gnt);
611 			if (min_gnt != 0) {
612 				switch (pci_p->pci_pbm_p->pbm_speed) {
613 				case PBM_SPEED_33MHZ:
614 					latency_timer = min_gnt * 8;
615 					break;
616 				case PBM_SPEED_66MHZ:
617 					latency_timer = min_gnt * 4;
618 					break;
619 				}
620 			}
621 		}
622 		latency_timer = MIN(latency_timer, 0xff);
623 		pci_config_put8(config_handle, PCI_CONF_LATENCY_TIMER,
624 		    latency_timer);
625 		n = pci_config_get8(config_handle, PCI_CONF_LATENCY_TIMER);
626 		if (n != 0)
627 			(void) ndi_prop_update_int(DDI_DEV_T_NONE, child,
628 			    "latency-timer", n);
629 	}
630 
631 	pci_config_teardown(&config_handle);
632 
633 	/*
634 	 * Handle chip specific init-child tasks.
635 	 */
636 	pci_post_init_child(pci_p, child);
637 
638 	return (DDI_SUCCESS);
639 }
640 
641 /*
642  * get_nreg_set
643  *
644  * Given a dev info pointer to a pci child, this routine returns the
645  * number of sets in its "reg" property.
646  *
647  * used by: pci_ctlops() - DDI_CTLOPS_NREGS
648  *
649  * return value: # of reg sets on success, zero on error
650  */
651 uint_t
652 get_nreg_set(dev_info_t *child)
653 {
654 	pci_regspec_t *pci_rp;
655 	int i, n;
656 
657 	/*
658 	 * Get the reg property for the device.
659 	 */
660 	if (ddi_getlongprop(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS, "reg",
661 	    (caddr_t)&pci_rp, &i) != DDI_SUCCESS)
662 		return (0);
663 
664 	n = i / (int)sizeof (pci_regspec_t);
665 	kmem_free(pci_rp, i);
666 	return (n);
667 }
668 
669 
670 /*
671  * get_nintr
672  *
673  * Given a dev info pointer to a pci child, this routine returns the
674  * number of items in its "interrupts" property.
675  *
676  * used by: pci_ctlops() - DDI_CTLOPS_NREGS
677  *
678  * return value: # of interrupts on success, zero on error
679  */
680 uint_t
681 get_nintr(dev_info_t *child)
682 {
683 	int *pci_ip;
684 	int i, n;
685 
686 	if (ddi_getlongprop(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS,
687 	    "interrupts", (caddr_t)&pci_ip, &i) != DDI_SUCCESS)
688 		return (0);
689 
690 	n = i / (int)sizeof (uint_t);
691 	kmem_free(pci_ip, i);
692 	return (n);
693 }
694 
695 uint64_t
696 pci_get_cfg_pabase(pci_t *pci_p)
697 {
698 	int i;
699 	pci_ranges_t *rangep = pci_p->pci_ranges;
700 	int nrange = pci_p->pci_ranges_length / sizeof (pci_ranges_t);
701 	uint32_t cfg_space_type = PCI_REG_ADDR_G(PCI_ADDR_CONFIG);
702 
703 	ASSERT(cfg_space_type == 0);
704 
705 	for (i = 0; i < nrange; i++, rangep++) {
706 		if (PCI_REG_ADDR_G(rangep->child_high) == cfg_space_type)
707 			break;
708 	}
709 
710 	if (i >= nrange)
711 		cmn_err(CE_PANIC, "no cfg space in pci(%p) ranges prop.\n",
712 			(void *)pci_p);
713 
714 	return (((uint64_t)rangep->parent_high << 32) | rangep->parent_low);
715 }
716 
717 int
718 pci_cfg_report(dev_info_t *dip, ddi_fm_error_t *derr, pci_errstate_t *pci_err_p,
719 	int caller, uint32_t prierr)
720 {
721 	int fatal = 0;
722 	int nonfatal = 0;
723 	int i;
724 	pci_target_err_t tgt_err;
725 
726 	ASSERT(dip);
727 
728 	derr->fme_ena = derr->fme_ena ? derr->fme_ena :
729 	    fm_ena_generate(0, FM_ENA_FMT1);
730 
731 	for (i = 0; pci_err_tbl[i].err_class != NULL; i++) {
732 		if (pci_err_p->pci_cfg_stat & pci_err_tbl[i].reg_bit) {
733 			char buf[FM_MAX_CLASS];
734 
735 			(void) snprintf(buf, FM_MAX_CLASS, "%s.%s",
736 					PCI_ERROR_SUBCLASS,
737 					pci_err_tbl[i].err_class);
738 			ddi_fm_ereport_post(dip, buf, derr->fme_ena,
739 			    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
740 			    PCI_CONFIG_STATUS, DATA_TYPE_UINT16,
741 			    pci_err_p->pci_cfg_stat,
742 			    PCI_CONFIG_COMMAND, DATA_TYPE_UINT16,
743 			    pci_err_p->pci_cfg_comm,
744 			    PCI_PA, DATA_TYPE_UINT64,
745 			    pci_err_p->pci_pa,
746 			    NULL);
747 
748 			switch (pci_err_tbl[i].reg_bit) {
749 			case PCI_STAT_S_SYSERR:
750 				/*
751 				 * address parity error on dma - treat as fatal
752 				 */
753 				fatal++;
754 				break;
755 			case PCI_STAT_R_MAST_AB:
756 			case PCI_STAT_R_TARG_AB:
757 			case PCI_STAT_S_PERROR:
758 				if (prierr) {
759 					/*
760 					 * piow case are already handled in
761 					 * pbm_afsr_report()
762 					 */
763 					break;
764 				}
765 				if (caller != PCI_TRAP_CALL) {
766 					/*
767 					 * if we haven't come from trap handler
768 					 * we won't have an address
769 					 */
770 					fatal++;
771 					break;
772 				}
773 
774 				/*
775 				 * queue target ereport - use return from
776 				 * pci_lookup_handle() to determine if sync
777 				 * or async
778 				 */
779 				tgt_err.tgt_err_ena = derr->fme_ena;
780 				tgt_err.tgt_err_class =
781 				    pci_err_tbl[i].terr_class;
782 				tgt_err.tgt_bridge_type = PCI_ERROR_SUBCLASS;
783 				tgt_err.tgt_err_addr =
784 				    (uint64_t)derr->fme_bus_specific;
785 				nonfatal++;
786 				errorq_dispatch(pci_target_queue,
787 				    (void *)&tgt_err,
788 				    sizeof (pci_target_err_t),
789 				    ERRORQ_ASYNC);
790 				break;
791 			default:
792 				/*
793 				 * dpe on dma write or ta on dma
794 				 */
795 				nonfatal++;
796 				break;
797 			}
798 		}
799 	}
800 
801 	if (fatal)
802 		return (DDI_FM_FATAL);
803 	else if (nonfatal)
804 		return (DDI_FM_NONFATAL);
805 
806 	return (DDI_FM_OK);
807 }
808 
809 void
810 pci_child_cfg_save(dev_info_t *dip)
811 {
812 	dev_info_t *cdip;
813 	int ret = DDI_SUCCESS;
814 
815 	/*
816 	 * Save the state of the configuration headers of child
817 	 * nodes.
818 	 */
819 
820 	for (cdip = ddi_get_child(dip); cdip != NULL;
821 	    cdip = ddi_get_next_sibling(cdip)) {
822 
823 		/*
824 		 * Not interested in children who are not already
825 		 * init'ed.  They will be set up in init_child().
826 		 */
827 		if (i_ddi_node_state(cdip) < DS_INITIALIZED) {
828 			DEBUG2(DBG_DETACH, dip, "DDI_SUSPEND: skipping "
829 			    "%s%d not in CF1\n", ddi_driver_name(cdip),
830 			    ddi_get_instance(cdip));
831 
832 			continue;
833 		}
834 
835 		/*
836 		 * Only save config registers if not already saved by child.
837 		 */
838 		if (ddi_prop_exists(DDI_DEV_T_ANY, cdip, DDI_PROP_DONTPASS,
839 		    SAVED_CONFIG_REGS) == 1) {
840 
841 			continue;
842 		}
843 
844 		/*
845 		 * The nexus needs to save config registers.  Create a property
846 		 * so it knows to restore on resume.
847 		 */
848 		ret = ndi_prop_create_boolean(DDI_DEV_T_NONE, cdip,
849 		    "nexus-saved-config-regs");
850 
851 		if (ret != DDI_PROP_SUCCESS) {
852 			cmn_err(CE_WARN, "%s%d can't update prop %s",
853 			    ddi_driver_name(cdip), ddi_get_instance(cdip),
854 			    "nexus-saved-config-regs");
855 		}
856 
857 		(void) pci_save_config_regs(cdip);
858 	}
859 }
860 
861 void
862 pci_child_cfg_restore(dev_info_t *dip)
863 {
864 	dev_info_t *cdip;
865 
866 	/*
867 	 * Restore config registers for children that did not save
868 	 * their own registers.  Children pwr states are UNKNOWN after
869 	 * a resume since it is possible for the PM framework to call
870 	 * resume without an actual power cycle. (ie if suspend fails).
871 	 */
872 	for (cdip = ddi_get_child(dip); cdip != NULL;
873 	    cdip = ddi_get_next_sibling(cdip)) {
874 
875 		/*
876 		 * Not interested in children who are not already
877 		 * init'ed.  They will be set up by init_child().
878 		 */
879 		if (i_ddi_node_state(cdip) < DS_INITIALIZED) {
880 			DEBUG2(DBG_DETACH, dip,
881 			    "DDI_RESUME: skipping %s%d not in CF1\n",
882 			    ddi_driver_name(cdip), ddi_get_instance(cdip));
883 			continue;
884 		}
885 
886 		/*
887 		 * Only restore config registers if saved by nexus.
888 		 */
889 		if (ddi_prop_exists(DDI_DEV_T_ANY, cdip, DDI_PROP_DONTPASS,
890 		    "nexus-saved-config-regs") == 1) {
891 			(void) pci_restore_config_regs(cdip);
892 
893 			DEBUG2(DBG_PWR, dip,
894 			    "DDI_RESUME: nexus restoring %s%d config regs\n",
895 			    ddi_driver_name(cdip), ddi_get_instance(cdip));
896 
897 			if (ndi_prop_remove(DDI_DEV_T_NONE, cdip,
898 			    "nexus-saved-config-regs") != DDI_PROP_SUCCESS) {
899 				cmn_err(CE_WARN, "%s%d can't remove prop %s",
900 				    ddi_driver_name(cdip),
901 				    ddi_get_instance(cdip),
902 				    "nexus-saved-config-regs");
903 			}
904 		}
905 	}
906 }
907