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