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