xref: /titanic_50/usr/src/uts/intel/io/pci/pci_pci.c (revision adc586debf12d2592024c0b8b9e44ffa104f858c)
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 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 /*
27  * PCI to PCI bus bridge nexus driver
28  */
29 
30 #include <sys/conf.h>
31 #include <sys/kmem.h>
32 #include <sys/debug.h>
33 #include <sys/modctl.h>
34 #include <sys/autoconf.h>
35 #include <sys/ddi_impldefs.h>
36 #include <sys/pci.h>
37 #include <sys/pcie_impl.h>
38 #include <sys/ddi.h>
39 #include <sys/sunddi.h>
40 #include <sys/sunndi.h>
41 #include <sys/ddifm.h>
42 #include <sys/ndifm.h>
43 #include <sys/fm/protocol.h>
44 #include <sys/hotplug/pci/pcihp.h>
45 #include <sys/pci_intr_lib.h>
46 #include <sys/psm.h>
47 
48 /*
49  * The variable controls the default setting of the command register
50  * for pci devices.  See ppb_initchild() for details.
51  */
52 static ushort_t ppb_command_default = PCI_COMM_ME | PCI_COMM_MAE | PCI_COMM_IO;
53 
54 
55 static int	ppb_bus_map(dev_info_t *, dev_info_t *, ddi_map_req_t *,
56 		    off_t, off_t, caddr_t *);
57 static int	ppb_ctlops(dev_info_t *, dev_info_t *, ddi_ctl_enum_t,
58 		    void *, void *);
59 static int	ppb_fm_init(dev_info_t *, dev_info_t *, int,
60 		    ddi_iblock_cookie_t *);
61 static int	ppb_fm_callback(dev_info_t *, ddi_fm_error_t *, const void *);
62 static int	ppb_intr_ops(dev_info_t *, dev_info_t *, ddi_intr_op_t,
63 		    ddi_intr_handle_impl_t *, void *);
64 
65 /*
66  * ppb_support_msi: Flag that controls MSI support across P2P Bridges.
67  * By default, MSI is not supported except for special cases like HT
68  * bridges/tunnels that have HT MSI mapping enabled.
69  *
70  * However, MSI support behavior can be patched on a system by changing
71  * the value of this flag as shown below:-
72  *	 0 = default value, MSI is allowed by this driver for special cases
73  *	 1 = MSI supported without any checks for this driver
74  *	-1 = MSI not supported at all
75  */
76 int ppb_support_msi = 0;
77 
78 /*
79  * Controls the usage of the Hypertransport MSI mapping capability
80  *	0 = default value, leave hardware function as it is
81  *	1 = always enable HT MSI mapping
82  *     -1 = always disable HT MSI mapping
83  */
84 int ppb_support_ht_msimap = 0;
85 
86 /*
87  * masks and values for the upper 16-bits of hypertransport cap headers
88  */
89 #define	PCI_CAP_HT_MSIMAP_TYPE			0xA800
90 #define	PCI_CAP_HT_MSIMAP_TYPE_MASK		0xFF00
91 #define	PCI_CAP_HT_MSIMAP_ENABLE		0x0001
92 #define	PCI_CAP_HT_MSIMAP_ENABLE_MASK		0x0001
93 
94 
95 struct bus_ops ppb_bus_ops = {
96 	BUSO_REV,
97 	ppb_bus_map,
98 	0,
99 	0,
100 	0,
101 	i_ddi_map_fault,
102 	ddi_dma_map,
103 	ddi_dma_allochdl,
104 	ddi_dma_freehdl,
105 	ddi_dma_bindhdl,
106 	ddi_dma_unbindhdl,
107 	ddi_dma_flush,
108 	ddi_dma_win,
109 	ddi_dma_mctl,
110 	ppb_ctlops,
111 	ddi_bus_prop_op,
112 	0,		/* (*bus_get_eventcookie)();	*/
113 	0,		/* (*bus_add_eventcall)();	*/
114 	0,		/* (*bus_remove_eventcall)();	*/
115 	0,		/* (*bus_post_event)();		*/
116 	0,		/* (*bus_intr_ctl)();		*/
117 	0,		/* (*bus_config)(); 		*/
118 	0,		/* (*bus_unconfig)(); 		*/
119 	ppb_fm_init,	/* (*bus_fm_init)(); 		*/
120 	NULL,		/* (*bus_fm_fini)(); 		*/
121 	NULL,		/* (*bus_fm_access_enter)(); 	*/
122 	NULL,		/* (*bus_fm_access_exit)(); 	*/
123 	NULL,		/* (*bus_power)(); 	*/
124 	ppb_intr_ops	/* (*bus_intr_op)(); 		*/
125 };
126 
127 /*
128  * The goal here is to leverage off of the pcihp.c source without making
129  * changes to it.  Call into it's cb_ops directly if needed.
130  */
131 static int	ppb_open(dev_t *, int, int, cred_t *);
132 static int	ppb_close(dev_t, int, int, cred_t *);
133 static int	ppb_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
134 static int	ppb_prop_op(dev_t, dev_info_t *, ddi_prop_op_t, int, char *,
135 		    caddr_t, int *);
136 static int	ppb_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
137 static void	ppb_peekpoke_cb(dev_info_t *, ddi_fm_error_t *);
138 
139 struct cb_ops ppb_cb_ops = {
140 	ppb_open,			/* open */
141 	ppb_close,			/* close */
142 	nodev,				/* strategy */
143 	nodev,				/* print */
144 	nodev,				/* dump */
145 	nodev,				/* read */
146 	nodev,				/* write */
147 	ppb_ioctl,			/* ioctl */
148 	nodev,				/* devmap */
149 	nodev,				/* mmap */
150 	nodev,				/* segmap */
151 	nochpoll,			/* poll */
152 	ppb_prop_op,			/* cb_prop_op */
153 	NULL,				/* streamtab */
154 	D_NEW | D_MP | D_HOTPLUG,	/* Driver compatibility flag */
155 	CB_REV,				/* rev */
156 	nodev,				/* int (*cb_aread)() */
157 	nodev				/* int (*cb_awrite)() */
158 };
159 
160 
161 static int ppb_probe(dev_info_t *);
162 static int ppb_attach(dev_info_t *devi, ddi_attach_cmd_t cmd);
163 static int ppb_detach(dev_info_t *devi, ddi_detach_cmd_t cmd);
164 
165 struct dev_ops ppb_ops = {
166 	DEVO_REV,		/* devo_rev */
167 	0,			/* refcnt  */
168 	ppb_info,		/* info */
169 	nulldev,		/* identify */
170 	ppb_probe,		/* probe */
171 	ppb_attach,		/* attach */
172 	ppb_detach,		/* detach */
173 	nulldev,		/* reset */
174 	&ppb_cb_ops,		/* driver operations */
175 	&ppb_bus_ops		/* bus operations */
176 };
177 
178 /*
179  * Module linkage information for the kernel.
180  */
181 
182 static struct modldrv modldrv = {
183 	&mod_driverops, /* Type of module */
184 	"PCI to PCI bridge nexus driver",
185 	&ppb_ops,	/* driver ops */
186 };
187 
188 static struct modlinkage modlinkage = {
189 	MODREV_1,
190 	(void *)&modldrv,
191 	NULL
192 };
193 
194 /*
195  * soft state pointer and structure template:
196  */
197 static void *ppb_state;
198 
199 typedef struct {
200 	dev_info_t *dip;
201 	int ppb_fmcap;
202 	ddi_iblock_cookie_t ppb_fm_ibc;
203 	kmutex_t ppb_peek_poke_mutex;
204 	kmutex_t ppb_err_mutex;
205 
206 	/*
207 	 * cpr support:
208 	 */
209 	uint_t config_state_index;
210 	struct {
211 		dev_info_t *dip;
212 		ushort_t command;
213 		uchar_t cache_line_size;
214 		uchar_t latency_timer;
215 		uchar_t header_type;
216 		uchar_t sec_latency_timer;
217 		ushort_t bridge_control;
218 	} config_state[PCI_MAX_CHILDREN];
219 
220 	uint8_t parent_bus;
221 } ppb_devstate_t;
222 
223 
224 /*
225  * forward function declarations:
226  */
227 static void	ppb_removechild(dev_info_t *);
228 static int	ppb_initchild(dev_info_t *child);
229 static void	ppb_save_config_regs(ppb_devstate_t *ppb_p);
230 static void	ppb_restore_config_regs(ppb_devstate_t *ppb_p);
231 static uint8_t	ppb_find_ht_cap(ddi_acc_handle_t cfg_hdl, uint16_t reg_mask,
232 		    uint16_t reg_val);
233 static boolean_t	ppb_ht_msimap_check(ddi_acc_handle_t cfg_hdl);
234 static int	ppb_ht_msimap_set(ddi_acc_handle_t cfg_hdl, int cmd);
235 
236 /*
237  * for <cmd> in ppb_ht_msimap_set
238  */
239 #define	HT_MSIMAP_ENABLE	1
240 #define	HT_MSIMAP_DISABLE	0
241 
242 
243 int
244 _init(void)
245 {
246 	int e;
247 
248 	if ((e = ddi_soft_state_init(&ppb_state, sizeof (ppb_devstate_t),
249 	    1)) == 0 && (e = mod_install(&modlinkage)) != 0)
250 		ddi_soft_state_fini(&ppb_state);
251 	return (e);
252 }
253 
254 int
255 _fini(void)
256 {
257 	int e;
258 
259 	if ((e = mod_remove(&modlinkage)) == 0)
260 		ddi_soft_state_fini(&ppb_state);
261 	return (e);
262 }
263 
264 int
265 _info(struct modinfo *modinfop)
266 {
267 	return (mod_info(&modlinkage, modinfop));
268 }
269 
270 /*ARGSUSED*/
271 static int
272 ppb_probe(dev_info_t *devi)
273 {
274 	return (DDI_PROBE_SUCCESS);
275 }
276 
277 /*ARGSUSED*/
278 static int
279 ppb_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
280 {
281 	dev_info_t *root = ddi_root_node();
282 	int instance;
283 	ppb_devstate_t *ppb;
284 	dev_info_t *pdip;
285 	ddi_acc_handle_t config_handle;
286 	char *bus;
287 
288 	switch (cmd) {
289 	case DDI_ATTACH:
290 
291 		/*
292 		 * Make sure the "device_type" property exists.
293 		 */
294 		(void) ddi_prop_update_string(DDI_DEV_T_NONE, devi,
295 		    "device_type", "pci");
296 
297 		/*
298 		 * Allocate and get soft state structure.
299 		 */
300 		instance = ddi_get_instance(devi);
301 		if (ddi_soft_state_zalloc(ppb_state, instance) != DDI_SUCCESS)
302 			return (DDI_FAILURE);
303 		ppb = ddi_get_soft_state(ppb_state, instance);
304 		ppb->dip = devi;
305 
306 		/*
307 		 * don't enable ereports if immediate child of npe
308 		 */
309 		if (strcmp(ddi_driver_name(ddi_get_parent(devi)), "npe") == 0)
310 			ppb->ppb_fmcap = DDI_FM_ERRCB_CAPABLE |
311 			    DDI_FM_ACCCHK_CAPABLE | DDI_FM_DMACHK_CAPABLE;
312 		else
313 			ppb->ppb_fmcap = DDI_FM_EREPORT_CAPABLE |
314 			    DDI_FM_ERRCB_CAPABLE | DDI_FM_ACCCHK_CAPABLE |
315 			    DDI_FM_DMACHK_CAPABLE;
316 
317 		ddi_fm_init(devi, &ppb->ppb_fmcap, &ppb->ppb_fm_ibc);
318 		mutex_init(&ppb->ppb_err_mutex, NULL, MUTEX_DRIVER,
319 		    (void *)ppb->ppb_fm_ibc);
320 		mutex_init(&ppb->ppb_peek_poke_mutex, NULL, MUTEX_DRIVER,
321 		    (void *)ppb->ppb_fm_ibc);
322 
323 		if (ppb->ppb_fmcap & (DDI_FM_ERRCB_CAPABLE |
324 		    DDI_FM_EREPORT_CAPABLE))
325 			pci_ereport_setup(devi);
326 		if (ppb->ppb_fmcap & DDI_FM_ERRCB_CAPABLE)
327 			ddi_fm_handler_register(devi, ppb_fm_callback, NULL);
328 
329 		if (pci_config_setup(devi, &config_handle) != DDI_SUCCESS) {
330 			if (ppb->ppb_fmcap & DDI_FM_ERRCB_CAPABLE)
331 				ddi_fm_handler_unregister(devi);
332 			if (ppb->ppb_fmcap & (DDI_FM_ERRCB_CAPABLE |
333 			    DDI_FM_EREPORT_CAPABLE))
334 				pci_ereport_teardown(devi);
335 			ddi_fm_fini(devi);
336 			ddi_soft_state_free(ppb_state, instance);
337 			return (DDI_FAILURE);
338 		}
339 
340 		ppb->parent_bus = PCIE_PCIECAP_DEV_TYPE_PCI_DEV;
341 		for (pdip = ddi_get_parent(devi); pdip && (pdip != root) &&
342 		    (ppb->parent_bus != PCIE_PCIECAP_DEV_TYPE_PCIE_DEV);
343 		    pdip = ddi_get_parent(pdip)) {
344 			if (ddi_prop_lookup_string(DDI_DEV_T_ANY, pdip,
345 			    DDI_PROP_DONTPASS, "device_type", &bus) !=
346 			    DDI_PROP_SUCCESS)
347 				break;
348 
349 			if (strcmp(bus, "pciex") == 0)
350 				ppb->parent_bus =
351 				    PCIE_PCIECAP_DEV_TYPE_PCIE_DEV;
352 
353 			ddi_prop_free(bus);
354 		}
355 
356 		if (ppb_support_ht_msimap == 1)
357 			(void) ppb_ht_msimap_set(config_handle,
358 			    HT_MSIMAP_ENABLE);
359 		else if (ppb_support_ht_msimap == -1)
360 			(void) ppb_ht_msimap_set(config_handle,
361 			    HT_MSIMAP_DISABLE);
362 
363 		pci_config_teardown(&config_handle);
364 
365 		/*
366 		 * Initialize hotplug support on this bus. At minimum
367 		 * (for non hotplug bus) this would create ":devctl" minor
368 		 * node to support DEVCTL_DEVICE_* and DEVCTL_BUS_* ioctls
369 		 * to this bus.
370 		 */
371 		if (pcihp_init(devi) != DDI_SUCCESS)
372 			cmn_err(CE_WARN,
373 			    "pci: Failed to setup hotplug framework");
374 
375 		ddi_report_dev(devi);
376 		return (DDI_SUCCESS);
377 
378 	case DDI_RESUME:
379 
380 		/*
381 		 * Get the soft state structure for the bridge.
382 		 */
383 		ppb = ddi_get_soft_state(ppb_state, ddi_get_instance(devi));
384 		ppb_restore_config_regs(ppb);
385 		return (DDI_SUCCESS);
386 
387 	default:
388 		break;
389 	}
390 	return (DDI_FAILURE);
391 }
392 
393 /*ARGSUSED*/
394 static int
395 ppb_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
396 {
397 	ppb_devstate_t *ppb;
398 
399 	switch (cmd) {
400 	case DDI_DETACH:
401 		(void) ddi_prop_remove(DDI_DEV_T_NONE, devi, "device_type");
402 
403 		ppb = ddi_get_soft_state(ppb_state, ddi_get_instance(devi));
404 		if (ppb->ppb_fmcap & DDI_FM_ERRCB_CAPABLE)
405 			ddi_fm_handler_unregister(devi);
406 		if (ppb->ppb_fmcap & (DDI_FM_ERRCB_CAPABLE |
407 		    DDI_FM_EREPORT_CAPABLE))
408 			pci_ereport_teardown(devi);
409 		mutex_destroy(&ppb->ppb_peek_poke_mutex);
410 		mutex_destroy(&ppb->ppb_err_mutex);
411 		ddi_fm_fini(devi);
412 
413 		/*
414 		 * And finally free the per-pci soft state.
415 		 */
416 		ddi_soft_state_free(ppb_state, ddi_get_instance(devi));
417 
418 		/*
419 		 * Uninitialize hotplug support on this bus.
420 		 */
421 		(void) pcihp_uninit(devi);
422 		return (DDI_SUCCESS);
423 
424 	case DDI_SUSPEND:
425 		ppb = ddi_get_soft_state(ppb_state, ddi_get_instance(devi));
426 		ppb_save_config_regs(ppb);
427 		return (DDI_SUCCESS);
428 
429 	default:
430 		break;
431 	}
432 	return (DDI_FAILURE);
433 }
434 
435 /*ARGSUSED*/
436 static int
437 ppb_bus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
438 	off_t offset, off_t len, caddr_t *vaddrp)
439 {
440 	dev_info_t *pdip;
441 
442 	pdip = (dev_info_t *)DEVI(dip)->devi_parent;
443 	return ((DEVI(pdip)->devi_ops->devo_bus_ops->bus_map)(pdip,
444 	    rdip, mp, offset, len, vaddrp));
445 }
446 
447 /*ARGSUSED*/
448 static int
449 ppb_ctlops(dev_info_t *dip, dev_info_t *rdip,
450 	ddi_ctl_enum_t ctlop, void *arg, void *result)
451 {
452 	pci_regspec_t *drv_regp;
453 	int	reglen;
454 	int	rn;
455 	int	totreg;
456 	ppb_devstate_t *ppb = ddi_get_soft_state(ppb_state,
457 	    ddi_get_instance(dip));
458 	struct detachspec *dsp;
459 	struct attachspec *asp;
460 
461 	switch (ctlop) {
462 	case DDI_CTLOPS_REPORTDEV:
463 		if (rdip == (dev_info_t *)0)
464 			return (DDI_FAILURE);
465 		cmn_err(CE_CONT, "?PCI-device: %s@%s, %s%d\n",
466 		    ddi_node_name(rdip), ddi_get_name_addr(rdip),
467 		    ddi_driver_name(rdip),
468 		    ddi_get_instance(rdip));
469 		return (DDI_SUCCESS);
470 
471 	case DDI_CTLOPS_INITCHILD:
472 		return (ppb_initchild((dev_info_t *)arg));
473 
474 	case DDI_CTLOPS_UNINITCHILD:
475 		ppb_removechild((dev_info_t *)arg);
476 		return (DDI_SUCCESS);
477 
478 	case DDI_CTLOPS_SIDDEV:
479 		return (DDI_SUCCESS);
480 
481 	case DDI_CTLOPS_REGSIZE:
482 	case DDI_CTLOPS_NREGS:
483 		if (rdip == (dev_info_t *)0)
484 			return (DDI_FAILURE);
485 		break;
486 
487 	/* X86 systems support PME wakeup from suspend */
488 	case DDI_CTLOPS_ATTACH:
489 		if (!pcie_is_child(dip, rdip))
490 			return (DDI_SUCCESS);
491 
492 		asp = (struct attachspec *)arg;
493 		if ((ppb->parent_bus == PCIE_PCIECAP_DEV_TYPE_PCIE_DEV) &&
494 		    (asp->when == DDI_POST) && (asp->result == DDI_SUCCESS))
495 			pf_init(rdip, (void *)ppb->ppb_fm_ibc, asp->cmd);
496 
497 		if (asp->cmd == DDI_RESUME && asp->when == DDI_PRE)
498 			if (pci_pre_resume(rdip) != DDI_SUCCESS)
499 				return (DDI_FAILURE);
500 
501 		return (DDI_SUCCESS);
502 
503 	case DDI_CTLOPS_DETACH:
504 		if (!pcie_is_child(dip, rdip))
505 			return (DDI_SUCCESS);
506 
507 		dsp = (struct detachspec *)arg;
508 		if ((ppb->parent_bus == PCIE_PCIECAP_DEV_TYPE_PCIE_DEV) &&
509 		    (dsp->when == DDI_PRE))
510 			pf_fini(rdip, dsp->cmd);
511 
512 		if (dsp->cmd == DDI_SUSPEND && dsp->when == DDI_POST)
513 			if (pci_post_suspend(rdip) != DDI_SUCCESS)
514 				return (DDI_FAILURE);
515 
516 		return (DDI_SUCCESS);
517 
518 	case DDI_CTLOPS_PEEK:
519 	case DDI_CTLOPS_POKE:
520 		if (strcmp(ddi_driver_name(ddi_get_parent(dip)), "npe") != 0)
521 			return (ddi_ctlops(dip, rdip, ctlop, arg, result));
522 		return (pci_peekpoke_check(dip, rdip, ctlop, arg, result,
523 		    ddi_ctlops, &ppb->ppb_err_mutex,
524 		    &ppb->ppb_peek_poke_mutex, ppb_peekpoke_cb));
525 
526 	default:
527 		return (ddi_ctlops(dip, rdip, ctlop, arg, result));
528 	}
529 
530 	*(int *)result = 0;
531 	if (ddi_getlongprop(DDI_DEV_T_ANY, rdip,
532 	    DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, "reg",
533 	    (caddr_t)&drv_regp, &reglen) != DDI_SUCCESS)
534 		return (DDI_FAILURE);
535 
536 	totreg = reglen / sizeof (pci_regspec_t);
537 	if (ctlop == DDI_CTLOPS_NREGS)
538 		*(int *)result = totreg;
539 	else if (ctlop == DDI_CTLOPS_REGSIZE) {
540 		rn = *(int *)arg;
541 		if (rn >= totreg) {
542 			kmem_free(drv_regp, reglen);
543 			return (DDI_FAILURE);
544 		}
545 		*(off_t *)result = drv_regp[rn].pci_size_low;
546 	}
547 
548 	kmem_free(drv_regp, reglen);
549 	return (DDI_SUCCESS);
550 }
551 
552 static int
553 ppb_name_child(dev_info_t *child, char *name, int namelen)
554 {
555 	pci_regspec_t *pci_rp;
556 	uint_t slot, func;
557 	char **unit_addr;
558 	uint_t n;
559 
560 	/*
561 	 * For .conf nodes, use unit-address property as name
562 	 */
563 	if (ndi_dev_is_persistent_node(child) == 0) {
564 		if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, child,
565 		    DDI_PROP_DONTPASS, "unit-address", &unit_addr, &n) !=
566 		    DDI_PROP_SUCCESS) {
567 			cmn_err(CE_WARN,
568 			    "cannot find unit-address in %s.conf",
569 			    ddi_driver_name(child));
570 			return (DDI_FAILURE);
571 		}
572 		if (n != 1 || *unit_addr == NULL || **unit_addr == 0) {
573 			cmn_err(CE_WARN, "unit-address property in %s.conf"
574 			    " not well-formed", ddi_driver_name(child));
575 			ddi_prop_free(unit_addr);
576 			return (DDI_SUCCESS);
577 		}
578 		(void) snprintf(name, namelen, "%s", *unit_addr);
579 		ddi_prop_free(unit_addr);
580 		return (DDI_SUCCESS);
581 	}
582 
583 	/* get child "reg" property */
584 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, child,
585 	    DDI_PROP_DONTPASS, "reg", (int **)&pci_rp, &n) != DDI_SUCCESS) {
586 		return (DDI_FAILURE);
587 	}
588 
589 	/* copy the device identifications */
590 	slot = PCI_REG_DEV_G(pci_rp->pci_phys_hi);
591 	func = PCI_REG_FUNC_G(pci_rp->pci_phys_hi);
592 
593 	if (func != 0)
594 		(void) snprintf(name, namelen, "%x,%x", slot, func);
595 	else
596 		(void) snprintf(name, namelen, "%x", slot);
597 
598 	ddi_prop_free(pci_rp);
599 	return (DDI_SUCCESS);
600 }
601 
602 static int
603 ppb_initchild(dev_info_t *child)
604 {
605 	struct ddi_parent_private_data *pdptr;
606 	ppb_devstate_t *ppb;
607 	char name[MAXNAMELEN];
608 	ddi_acc_handle_t config_handle;
609 	ushort_t command_preserve, command;
610 
611 	ppb = (ppb_devstate_t *)ddi_get_soft_state(ppb_state,
612 	    ddi_get_instance(ddi_get_parent(child)));
613 
614 	if (ppb_name_child(child, name, MAXNAMELEN) != DDI_SUCCESS)
615 		return (DDI_FAILURE);
616 	ddi_set_name_addr(child, name);
617 
618 	/*
619 	 * Pseudo nodes indicate a prototype node with per-instance
620 	 * properties to be merged into the real h/w device node.
621 	 * The interpretation of the unit-address is DD[,F]
622 	 * where DD is the device id and F is the function.
623 	 */
624 	if (ndi_dev_is_persistent_node(child) == 0) {
625 		extern int pci_allow_pseudo_children;
626 
627 		ddi_set_parent_data(child, NULL);
628 
629 		/*
630 		 * Try to merge the properties from this prototype
631 		 * node into real h/w nodes.
632 		 */
633 		if (ndi_merge_node(child, ppb_name_child) == DDI_SUCCESS) {
634 			/*
635 			 * Merged ok - return failure to remove the node.
636 			 */
637 			ddi_set_name_addr(child, NULL);
638 			return (DDI_FAILURE);
639 		}
640 
641 		/* workaround for ddivs to run under PCI */
642 		if (pci_allow_pseudo_children)
643 			return (DDI_SUCCESS);
644 
645 		/*
646 		 * The child was not merged into a h/w node,
647 		 * but there's not much we can do with it other
648 		 * than return failure to cause the node to be removed.
649 		 */
650 		cmn_err(CE_WARN, "!%s@%s: %s.conf properties not merged",
651 		    ddi_driver_name(child), ddi_get_name_addr(child),
652 		    ddi_driver_name(child));
653 		ddi_set_name_addr(child, NULL);
654 		return (DDI_NOT_WELL_FORMED);
655 	}
656 
657 	ddi_set_parent_data(child, NULL);
658 
659 	/*
660 	 * PCIe FMA specific
661 	 *
662 	 * Note: parent_data for parent is created only if this is PCI-E
663 	 * platform, for which, SG take a different route to handle device
664 	 * errors.
665 	 */
666 	if (ppb->parent_bus == PCIE_PCIECAP_DEV_TYPE_PCIE_DEV) {
667 		if (pcie_init_bus(child) == NULL)
668 			return (DDI_FAILURE);
669 	}
670 
671 	/* transfer select properties from PROM to kernel */
672 	if (ddi_getprop(DDI_DEV_T_NONE, child, DDI_PROP_DONTPASS,
673 	    "interrupts", -1) != -1) {
674 		pdptr = kmem_zalloc((sizeof (struct ddi_parent_private_data) +
675 		    sizeof (struct intrspec)), KM_SLEEP);
676 		pdptr->par_intr = (struct intrspec *)(pdptr + 1);
677 		pdptr->par_nintr = 1;
678 		ddi_set_parent_data(child, pdptr);
679 	} else
680 		ddi_set_parent_data(child, NULL);
681 
682 	if (pci_config_setup(child, &config_handle) != DDI_SUCCESS)
683 		return (DDI_FAILURE);
684 
685 	/*
686 	 * Support for the "command-preserve" property.
687 	 */
688 	command_preserve = ddi_prop_get_int(DDI_DEV_T_ANY, child,
689 	    DDI_PROP_DONTPASS, "command-preserve", 0);
690 	command = pci_config_get16(config_handle, PCI_CONF_COMM);
691 	command &= (command_preserve | PCI_COMM_BACK2BACK_ENAB);
692 	command |= (ppb_command_default & ~command_preserve);
693 	pci_config_put16(config_handle, PCI_CONF_COMM, command);
694 
695 	pci_config_teardown(&config_handle);
696 	return (DDI_SUCCESS);
697 }
698 
699 static void
700 ppb_removechild(dev_info_t *dip)
701 {
702 	struct ddi_parent_private_data *pdptr;
703 	ppb_devstate_t *ppb;
704 
705 	ppb = (ppb_devstate_t *)ddi_get_soft_state(ppb_state,
706 	    ddi_get_instance(ddi_get_parent(dip)));
707 
708 	if (ppb->parent_bus == PCIE_PCIECAP_DEV_TYPE_PCIE_DEV)
709 		pcie_fini_bus(dip);
710 	else if ((pdptr = ddi_get_parent_data(dip)) != NULL) {
711 		kmem_free(pdptr, (sizeof (*pdptr) + sizeof (struct intrspec)));
712 		ddi_set_parent_data(dip, NULL);
713 	}
714 	ddi_set_name_addr(dip, NULL);
715 
716 	/*
717 	 * Strip the node to properly convert it back to prototype form
718 	 */
719 	ddi_remove_minor_node(dip, NULL);
720 
721 	impl_rem_dev_props(dip);
722 }
723 
724 /*
725  * ppb_save_config_regs
726  *
727  * This routine saves the state of the configuration registers of all
728  * the child nodes of each PBM.
729  *
730  * used by: ppb_detach() on suspends
731  *
732  * return value: none
733  */
734 static void
735 ppb_save_config_regs(ppb_devstate_t *ppb_p)
736 {
737 	int i;
738 	dev_info_t *dip;
739 	ddi_acc_handle_t config_handle;
740 
741 	for (i = 0, dip = ddi_get_child(ppb_p->dip); dip != NULL;
742 	    i++, dip = ddi_get_next_sibling(dip)) {
743 
744 		if (pci_config_setup(dip, &config_handle) != DDI_SUCCESS) {
745 			cmn_err(CE_WARN, "%s%d: can't config space for %s%d\n",
746 			    ddi_driver_name(ppb_p->dip),
747 			    ddi_get_instance(ppb_p->dip),
748 			    ddi_driver_name(dip),
749 			    ddi_get_instance(dip));
750 			continue;
751 		}
752 
753 		ppb_p->config_state[i].dip = dip;
754 		ppb_p->config_state[i].command =
755 		    pci_config_get16(config_handle, PCI_CONF_COMM);
756 		pci_config_teardown(&config_handle);
757 	}
758 	ppb_p->config_state_index = i;
759 }
760 
761 
762 /*
763  * ppb_restore_config_regs
764  *
765  * This routine restores the state of the configuration registers of all
766  * the child nodes of each PBM.
767  *
768  * used by: ppb_attach() on resume
769  *
770  * return value: none
771  */
772 static void
773 ppb_restore_config_regs(ppb_devstate_t *ppb_p)
774 {
775 	int i;
776 	dev_info_t *dip;
777 	ddi_acc_handle_t config_handle;
778 
779 	for (i = 0; i < ppb_p->config_state_index; i++) {
780 		dip = ppb_p->config_state[i].dip;
781 		if (pci_config_setup(dip, &config_handle) != DDI_SUCCESS) {
782 			cmn_err(CE_WARN, "%s%d: can't config space for %s%d\n",
783 			    ddi_driver_name(ppb_p->dip),
784 			    ddi_get_instance(ppb_p->dip),
785 			    ddi_driver_name(dip),
786 			    ddi_get_instance(dip));
787 			continue;
788 		}
789 		pci_config_put16(config_handle, PCI_CONF_COMM,
790 		    ppb_p->config_state[i].command);
791 		pci_config_teardown(&config_handle);
792 	}
793 }
794 
795 
796 /*
797  * returns the location of a hypertransport capability whose upper 16-bit
798  * register of the cap header matches <reg_val> after masking the register
799  * with <reg_mask>; if both <reg_mask> and <reg_val> are 0, it will return the
800  * first HT cap found
801  */
802 static uint8_t
803 ppb_find_ht_cap(ddi_acc_handle_t cfg_hdl, uint16_t reg_mask, uint16_t reg_val)
804 {
805 	uint16_t status, reg;
806 	uint8_t ptr, id;
807 
808 	status = pci_config_get16(cfg_hdl, PCI_CONF_STAT);
809 	if (status == 0xffff || !((status & PCI_STAT_CAP)))
810 		return (PCI_CAP_NEXT_PTR_NULL);
811 
812 	ptr = pci_config_get8(cfg_hdl, PCI_CONF_CAP_PTR);
813 	while (ptr != 0xFF &&
814 	    ptr != PCI_CAP_NEXT_PTR_NULL &&
815 	    ptr >= PCI_CAP_PTR_OFF) {
816 
817 		ptr &= PCI_CAP_PTR_MASK;
818 		id = pci_config_get8(cfg_hdl, ptr + PCI_CAP_ID);
819 
820 		if (id == PCI_CAP_ID_HT) {
821 			reg = pci_config_get16(cfg_hdl,
822 			    ptr + PCI_CAP_ID_REGS_OFF);
823 			if ((reg & reg_mask) == reg_val)
824 				return (ptr);
825 		}
826 		ptr = pci_config_get8(cfg_hdl, ptr + PCI_CAP_NEXT_PTR);
827 	}
828 
829 	return (PCI_CAP_NEXT_PTR_NULL);
830 }
831 
832 
833 static boolean_t
834 ppb_ht_msimap_check(ddi_acc_handle_t cfg_hdl)
835 {
836 	uint8_t ptr;
837 
838 	ptr = ppb_find_ht_cap(cfg_hdl,
839 	    PCI_CAP_HT_MSIMAP_TYPE_MASK | PCI_CAP_HT_MSIMAP_ENABLE_MASK,
840 	    PCI_CAP_HT_MSIMAP_TYPE | PCI_CAP_HT_MSIMAP_ENABLE);
841 
842 	if (ptr == PCI_CAP_NEXT_PTR_NULL)
843 		return (B_FALSE);
844 
845 	return (B_TRUE);
846 }
847 
848 
849 static int
850 ppb_ht_msimap_set(ddi_acc_handle_t cfg_hdl, int cmd)
851 {
852 	uint8_t ptr;
853 	uint16_t reg;
854 
855 	ptr = ppb_find_ht_cap(cfg_hdl, PCI_CAP_HT_MSIMAP_TYPE_MASK,
856 	    PCI_CAP_HT_MSIMAP_TYPE);
857 	if (ptr == PCI_CAP_NEXT_PTR_NULL)
858 		return (0);
859 
860 	reg = pci_config_get16(cfg_hdl, ptr + PCI_CAP_ID_REGS_OFF);
861 	switch (cmd) {
862 	case HT_MSIMAP_ENABLE:
863 		reg |= PCI_CAP_HT_MSIMAP_ENABLE;
864 		break;
865 	case HT_MSIMAP_DISABLE:
866 	default:
867 		reg &= ~(uint16_t)PCI_CAP_HT_MSIMAP_ENABLE;
868 	}
869 
870 	pci_config_put16(cfg_hdl, ptr + PCI_CAP_ID_REGS_OFF, reg);
871 	return (1);
872 }
873 
874 
875 /*
876  * intercept certain interrupt services to handle special cases
877  */
878 static int
879 ppb_intr_ops(dev_info_t *pdip, dev_info_t *rdip, ddi_intr_op_t intr_op,
880     ddi_intr_handle_impl_t *hdlp, void *result)
881 {
882 	ddi_acc_handle_t cfg_hdl;
883 	int rv = DDI_SUCCESS;
884 
885 	if (intr_op != DDI_INTROP_SUPPORTED_TYPES)
886 		return (i_ddi_intr_ops(pdip, rdip, intr_op, hdlp, result));
887 
888 	DDI_INTR_NEXDBG((CE_CONT,
889 	    "ppb_intr_ops: pdip 0x%p, rdip 0x%p, op %x handle 0x%p\n",
890 	    (void *)pdip, (void *)rdip, intr_op, (void *)hdlp));
891 
892 	/* Fixed interrupt is supported by default */
893 	*(int *)result = DDI_INTR_TYPE_FIXED;
894 
895 	if (ppb_support_msi == -1) {
896 		DDI_INTR_NEXDBG((CE_CONT,
897 		    "ppb_intr_ops: MSI is not allowed\n"));
898 		goto OUT;
899 	}
900 
901 	if (ppb_support_msi == 1) {
902 		DDI_INTR_NEXDBG((CE_CONT,
903 		    "ppb_intr_ops: MSI is always allowed\n"));
904 		rv = i_ddi_intr_ops(pdip, rdip, intr_op, hdlp, result);
905 		goto OUT;
906 	}
907 
908 	if (pci_config_setup(pdip, &cfg_hdl) != DDI_SUCCESS) {
909 		DDI_INTR_NEXDBG((CE_CONT,
910 		    "ppb_intr_ops: pci_config_setup() failed\n"));
911 		goto OUT;
912 	}
913 
914 	/*
915 	 * check for hypertransport msi mapping capability
916 	 */
917 	if (ppb_ht_msimap_check(cfg_hdl)) {
918 		DDI_INTR_NEXDBG((CE_CONT,
919 		    "ppb_intr_ops: HT MSI mapping enabled\n"));
920 		rv = i_ddi_intr_ops(pdip, rdip, intr_op, hdlp, result);
921 	}
922 
923 	/*
924 	 * if we add failure conditions after pci_config_setup, move this to
925 	 * OUT and use an extra flag to indicate the need to teardown cfg_hdl
926 	 */
927 	pci_config_teardown(&cfg_hdl);
928 
929 OUT:
930 	DDI_INTR_NEXDBG((CE_CONT,
931 	    "ppb_intr_ops: rdip 0x%p, returns supported types: 0x%x\n",
932 	    (void *)rdip, *(int *)result));
933 	return (rv);
934 }
935 
936 static int
937 ppb_open(dev_t *devp, int flags, int otyp, cred_t *credp)
938 {
939 	return ((pcihp_get_cb_ops())->cb_open(devp, flags, otyp, credp));
940 }
941 
942 static int
943 ppb_close(dev_t dev, int flags, int otyp, cred_t *credp)
944 {
945 	return ((pcihp_get_cb_ops())->cb_close(dev, flags, otyp, credp));
946 }
947 
948 static int
949 ppb_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, int *rvalp)
950 {
951 	return ((pcihp_get_cb_ops())->cb_ioctl(dev, cmd, arg, mode, credp,
952 	    rvalp));
953 }
954 
955 static int
956 ppb_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op,
957 	int flags, char *name, caddr_t valuep, int *lengthp)
958 {
959 	return ((pcihp_get_cb_ops())->cb_prop_op(dev, dip, prop_op, flags,
960 	    name, valuep, lengthp));
961 }
962 
963 static int
964 ppb_info(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
965 {
966 	return (pcihp_info(dip, cmd, arg, result));
967 }
968 
969 void ppb_peekpoke_cb(dev_info_t *dip, ddi_fm_error_t *derr) {
970 	(void) pci_ereport_post(dip, derr, NULL);
971 }
972 
973 /*ARGSUSED*/
974 static int
975 ppb_fm_init(dev_info_t *dip, dev_info_t *tdip, int cap,
976     ddi_iblock_cookie_t *ibc)
977 {
978 	ppb_devstate_t  *ppb = ddi_get_soft_state(ppb_state,
979 	    ddi_get_instance(dip));
980 
981 	ASSERT(ibc != NULL);
982 	*ibc = ppb->ppb_fm_ibc;
983 
984 	return (ppb->ppb_fmcap);
985 }
986 
987 /*ARGSUSED*/
988 static int
989 ppb_fm_callback(dev_info_t *dip, ddi_fm_error_t *derr, const void *no_used)
990 {
991 	ppb_devstate_t  *ppb = ddi_get_soft_state(ppb_state,
992 	    ddi_get_instance(dip));
993 
994 	mutex_enter(&ppb->ppb_err_mutex);
995 	pci_ereport_post(dip, derr, NULL);
996 	mutex_exit(&ppb->ppb_err_mutex);
997 	return (derr->fme_status);
998 }
999