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  *	Host to PCI local bus driver
     28  */
     29 
     30 #include <sys/conf.h>
     31 #include <sys/modctl.h>
     32 #include <sys/pci.h>
     33 #include <sys/pci_impl.h>
     34 #include <sys/sysmacros.h>
     35 #include <sys/sunndi.h>
     36 #include <sys/ddifm.h>
     37 #include <sys/ndifm.h>
     38 #include <sys/fm/protocol.h>
     39 #include <sys/hotplug/pci/pcihp.h>
     40 #include <io/pci/pci_common.h>
     41 #include <io/pci/pci_tools_ext.h>
     42 
     43 /* Save minimal state. */
     44 void *pci_statep;
     45 
     46 /*
     47  * Bus Operation functions
     48  */
     49 static int	pci_bus_map(dev_info_t *, dev_info_t *, ddi_map_req_t *,
     50 		    off_t, off_t, caddr_t *);
     51 static int	pci_ctlops(dev_info_t *, dev_info_t *, ddi_ctl_enum_t,
     52 		    void *, void *);
     53 static int	pci_intr_ops(dev_info_t *, dev_info_t *, ddi_intr_op_t,
     54 		    ddi_intr_handle_impl_t *, void *);
     55 static int	pci_fm_init(dev_info_t *, dev_info_t *, int,
     56 		    ddi_iblock_cookie_t *);
     57 static int	pci_fm_callback(dev_info_t *, ddi_fm_error_t *, const void *);
     58 
     59 struct bus_ops pci_bus_ops = {
     60 	BUSO_REV,
     61 	pci_bus_map,
     62 	NULL,
     63 	NULL,
     64 	NULL,
     65 	i_ddi_map_fault,
     66 	ddi_dma_map,
     67 	ddi_dma_allochdl,
     68 	ddi_dma_freehdl,
     69 	ddi_dma_bindhdl,
     70 	ddi_dma_unbindhdl,
     71 	ddi_dma_flush,
     72 	ddi_dma_win,
     73 	ddi_dma_mctl,
     74 	pci_ctlops,
     75 	ddi_bus_prop_op,
     76 	0,		/* (*bus_get_eventcookie)();	*/
     77 	0,		/* (*bus_add_eventcall)();	*/
     78 	0,		/* (*bus_remove_eventcall)();	*/
     79 	0,		/* (*bus_post_event)();		*/
     80 	0,		/* (*bus_intr_ctl)(); */
     81 	0,		/* (*bus_config)(); */
     82 	0,		/* (*bus_unconfig)(); */
     83 	pci_fm_init,	/* (*bus_fm_init)(); */
     84 	NULL,		/* (*bus_fm_fini)(); */
     85 	NULL,		/* (*bus_fm_access_enter)(); */
     86 	NULL,		/* (*bus_fm_access_exit)(); */
     87 	NULL,		/* (*bus_power)(); */
     88 	pci_intr_ops	/* (*bus_intr_op)(); */
     89 };
     90 
     91 /*
     92  * One goal here is to leverage off of the pcihp.c source without making
     93  * changes to it.  Call into it's cb_ops directly if needed, piggybacking
     94  * anything else needed by the pci_tools.c module.  Only pci_tools and pcihp
     95  * will be opening PCI nexus driver file descriptors.
     96  */
     97 static int	pci_open(dev_t *, int, int, cred_t *);
     98 static int	pci_close(dev_t, int, int, cred_t *);
     99 static int	pci_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
    100 static int	pci_prop_op(dev_t, dev_info_t *, ddi_prop_op_t, int, char *,
    101 		    caddr_t, int *);
    102 static int	pci_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
    103 static void	pci_peekpoke_cb(dev_info_t *, ddi_fm_error_t *);
    104 
    105 struct cb_ops pci_cb_ops = {
    106 	pci_open,			/* open */
    107 	pci_close,			/* close */
    108 	nodev,				/* strategy */
    109 	nodev,				/* print */
    110 	nodev,				/* dump */
    111 	nodev,				/* read */
    112 	nodev,				/* write */
    113 	pci_ioctl,			/* ioctl */
    114 	nodev,				/* devmap */
    115 	nodev,				/* mmap */
    116 	nodev,				/* segmap */
    117 	nochpoll,			/* poll */
    118 	pci_prop_op,			/* cb_prop_op */
    119 	NULL,				/* streamtab */
    120 	D_NEW | D_MP | D_HOTPLUG,	/* Driver compatibility flag */
    121 	CB_REV,				/* rev */
    122 	nodev,				/* int (*cb_aread)() */
    123 	nodev				/* int (*cb_awrite)() */
    124 };
    125 
    126 /*
    127  * Device Node Operation functions
    128  */
    129 static int pci_attach(dev_info_t *devi, ddi_attach_cmd_t cmd);
    130 static int pci_detach(dev_info_t *devi, ddi_detach_cmd_t cmd);
    131 
    132 struct dev_ops pci_ops = {
    133 	DEVO_REV,		/* devo_rev */
    134 	0,			/* refcnt  */
    135 	pci_info,		/* info */
    136 	nulldev,		/* identify */
    137 	nulldev,		/* probe */
    138 	pci_attach,		/* attach */
    139 	pci_detach,		/* detach */
    140 	nulldev,		/* reset */
    141 	&pci_cb_ops,		/* driver operations */
    142 	&pci_bus_ops,		/* bus operations */
    143 	NULL,			/* power */
    144 	ddi_quiesce_not_needed		/* quiesce */
    145 };
    146 
    147 /*
    148  * This variable controls the default setting of the command register
    149  * for pci devices.  See pci_initchild() for details.
    150  */
    151 static ushort_t pci_command_default = PCI_COMM_ME |
    152 					PCI_COMM_MAE |
    153 					PCI_COMM_IO;
    154 
    155 /*
    156  * Internal routines in support of particular pci_ctlops.
    157  */
    158 static int pci_removechild(dev_info_t *child);
    159 static int pci_initchild(dev_info_t *child);
    160 
    161 /*
    162  * Module linkage information for the kernel.
    163  */
    164 
    165 static struct modldrv modldrv = {
    166 	&mod_driverops, 			/* Type of module */
    167 	"x86 Host to PCI nexus driver",		/* Name of module */
    168 	&pci_ops,				/* driver ops */
    169 };
    170 
    171 static struct modlinkage modlinkage = {
    172 	MODREV_1,
    173 	(void *)&modldrv,
    174 	NULL
    175 };
    176 
    177 int
    178 _init(void)
    179 {
    180 	int e;
    181 
    182 	/*
    183 	 * Initialize per-pci bus soft state pointer.
    184 	 */
    185 	e = ddi_soft_state_init(&pci_statep, sizeof (pci_state_t), 1);
    186 	if (e != 0)
    187 		return (e);
    188 
    189 	if ((e = mod_install(&modlinkage)) != 0)
    190 		ddi_soft_state_fini(&pci_statep);
    191 
    192 	return (e);
    193 }
    194 
    195 int
    196 _fini(void)
    197 {
    198 	int rc;
    199 
    200 	rc = mod_remove(&modlinkage);
    201 	if (rc != 0)
    202 		return (rc);
    203 
    204 	ddi_soft_state_fini(&pci_statep);
    205 
    206 	return (rc);
    207 }
    208 
    209 int
    210 _info(struct modinfo *modinfop)
    211 {
    212 	return (mod_info(&modlinkage, modinfop));
    213 }
    214 
    215 /*ARGSUSED*/
    216 static int
    217 pci_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
    218 {
    219 	/*
    220 	 * Use the minor number as constructed by pcihp, as the index value to
    221 	 * ddi_soft_state_zalloc.
    222 	 */
    223 	int instance = ddi_get_instance(devi);
    224 	pci_state_t *pcip = NULL;
    225 	switch (cmd) {
    226 	case DDI_ATTACH:
    227 		break;
    228 
    229 	case DDI_RESUME:
    230 		return (DDI_SUCCESS);
    231 
    232 	default:
    233 		return (DDI_FAILURE);
    234 	}
    235 
    236 	if (ddi_prop_update_string(DDI_DEV_T_NONE, devi, "device_type", "pci")
    237 	    != DDI_PROP_SUCCESS) {
    238 		cmn_err(CE_WARN, "pci:  'device_type' prop create failed");
    239 	}
    240 
    241 	if (ddi_soft_state_zalloc(pci_statep, instance) == DDI_SUCCESS) {
    242 		pcip = ddi_get_soft_state(pci_statep, instance);
    243 	}
    244 
    245 	if (pcip == NULL) {
    246 		goto bad_soft_state;
    247 	}
    248 
    249 	pcip->pci_dip = devi;
    250 	pcip->pci_soft_state = PCI_SOFT_STATE_CLOSED;
    251 
    252 	/*
    253 	 * Initialize hotplug support on this bus. At minimum
    254 	 * (for non hotplug bus) this would create ":devctl" minor
    255 	 * node to support DEVCTL_DEVICE_* and DEVCTL_BUS_* ioctls
    256 	 * to this bus.
    257 	 */
    258 	if (pcihp_init(devi) != DDI_SUCCESS) {
    259 		cmn_err(CE_WARN, "pci: Failed to setup hotplug framework");
    260 		goto bad_pcihp_init;
    261 	}
    262 
    263 	/* Second arg: initialize for pci, not pci_express */
    264 	if (pcitool_init(devi, B_FALSE) != DDI_SUCCESS) {
    265 		goto bad_pcitool_init;
    266 	}
    267 
    268 	pcip->pci_fmcap = DDI_FM_ERRCB_CAPABLE |
    269 	    DDI_FM_ACCCHK_CAPABLE | DDI_FM_DMACHK_CAPABLE;
    270 	ddi_fm_init(devi, &pcip->pci_fmcap, &pcip->pci_fm_ibc);
    271 	mutex_init(&pcip->pci_mutex, NULL, MUTEX_DRIVER, NULL);
    272 	mutex_init(&pcip->pci_err_mutex, NULL, MUTEX_DRIVER,
    273 	    (void *)pcip->pci_fm_ibc);
    274 	mutex_init(&pcip->pci_peek_poke_mutex, NULL, MUTEX_DRIVER,
    275 	    (void *)pcip->pci_fm_ibc);
    276 	if (pcip->pci_fmcap & DDI_FM_ERRCB_CAPABLE) {
    277 		pci_ereport_setup(devi);
    278 		ddi_fm_handler_register(devi, pci_fm_callback, NULL);
    279 	}
    280 
    281 	ddi_report_dev(devi);
    282 
    283 	return (DDI_SUCCESS);
    284 
    285 bad_pcitool_init:
    286 	(void) pcihp_uninit(devi);
    287 bad_pcihp_init:
    288 	ddi_soft_state_free(pci_statep, instance);
    289 bad_soft_state:
    290 	return (DDI_FAILURE);
    291 }
    292 
    293 /*ARGSUSED*/
    294 static int
    295 pci_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
    296 {
    297 	int instance = ddi_get_instance(devi);
    298 	pci_state_t *pcip;
    299 
    300 	pcip = ddi_get_soft_state(pci_statep, ddi_get_instance(devi));
    301 
    302 
    303 	switch (cmd) {
    304 	case DDI_DETACH:
    305 		if (pcip->pci_fmcap & DDI_FM_ERRCB_CAPABLE) {
    306 			ddi_fm_handler_unregister(devi);
    307 			pci_ereport_teardown(devi);
    308 		}
    309 		mutex_destroy(&pcip->pci_peek_poke_mutex);
    310 		mutex_destroy(&pcip->pci_err_mutex);
    311 		mutex_destroy(&pcip->pci_mutex);
    312 		ddi_fm_fini(devi);	/* Uninitialize pcitool support. */
    313 		pcitool_uninit(devi);
    314 
    315 		/* Uninitialize hotplug support on this bus. */
    316 		(void) pcihp_uninit(devi);
    317 
    318 		ddi_soft_state_free(pci_statep, instance);
    319 
    320 		return (DDI_SUCCESS);
    321 	case DDI_SUSPEND:
    322 		return (DDI_SUCCESS);
    323 	default:
    324 		return (DDI_FAILURE);
    325 	}
    326 }
    327 
    328 static int
    329 pci_bus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
    330 	off_t offset, off_t len, caddr_t *vaddrp)
    331 {
    332 	struct regspec reg;
    333 	ddi_map_req_t mr;
    334 	ddi_acc_hdl_t *hp;
    335 	ddi_acc_impl_t *hdlp;
    336 	pci_regspec_t pci_reg;
    337 	pci_regspec_t *pci_rp;
    338 	int 	rnumber;
    339 	int	length;
    340 	pci_acc_cfblk_t *cfp;
    341 	int	space;
    342 	pci_state_t *pcip;
    343 
    344 	mr = *mp; /* Get private copy of request */
    345 	mp = &mr;
    346 
    347 	if (mp->map_handlep != NULL) {
    348 		pcip = ddi_get_soft_state(pci_statep, ddi_get_instance(dip));
    349 		hdlp = (ddi_acc_impl_t *)(mp->map_handlep)->ah_platform_private;
    350 		hdlp->ahi_err_mutexp = &pcip->pci_err_mutex;
    351 		hdlp->ahi_peekpoke_mutexp = &pcip->pci_peek_poke_mutex;
    352 		hdlp->ahi_scan_dip = dip;
    353 		hdlp->ahi_scan = pci_peekpoke_cb;
    354 	}
    355 
    356 	/*
    357 	 * check for register number
    358 	 */
    359 	switch (mp->map_type) {
    360 	case DDI_MT_REGSPEC:
    361 		pci_reg = *(pci_regspec_t *)(mp->map_obj.rp);
    362 		pci_rp = &pci_reg;
    363 		if (pci_common_get_reg_prop(rdip, pci_rp) != DDI_SUCCESS)
    364 			return (DDI_FAILURE);
    365 		break;
    366 	case DDI_MT_RNUMBER:
    367 		rnumber = mp->map_obj.rnumber;
    368 		/*
    369 		 * get ALL "reg" properties for dip, select the one of
    370 		 * of interest. In x86, "assigned-addresses" property
    371 		 * is identical to the "reg" property, so there is no
    372 		 * need to cross check the two to determine the physical
    373 		 * address of the registers.
    374 		 * This routine still performs some validity checks to
    375 		 * make sure that everything is okay.
    376 		 */
    377 		if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, rdip,
    378 		    DDI_PROP_DONTPASS, "reg", (int **)&pci_rp,
    379 		    (uint_t *)&length) != DDI_PROP_SUCCESS)
    380 			return (DDI_FAILURE);
    381 
    382 		/*
    383 		 * validate the register number.
    384 		 */
    385 		length /= (sizeof (pci_regspec_t) / sizeof (int));
    386 		if (rnumber >= length) {
    387 			ddi_prop_free(pci_rp);
    388 			return (DDI_FAILURE);
    389 		}
    390 
    391 		/*
    392 		 * copy the required entry.
    393 		 */
    394 		pci_reg = pci_rp[rnumber];
    395 
    396 		/*
    397 		 * free the memory allocated by ddi_prop_lookup_int_array
    398 		 */
    399 		ddi_prop_free(pci_rp);
    400 
    401 		pci_rp = &pci_reg;
    402 		if (pci_common_get_reg_prop(rdip, pci_rp) != DDI_SUCCESS)
    403 			return (DDI_FAILURE);
    404 		mp->map_type = DDI_MT_REGSPEC;
    405 		break;
    406 	default:
    407 		return (DDI_ME_INVAL);
    408 	}
    409 
    410 	space = pci_rp->pci_phys_hi & PCI_REG_ADDR_M;
    411 
    412 	/*
    413 	 * check for unmap and unlock of address space
    414 	 */
    415 	if ((mp->map_op == DDI_MO_UNMAP) || (mp->map_op == DDI_MO_UNLOCK)) {
    416 		/*
    417 		 * Adjust offset and length
    418 		 * A non-zero length means override the one in the regspec.
    419 		 */
    420 		pci_rp->pci_phys_low += (uint_t)offset;
    421 		if (len != 0)
    422 			pci_rp->pci_size_low = len;
    423 
    424 		switch (space) {
    425 		case PCI_ADDR_CONFIG:
    426 			/* No work required on unmap of Config space */
    427 			return (DDI_SUCCESS);
    428 
    429 		case PCI_ADDR_IO:
    430 			reg.regspec_bustype = 1;
    431 			break;
    432 
    433 		case PCI_ADDR_MEM64:
    434 			/*
    435 			 * MEM64 requires special treatment on map, to check
    436 			 * that the device is below 4G.  On unmap, however,
    437 			 * we can assume that everything is OK... the map
    438 			 * must have succeeded.
    439 			 */
    440 			/* FALLTHROUGH */
    441 		case PCI_ADDR_MEM32:
    442 			reg.regspec_bustype = 0;
    443 			break;
    444 
    445 		default:
    446 			return (DDI_FAILURE);
    447 		}
    448 		reg.regspec_addr = pci_rp->pci_phys_low;
    449 		reg.regspec_size = pci_rp->pci_size_low;
    450 
    451 		mp->map_obj.rp = &reg;
    452 		return (ddi_map(dip, mp, (off_t)0, (off_t)0, vaddrp));
    453 
    454 	}
    455 
    456 	/* check for user mapping request - not legal for Config */
    457 	if (mp->map_op == DDI_MO_MAP_HANDLE && space == PCI_ADDR_CONFIG) {
    458 		return (DDI_FAILURE);
    459 	}
    460 
    461 	/*
    462 	 * check for config space
    463 	 * On x86, CONFIG is not mapped via MMU and there is
    464 	 * no endian-ness issues. Set the attr field in the handle to
    465 	 * indicate that the common routines to call the nexus driver.
    466 	 */
    467 	if (space == PCI_ADDR_CONFIG) {
    468 		/* Can't map config space without a handle */
    469 		hp = (ddi_acc_hdl_t *)mp->map_handlep;
    470 		if (hp == NULL)
    471 			return (DDI_FAILURE);
    472 
    473 		/* record the device address for future reference */
    474 		cfp = (pci_acc_cfblk_t *)&hp->ah_bus_private;
    475 		cfp->c_busnum = PCI_REG_BUS_G(pci_rp->pci_phys_hi);
    476 		cfp->c_devnum = PCI_REG_DEV_G(pci_rp->pci_phys_hi);
    477 		cfp->c_funcnum = PCI_REG_FUNC_G(pci_rp->pci_phys_hi);
    478 
    479 		*vaddrp = (caddr_t)offset;
    480 		return (pci_fm_acc_setup(hp, offset, len));
    481 	}
    482 
    483 	/*
    484 	 * range check
    485 	 */
    486 	if ((offset >= pci_rp->pci_size_low) ||
    487 	    (len > pci_rp->pci_size_low) ||
    488 	    (offset + len > pci_rp->pci_size_low)) {
    489 		return (DDI_FAILURE);
    490 	}
    491 
    492 	/*
    493 	 * Adjust offset and length
    494 	 * A non-zero length means override the one in the regspec.
    495 	 */
    496 	pci_rp->pci_phys_low += (uint_t)offset;
    497 	if (len != 0)
    498 		pci_rp->pci_size_low = len;
    499 
    500 	/*
    501 	 * convert the pci regsec into the generic regspec used by the
    502 	 * parent root nexus driver.
    503 	 */
    504 	switch (space) {
    505 	case PCI_ADDR_IO:
    506 		reg.regspec_bustype = 1;
    507 		break;
    508 	case PCI_ADDR_MEM64:
    509 		/*
    510 		 * We can't handle 64-bit devices that are mapped above
    511 		 * 4G or that are larger than 4G.
    512 		 */
    513 		if (pci_rp->pci_phys_mid != 0 ||
    514 		    pci_rp->pci_size_hi != 0)
    515 			return (DDI_FAILURE);
    516 		/*
    517 		 * Other than that, we can treat them as 32-bit mappings
    518 		 */
    519 		/* FALLTHROUGH */
    520 	case PCI_ADDR_MEM32:
    521 		reg.regspec_bustype = 0;
    522 		break;
    523 	default:
    524 		return (DDI_FAILURE);
    525 	}
    526 	reg.regspec_addr = pci_rp->pci_phys_low;
    527 	reg.regspec_size = pci_rp->pci_size_low;
    528 
    529 	mp->map_obj.rp = &reg;
    530 	return (ddi_map(dip, mp, (off_t)0, (off_t)0, vaddrp));
    531 }
    532 
    533 
    534 /*ARGSUSED*/
    535 static int
    536 pci_ctlops(dev_info_t *dip, dev_info_t *rdip,
    537 	ddi_ctl_enum_t ctlop, void *arg, void *result)
    538 {
    539 	pci_regspec_t *drv_regp;
    540 	uint_t	reglen;
    541 	int	rn;
    542 	int	totreg;
    543 	pci_state_t *pcip;
    544 	struct  attachspec *asp;
    545 
    546 	switch (ctlop) {
    547 	case DDI_CTLOPS_REPORTDEV:
    548 		if (rdip == (dev_info_t *)0)
    549 			return (DDI_FAILURE);
    550 		cmn_err(CE_CONT, "?PCI-device: %s@%s, %s%d\n",
    551 		    ddi_node_name(rdip), ddi_get_name_addr(rdip),
    552 		    ddi_driver_name(rdip),
    553 		    ddi_get_instance(rdip));
    554 		return (DDI_SUCCESS);
    555 
    556 	case DDI_CTLOPS_INITCHILD:
    557 		return (pci_initchild((dev_info_t *)arg));
    558 
    559 	case DDI_CTLOPS_UNINITCHILD:
    560 		return (pci_removechild((dev_info_t *)arg));
    561 
    562 	case DDI_CTLOPS_SIDDEV:
    563 		return (DDI_SUCCESS);
    564 
    565 	case DDI_CTLOPS_REGSIZE:
    566 	case DDI_CTLOPS_NREGS:
    567 		if (rdip == (dev_info_t *)0)
    568 			return (DDI_FAILURE);
    569 
    570 		*(int *)result = 0;
    571 		if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, rdip,
    572 		    DDI_PROP_DONTPASS, "reg", (int **)&drv_regp,
    573 		    &reglen) != DDI_PROP_SUCCESS) {
    574 			return (DDI_FAILURE);
    575 		}
    576 
    577 		totreg = (reglen * sizeof (int)) / sizeof (pci_regspec_t);
    578 		if (ctlop == DDI_CTLOPS_NREGS)
    579 			*(int *)result = totreg;
    580 		else if (ctlop == DDI_CTLOPS_REGSIZE) {
    581 			rn = *(int *)arg;
    582 			if (rn >= totreg) {
    583 				ddi_prop_free(drv_regp);
    584 				return (DDI_FAILURE);
    585 			}
    586 			*(off_t *)result = drv_regp[rn].pci_size_low;
    587 		}
    588 		ddi_prop_free(drv_regp);
    589 
    590 		return (DDI_SUCCESS);
    591 
    592 	case DDI_CTLOPS_POWER: {
    593 		power_req_t	*reqp = (power_req_t *)arg;
    594 		/*
    595 		 * We currently understand reporting of PCI_PM_IDLESPEED
    596 		 * capability. Everything else is passed up.
    597 		 */
    598 		if ((reqp->request_type == PMR_REPORT_PMCAP) &&
    599 		    (reqp->req.report_pmcap_req.cap ==  PCI_PM_IDLESPEED)) {
    600 
    601 			return (DDI_SUCCESS);
    602 		}
    603 		return (ddi_ctlops(dip, rdip, ctlop, arg, result));
    604 	}
    605 
    606 	case DDI_CTLOPS_PEEK:
    607 	case DDI_CTLOPS_POKE:
    608 		pcip = ddi_get_soft_state(pci_statep, ddi_get_instance(dip));
    609 		return (pci_peekpoke_check(dip, rdip, ctlop, arg, result,
    610 		    pci_common_peekpoke, &pcip->pci_err_mutex,
    611 		    &pcip->pci_peek_poke_mutex, pci_peekpoke_cb));
    612 
    613 	/* for now only X86 systems support PME wakeup from suspended state */
    614 	case DDI_CTLOPS_ATTACH:
    615 		asp = (struct attachspec *)arg;
    616 		if (asp->cmd == DDI_RESUME && asp->when == DDI_PRE)
    617 			if (pci_pre_resume(rdip) != DDI_SUCCESS)
    618 				return (DDI_FAILURE);
    619 		return (ddi_ctlops(dip, rdip, ctlop, arg, result));
    620 
    621 	case DDI_CTLOPS_DETACH:
    622 		asp = (struct attachspec *)arg;
    623 		if (asp->cmd == DDI_SUSPEND && asp->when == DDI_POST)
    624 			if (pci_post_suspend(rdip) != DDI_SUCCESS)
    625 				return (DDI_FAILURE);
    626 		return (ddi_ctlops(dip, rdip, ctlop, arg, result));
    627 
    628 	default:
    629 		return (ddi_ctlops(dip, rdip, ctlop, arg, result));
    630 	}
    631 
    632 	/* NOTREACHED */
    633 
    634 }
    635 
    636 /*
    637  * pci_intr_ops
    638  */
    639 static int
    640 pci_intr_ops(dev_info_t *pdip, dev_info_t *rdip, ddi_intr_op_t intr_op,
    641     ddi_intr_handle_impl_t *hdlp, void *result)
    642 {
    643 	return (pci_common_intr_ops(pdip, rdip, intr_op, hdlp, result));
    644 }
    645 
    646 
    647 static int
    648 pci_initchild(dev_info_t *child)
    649 {
    650 	char name[80];
    651 	ddi_acc_handle_t config_handle;
    652 	ushort_t command_preserve, command;
    653 
    654 	if (pci_common_name_child(child, name, 80) != DDI_SUCCESS) {
    655 		return (DDI_FAILURE);
    656 	}
    657 	ddi_set_name_addr(child, name);
    658 
    659 	/*
    660 	 * Pseudo nodes indicate a prototype node with per-instance
    661 	 * properties to be merged into the real h/w device node.
    662 	 * The interpretation of the unit-address is DD[,F]
    663 	 * where DD is the device id and F is the function.
    664 	 */
    665 	if (ndi_dev_is_persistent_node(child) == 0) {
    666 		extern int pci_allow_pseudo_children;
    667 
    668 		ddi_set_parent_data(child, NULL);
    669 
    670 		/*
    671 		 * Try to merge the properties from this prototype
    672 		 * node into real h/w nodes.
    673 		 */
    674 		if (ndi_merge_node(child, pci_common_name_child) ==
    675 		    DDI_SUCCESS) {
    676 			/*
    677 			 * Merged ok - return failure to remove the node.
    678 			 */
    679 			ddi_set_name_addr(child, NULL);
    680 			return (DDI_FAILURE);
    681 		}
    682 
    683 		/* workaround for ddivs to run under PCI */
    684 		if (pci_allow_pseudo_children) {
    685 			/*
    686 			 * If the "interrupts" property doesn't exist,
    687 			 * this must be the ddivs no-intr case, and it returns
    688 			 * DDI_SUCCESS instead of DDI_FAILURE.
    689 			 */
    690 			if (ddi_prop_get_int(DDI_DEV_T_ANY, child,
    691 			    DDI_PROP_DONTPASS, "interrupts", -1) == -1)
    692 				return (DDI_SUCCESS);
    693 			/*
    694 			 * Create the ddi_parent_private_data for a pseudo
    695 			 * child.
    696 			 */
    697 			pci_common_set_parent_private_data(child);
    698 			return (DDI_SUCCESS);
    699 		}
    700 
    701 		/*
    702 		 * The child was not merged into a h/w node,
    703 		 * but there's not much we can do with it other
    704 		 * than return failure to cause the node to be removed.
    705 		 */
    706 		cmn_err(CE_WARN, "!%s@%s: %s.conf properties not merged",
    707 		    ddi_get_name(child), ddi_get_name_addr(child),
    708 		    ddi_get_name(child));
    709 		ddi_set_name_addr(child, NULL);
    710 		return (DDI_NOT_WELL_FORMED);
    711 	}
    712 
    713 	if (ddi_prop_get_int(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS,
    714 	    "interrupts", -1) != -1)
    715 		pci_common_set_parent_private_data(child);
    716 	else
    717 		ddi_set_parent_data(child, NULL);
    718 
    719 	/*
    720 	 * initialize command register
    721 	 */
    722 	if (pci_config_setup(child, &config_handle) != DDI_SUCCESS)
    723 		return (DDI_FAILURE);
    724 
    725 	/*
    726 	 * Support for the "command-preserve" property.
    727 	 */
    728 	command_preserve = ddi_prop_get_int(DDI_DEV_T_ANY, child,
    729 	    DDI_PROP_DONTPASS, "command-preserve", 0);
    730 	command = pci_config_get16(config_handle, PCI_CONF_COMM);
    731 	command &= (command_preserve | PCI_COMM_BACK2BACK_ENAB);
    732 	command |= (pci_command_default & ~command_preserve);
    733 	pci_config_put16(config_handle, PCI_CONF_COMM, command);
    734 
    735 	pci_config_teardown(&config_handle);
    736 	return (DDI_SUCCESS);
    737 }
    738 
    739 static int
    740 pci_removechild(dev_info_t *dip)
    741 {
    742 	struct ddi_parent_private_data *pdptr;
    743 
    744 	if ((pdptr = ddi_get_parent_data(dip)) != NULL) {
    745 		kmem_free(pdptr, (sizeof (*pdptr) + sizeof (struct intrspec)));
    746 		ddi_set_parent_data(dip, NULL);
    747 	}
    748 	ddi_set_name_addr(dip, NULL);
    749 
    750 	/*
    751 	 * Strip the node to properly convert it back to prototype form
    752 	 */
    753 	ddi_remove_minor_node(dip, NULL);
    754 
    755 	impl_rem_dev_props(dip);
    756 
    757 	return (DDI_SUCCESS);
    758 }
    759 
    760 
    761 /*
    762  * When retrofitting this module for pci_tools, functions such as open, close,
    763  * and ioctl are now pulled into this module.  Before this, the functions in
    764  * the pcihp module were referenced directly.  Now they are called or
    765  * referenced through the pcihp cb_ops structure from functions in this module.
    766  */
    767 
    768 static int
    769 pci_open(dev_t *devp, int flags, int otyp, cred_t *credp)
    770 {
    771 	return ((pcihp_get_cb_ops())->cb_open(devp, flags, otyp, credp));
    772 }
    773 
    774 static int
    775 pci_close(dev_t dev, int flags, int otyp, cred_t *credp)
    776 {
    777 	return ((pcihp_get_cb_ops())->cb_close(dev, flags, otyp, credp));
    778 }
    779 
    780 static int
    781 pci_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, int *rvalp)
    782 {
    783 	minor_t		minor = getminor(dev);
    784 	int		instance = PCI_MINOR_NUM_TO_INSTANCE(minor);
    785 	pci_state_t	*pci_p = ddi_get_soft_state(pci_statep, instance);
    786 	int		ret = ENOTTY;
    787 
    788 	if (pci_p == NULL)
    789 		return (ENXIO);
    790 
    791 	switch (PCI_MINOR_NUM_TO_PCI_DEVNUM(minor)) {
    792 	case PCI_TOOL_REG_MINOR_NUM:
    793 	case PCI_TOOL_INTR_MINOR_NUM:
    794 		/* To handle pcitool related ioctls */
    795 		ret =  pci_common_ioctl(pci_p->pci_dip, dev, cmd, arg, mode,
    796 		    credp, rvalp);
    797 		break;
    798 	default:
    799 		/* To handle devctl and hotplug related ioctls */
    800 		ret = (pcihp_get_cb_ops())->cb_ioctl(dev, cmd, arg, mode,
    801 		    credp, rvalp);
    802 		break;
    803 	}
    804 
    805 	return (ret);
    806 }
    807 
    808 
    809 static int
    810 pci_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op,
    811 	int flags, char *name, caddr_t valuep, int *lengthp)
    812 {
    813 	return ((pcihp_get_cb_ops())->cb_prop_op(dev, dip, prop_op, flags,
    814 	    name, valuep, lengthp));
    815 }
    816 
    817 static int
    818 pci_info(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
    819 {
    820 	return (pcihp_info(dip, cmd, arg, result));
    821 }
    822 
    823 void pci_peekpoke_cb(dev_info_t *dip, ddi_fm_error_t *derr) {
    824 	(void) pci_ereport_post(dip, derr, NULL);
    825 }
    826 
    827 /*ARGSUSED*/
    828 static int
    829 pci_fm_init(dev_info_t *dip, dev_info_t *tdip, int cap,
    830     ddi_iblock_cookie_t *ibc)
    831 {
    832 	pci_state_t  *pcip = ddi_get_soft_state(pci_statep,
    833 	    ddi_get_instance(dip));
    834 
    835 	ASSERT(ibc != NULL);
    836 	*ibc = pcip->pci_fm_ibc;
    837 
    838 	return (pcip->pci_fmcap);
    839 }
    840 
    841 /*ARGSUSED*/
    842 static int
    843 pci_fm_callback(dev_info_t *dip, ddi_fm_error_t *derr, const void *no_used)
    844 {
    845 	pci_state_t  *pcip = ddi_get_soft_state(pci_statep,
    846 	    ddi_get_instance(dip));
    847 
    848 	mutex_enter(&pcip->pci_err_mutex);
    849 	pci_ereport_post(dip, derr, NULL);
    850 	mutex_exit(&pcip->pci_err_mutex);
    851 	return (derr->fme_status);
    852 }
    853