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