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