xref: /titanic_50/usr/src/uts/i86pc/io/pci/pci.c (revision 108322fb1c3ed341aba9c80c9774df0ed9e35768)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  *	Host to PCI local bus driver
31  */
32 
33 #include <sys/conf.h>
34 #include <sys/kmem.h>
35 #include <sys/debug.h>
36 #include <sys/modctl.h>
37 #include <sys/autoconf.h>
38 #include <sys/ddi_impldefs.h>
39 #include <sys/ddi_subrdefs.h>
40 #include <sys/pci.h>
41 #include <sys/pci_impl.h>
42 #include <sys/ddi.h>
43 #include <sys/sunddi.h>
44 #include <sys/sunndi.h>
45 #include <sys/hotplug/pci/pcihp.h>
46 #include <sys/pci_cfgspace.h>
47 #include <sys/avintr.h>
48 #include <sys/psm.h>
49 #include <sys/pci_intr_lib.h>
50 #include <sys/policy.h>
51 #include <sys/pci_tools.h>
52 #include <sys/pci_tools_var.h>
53 #include "pci_var.h"
54 
55 /* Save minimal state. */
56 void *pci_statep;
57 
58 /*
59  * Bus Operation functions
60  */
61 static int	pci_bus_map(dev_info_t *, dev_info_t *, ddi_map_req_t *,
62 		    off_t, off_t, caddr_t *);
63 static int	pci_ctlops(dev_info_t *, dev_info_t *, ddi_ctl_enum_t,
64 		    void *, void *);
65 static int	pci_intr_ops(dev_info_t *, dev_info_t *, ddi_intr_op_t,
66 		    ddi_intr_handle_impl_t *, void *);
67 static int	pci_get_priority(dev_info_t *, int, int *);
68 static int	pci_get_nintrs(dev_info_t *, int, int *);
69 static int	pci_enable_intr(dev_info_t *, dev_info_t *,
70 		    ddi_intr_handle_impl_t *, uint32_t);
71 static void	pci_disable_intr(dev_info_t *, dev_info_t *,
72 		    ddi_intr_handle_impl_t *, uint32_t);
73 
74 /* Extern decalrations */
75 extern int	(*psm_intr_ops)(dev_info_t *, ddi_intr_handle_impl_t *,
76 		    psm_intr_op_t, int *);
77 
78 struct bus_ops pci_bus_ops = {
79 	BUSO_REV,
80 	pci_bus_map,
81 	NULL,
82 	NULL,
83 	NULL,
84 	i_ddi_map_fault,
85 	ddi_dma_map,
86 	ddi_dma_allochdl,
87 	ddi_dma_freehdl,
88 	ddi_dma_bindhdl,
89 	ddi_dma_unbindhdl,
90 	ddi_dma_flush,
91 	ddi_dma_win,
92 	ddi_dma_mctl,
93 	pci_ctlops,
94 	ddi_bus_prop_op,
95 	0,		/* (*bus_get_eventcookie)();	*/
96 	0,		/* (*bus_add_eventcall)();	*/
97 	0,		/* (*bus_remove_eventcall)();	*/
98 	0,		/* (*bus_post_event)();		*/
99 	0,		/* (*bus_intr_ctl)(); */
100 	0,		/* (*bus_config)(); */
101 	0,		/* (*bus_unconfig)(); */
102 	NULL,		/* (*bus_fm_init)(); */
103 	NULL,		/* (*bus_fm_fini)(); */
104 	NULL,		/* (*bus_fm_access_enter)(); */
105 	NULL,		/* (*bus_fm_access_exit)(); */
106 	NULL,		/* (*bus_power)(); */
107 	pci_intr_ops	/* (*bus_intr_op)(); */
108 };
109 
110 static int pci_open(dev_t *devp, int flags, int otyp, cred_t *credp);
111 static int pci_close(dev_t dev, int flags, int otyp, cred_t *credp);
112 static int pci_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
113     int *rvalp);
114 static int pci_prop_op(dev_t dev, dev_info_t *devi, ddi_prop_op_t prop_op,
115     int flags, char *name, caddr_t valuep, int *lengthp);
116 
117 /*
118  * One goal here is to leverage off of the pcihp.c source without making
119  * changes to it.  Call into it's cb_ops directly if needed, piggybacking
120  * anything else needed by the pci_tools.c module.  Only pci_tools and pcihp
121  * will be opening PCI nexus driver file descriptors.
122  */
123 
124 struct cb_ops pci_cb_ops = {
125 	pci_open,			/* open */
126 	pci_close,			/* close */
127 	nodev,				/* strategy */
128 	nodev,				/* print */
129 	nodev,				/* dump */
130 	nodev,				/* read */
131 	nodev,				/* write */
132 	pci_ioctl,			/* ioctl */
133 	nodev,				/* devmap */
134 	nodev,				/* mmap */
135 	nodev,				/* segmap */
136 	nochpoll,			/* poll */
137 	pci_prop_op,			/* cb_prop_op */
138 	NULL,				/* streamtab */
139 	D_NEW | D_MP | D_HOTPLUG,	/* Driver compatibility flag */
140 	CB_REV,				/* rev */
141 	nodev,				/* int (*cb_aread)() */
142 	nodev				/* int (*cb_awrite)() */
143 };
144 
145 /*
146  * Device Node Operation functions
147  */
148 static int pci_info(dev_info_t *devi, ddi_info_cmd_t cmd, void *arg,
149     void **result);
150 static int pci_attach(dev_info_t *devi, ddi_attach_cmd_t cmd);
151 static int pci_detach(dev_info_t *devi, ddi_detach_cmd_t cmd);
152 
153 struct dev_ops pci_ops = {
154 	DEVO_REV,		/* devo_rev */
155 	0,			/* refcnt  */
156 	pci_info,		/* info */
157 	nulldev,		/* identify */
158 	nulldev,		/* probe */
159 	pci_attach,		/* attach */
160 	pci_detach,		/* detach */
161 	nulldev,		/* reset */
162 	&pci_cb_ops,		/* driver operations */
163 	&pci_bus_ops		/* bus operations */
164 };
165 
166 /*
167  * This variable controls the default setting of the command register
168  * for pci devices.  See pci_initchild() for details.
169  */
170 static ushort_t pci_command_default = PCI_COMM_ME |
171 					PCI_COMM_MAE |
172 					PCI_COMM_IO;
173 
174 /*
175  * Internal routines in support of particular pci_ctlops.
176  */
177 static int pci_removechild(dev_info_t *child);
178 static int pci_initchild(dev_info_t *child);
179 
180 /*
181  * Miscellaneous internal functions
182  */
183 static int pci_get_reg_prop(dev_info_t *dip, pci_regspec_t *pci_rp);
184 
185 /*
186  * These are the access routines.  The pci_bus_map sets the handle
187  * to point to these.
188  */
189 static uint8_t pci_config_rd8(ddi_acc_impl_t *hdlp, uint8_t *addr);
190 static uint16_t pci_config_rd16(ddi_acc_impl_t *hdlp, uint16_t *addr);
191 static uint32_t pci_config_rd32(ddi_acc_impl_t *hdlp, uint32_t *addr);
192 static uint64_t pci_config_rd64(ddi_acc_impl_t *hdlp, uint64_t *addr);
193 
194 static void pci_config_wr8(ddi_acc_impl_t *hdlp, uint8_t *addr,
195 				uint8_t value);
196 static void pci_config_wr16(ddi_acc_impl_t *hdlp, uint16_t *addr,
197 				uint16_t value);
198 static void pci_config_wr32(ddi_acc_impl_t *hdlp, uint32_t *addr,
199 				uint32_t value);
200 static void pci_config_wr64(ddi_acc_impl_t *hdlp, uint64_t *addr,
201 				uint64_t value);
202 
203 static void pci_config_rep_rd8(ddi_acc_impl_t *hdlp, uint8_t *host_addr,
204 	uint8_t *dev_addr, size_t repcount, uint_t flags);
205 static void pci_config_rep_rd16(ddi_acc_impl_t *hdlp, uint16_t *host_addr,
206 	uint16_t *dev_addr, size_t repcount, uint_t flags);
207 static void pci_config_rep_rd32(ddi_acc_impl_t *hdlp, uint32_t *host_addr,
208 	uint32_t *dev_addr, size_t repcount, uint_t flags);
209 static void pci_config_rep_rd64(ddi_acc_impl_t *hdlp, uint64_t *host_addr,
210 	uint64_t *dev_addr, size_t repcount, uint_t flags);
211 
212 static void pci_config_rep_wr8(ddi_acc_impl_t *hdlp, uint8_t *host_addr,
213 	uint8_t *dev_addr, size_t repcount, uint_t flags);
214 static void pci_config_rep_wr16(ddi_acc_impl_t *hdlp, uint16_t *host_addr,
215 	uint16_t *dev_addr, size_t repcount, uint_t flags);
216 static void pci_config_rep_wr32(ddi_acc_impl_t *hdlp, uint32_t *host_addr,
217 	uint32_t *dev_addr, size_t repcount, uint_t flags);
218 static void pci_config_rep_wr64(ddi_acc_impl_t *hdlp, uint64_t *host_addr,
219 	uint64_t *dev_addr, size_t repcount, uint_t flags);
220 
221 /*
222  * Module linkage information for the kernel.
223  */
224 
225 static struct modldrv modldrv = {
226 	&mod_driverops, /* Type of module */
227 	"host to PCI nexus driver %I%",
228 	&pci_ops,	/* driver ops */
229 };
230 
231 static struct modlinkage modlinkage = {
232 	MODREV_1,
233 	(void *)&modldrv,
234 	NULL
235 };
236 
237 int
238 _init(void)
239 {
240 	int e;
241 
242 	/*
243 	 * Initialize per-pci bus soft state pointer.
244 	 */
245 	e = ddi_soft_state_init(&pci_statep, sizeof (pci_state_t), 1);
246 	if (e != 0)
247 		return (e);
248 
249 	if ((e = mod_install(&modlinkage)) != 0)
250 		ddi_soft_state_fini(&pci_statep);
251 
252 	return (e);
253 }
254 
255 int
256 _fini(void)
257 {
258 	int rc;
259 
260 	rc = mod_remove(&modlinkage);
261 	if (rc != 0)
262 		return (rc);
263 
264 	ddi_soft_state_fini(&pci_statep);
265 
266 	return (rc);
267 }
268 
269 int
270 _info(struct modinfo *modinfop)
271 {
272 	return (mod_info(&modlinkage, modinfop));
273 }
274 
275 /*ARGSUSED*/
276 static int
277 pci_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
278 {
279 	/*
280 	 * Use the minor number as constructed by pcihp, as the index value to
281 	 * ddi_soft_state_zalloc.
282 	 */
283 	int instance = ddi_get_instance(devi);
284 	pci_state_t *pcip = NULL;
285 
286 	if (ddi_prop_update_string(DDI_DEV_T_NONE, devi, "device_type", "pci")
287 	    != DDI_PROP_SUCCESS) {
288 		cmn_err(CE_WARN, "pci:  'device_type' prop create failed");
289 	}
290 
291 	if (ddi_soft_state_zalloc(pci_statep, instance) == DDI_SUCCESS) {
292 		pcip = ddi_get_soft_state(pci_statep, instance);
293 	}
294 
295 	if (pcip == NULL) {
296 		goto bad_soft_state;
297 	}
298 
299 	pcip->pci_dip = devi;
300 
301 	/*
302 	 * Initialize hotplug support on this bus. At minimum
303 	 * (for non hotplug bus) this would create ":devctl" minor
304 	 * node to support DEVCTL_DEVICE_* and DEVCTL_BUS_* ioctls
305 	 * to this bus.
306 	 */
307 	if (pcihp_init(devi) != DDI_SUCCESS) {
308 		cmn_err(CE_WARN, "pci: Failed to setup hotplug framework");
309 		goto bad_pcihp_init;
310 	}
311 
312 	if (pcitool_init(devi) != DDI_SUCCESS) {
313 		goto bad_pcitool_init;
314 	}
315 
316 	ddi_report_dev(devi);
317 
318 	return (DDI_SUCCESS);
319 
320 bad_pcitool_init:
321 	(void) pcihp_uninit(devi);
322 bad_pcihp_init:
323 	ddi_soft_state_free(pci_statep, instance);
324 bad_soft_state:
325 	return (DDI_FAILURE);
326 }
327 
328 /*ARGSUSED*/
329 static int
330 pci_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
331 {
332 	/* Uninitialize pcitool support. */
333 	pcitool_uninit(devi);
334 
335 	/* Uninitialize hotplug support on this bus. */
336 	(void) pcihp_uninit(devi);
337 
338 	ddi_soft_state_free(pci_statep, DIP_TO_MINOR(devi));
339 
340 	return (DDI_SUCCESS);
341 }
342 
343 static int
344 pci_get_reg_prop(dev_info_t *dip, pci_regspec_t *pci_rp)
345 {
346 	pci_regspec_t *assigned_addr;
347 	int	assigned_addr_len;
348 	uint_t 	phys_hi;
349 	int	i;
350 	int 	rc;
351 	int 	number;
352 
353 	phys_hi = pci_rp->pci_phys_hi;
354 	if (((phys_hi & PCI_REG_ADDR_M) == PCI_ADDR_CONFIG) ||
355 		(phys_hi & PCI_RELOCAT_B))
356 		return (DDI_SUCCESS);
357 
358 	/*
359 	 * the "reg" property specifies relocatable, get and interpret the
360 	 * "assigned-addresses" property.
361 	 */
362 	rc = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip,
363 		DDI_PROP_DONTPASS, "assigned-addresses",
364 		(int **)&assigned_addr, (uint_t *)&assigned_addr_len);
365 	if (rc != DDI_PROP_SUCCESS)
366 		return (DDI_FAILURE);
367 
368 	/*
369 	 * Scan the "assigned-addresses" for one that matches the specified
370 	 * "reg" property entry.
371 	 */
372 	phys_hi &= PCI_CONF_ADDR_MASK;
373 	number = assigned_addr_len / (sizeof (pci_regspec_t) / sizeof (int));
374 	for (i = 0; i < number; i++) {
375 		if ((assigned_addr[i].pci_phys_hi & PCI_CONF_ADDR_MASK) ==
376 				phys_hi) {
377 			pci_rp->pci_phys_mid = assigned_addr[i].pci_phys_mid;
378 			pci_rp->pci_phys_low = assigned_addr[i].pci_phys_low;
379 			ddi_prop_free(assigned_addr);
380 			return (DDI_SUCCESS);
381 		}
382 	}
383 
384 	ddi_prop_free(assigned_addr);
385 	return (DDI_FAILURE);
386 }
387 
388 static int
389 pci_bus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
390 	off_t offset, off_t len, caddr_t *vaddrp)
391 {
392 	struct regspec reg;
393 	ddi_map_req_t mr;
394 	ddi_acc_hdl_t *hp;
395 	ddi_acc_impl_t *ap;
396 	pci_regspec_t pci_reg;
397 	pci_regspec_t *pci_rp;
398 	int 	rnumber;
399 	int	length;
400 	int	rc;
401 	pci_acc_cfblk_t *cfp;
402 	int	space;
403 
404 
405 	mr = *mp; /* Get private copy of request */
406 	mp = &mr;
407 
408 	/*
409 	 * check for register number
410 	 */
411 	switch (mp->map_type) {
412 	case DDI_MT_REGSPEC:
413 		pci_reg = *(pci_regspec_t *)(mp->map_obj.rp);
414 		pci_rp = &pci_reg;
415 		if (pci_get_reg_prop(rdip, pci_rp) != DDI_SUCCESS)
416 			return (DDI_FAILURE);
417 		break;
418 	case DDI_MT_RNUMBER:
419 		rnumber = mp->map_obj.rnumber;
420 		/*
421 		 * get ALL "reg" properties for dip, select the one of
422 		 * of interest. In x86, "assigned-addresses" property
423 		 * is identical to the "reg" property, so there is no
424 		 * need to cross check the two to determine the physical
425 		 * address of the registers.
426 		 * This routine still performs some validity checks to
427 		 * make sure that everything is okay.
428 		 */
429 		rc = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, rdip,
430 			DDI_PROP_DONTPASS, "reg", (int **)&pci_rp,
431 			(uint_t *)&length);
432 		if (rc != DDI_PROP_SUCCESS) {
433 			return (DDI_FAILURE);
434 		}
435 
436 		/*
437 		 * validate the register number.
438 		 */
439 		length /= (sizeof (pci_regspec_t) / sizeof (int));
440 		if (rnumber >= length) {
441 			ddi_prop_free(pci_rp);
442 			return (DDI_FAILURE);
443 		}
444 
445 		/*
446 		 * copy the required entry.
447 		 */
448 		pci_reg = pci_rp[rnumber];
449 
450 		/*
451 		 * free the memory allocated by ddi_prop_lookup_int_array
452 		 */
453 		ddi_prop_free(pci_rp);
454 
455 		pci_rp = &pci_reg;
456 		if (pci_get_reg_prop(rdip, pci_rp) != DDI_SUCCESS)
457 			return (DDI_FAILURE);
458 		mp->map_type = DDI_MT_REGSPEC;
459 		break;
460 	default:
461 		return (DDI_ME_INVAL);
462 	}
463 
464 	space = pci_rp->pci_phys_hi & PCI_REG_ADDR_M;
465 
466 	/*
467 	 * check for unmap and unlock of address space
468 	 */
469 	if ((mp->map_op == DDI_MO_UNMAP) || (mp->map_op == DDI_MO_UNLOCK)) {
470 		/*
471 		 * Adjust offset and length
472 		 * A non-zero length means override the one in the regspec.
473 		 */
474 		pci_rp->pci_phys_low += (uint_t)offset;
475 		if (len != 0)
476 			pci_rp->pci_size_low = len;
477 
478 		switch (space) {
479 		case PCI_ADDR_CONFIG:
480 			/* No work required on unmap of Config space */
481 			return (DDI_SUCCESS);
482 
483 		case PCI_ADDR_IO:
484 			reg.regspec_bustype = 1;
485 			break;
486 
487 		case PCI_ADDR_MEM64:
488 			/*
489 			 * MEM64 requires special treatment on map, to check
490 			 * that the device is below 4G.  On unmap, however,
491 			 * we can assume that everything is OK... the map
492 			 * must have succeeded.
493 			 */
494 			/* FALLTHROUGH */
495 		case PCI_ADDR_MEM32:
496 			reg.regspec_bustype = 0;
497 			break;
498 
499 		default:
500 			return (DDI_FAILURE);
501 		}
502 		reg.regspec_addr = pci_rp->pci_phys_low;
503 		reg.regspec_size = pci_rp->pci_size_low;
504 
505 		mp->map_obj.rp = &reg;
506 		return (ddi_map(dip, mp, (off_t)0, (off_t)0, vaddrp));
507 
508 	}
509 
510 	/* check for user mapping request - not legal for Config */
511 	if (mp->map_op == DDI_MO_MAP_HANDLE && space == PCI_ADDR_CONFIG) {
512 		return (DDI_FAILURE);
513 	}
514 
515 	/*
516 	 * check for config space
517 	 * On x86, CONFIG is not mapped via MMU and there is
518 	 * no endian-ness issues. Set the attr field in the handle to
519 	 * indicate that the common routines to call the nexus driver.
520 	 */
521 	if (space == PCI_ADDR_CONFIG) {
522 		hp = (ddi_acc_hdl_t *)mp->map_handlep;
523 
524 		if (hp == NULL) {
525 			/* Can't map config space without a handle */
526 			return (DDI_FAILURE);
527 		}
528 
529 		ap = (ddi_acc_impl_t *)hp->ah_platform_private;
530 
531 		/* endian-ness check */
532 		if (hp->ah_acc.devacc_attr_endian_flags == DDI_STRUCTURE_BE_ACC)
533 			return (DDI_FAILURE);
534 
535 		/*
536 		 * range check
537 		 */
538 		if ((offset >= 256) || (len > 256) || (offset + len > 256))
539 			return (DDI_FAILURE);
540 		*vaddrp = (caddr_t)offset;
541 
542 		ap->ahi_acc_attr |= DDI_ACCATTR_CONFIG_SPACE;
543 		ap->ahi_put8 = pci_config_wr8;
544 		ap->ahi_get8 = pci_config_rd8;
545 		ap->ahi_put64 = pci_config_wr64;
546 		ap->ahi_get64 = pci_config_rd64;
547 		ap->ahi_rep_put8 = pci_config_rep_wr8;
548 		ap->ahi_rep_get8 = pci_config_rep_rd8;
549 		ap->ahi_rep_put64 = pci_config_rep_wr64;
550 		ap->ahi_rep_get64 = pci_config_rep_rd64;
551 		ap->ahi_get16 = pci_config_rd16;
552 		ap->ahi_get32 = pci_config_rd32;
553 		ap->ahi_put16 = pci_config_wr16;
554 		ap->ahi_put32 = pci_config_wr32;
555 		ap->ahi_rep_get16 = pci_config_rep_rd16;
556 		ap->ahi_rep_get32 = pci_config_rep_rd32;
557 		ap->ahi_rep_put16 = pci_config_rep_wr16;
558 		ap->ahi_rep_put32 = pci_config_rep_wr32;
559 
560 		/* Initialize to default check/notify functions */
561 		ap->ahi_fault_check = i_ddi_acc_fault_check;
562 		ap->ahi_fault_notify = i_ddi_acc_fault_notify;
563 		ap->ahi_fault = 0;
564 		impl_acc_err_init(hp);
565 
566 		/* record the device address for future reference */
567 		cfp = (pci_acc_cfblk_t *)&hp->ah_bus_private;
568 		cfp->c_busnum = PCI_REG_BUS_G(pci_rp->pci_phys_hi);
569 		cfp->c_devnum = PCI_REG_DEV_G(pci_rp->pci_phys_hi);
570 		cfp->c_funcnum = PCI_REG_FUNC_G(pci_rp->pci_phys_hi);
571 
572 		return (DDI_SUCCESS);
573 	}
574 
575 	/*
576 	 * range check
577 	 */
578 	if ((offset >= pci_rp->pci_size_low) ||
579 	    (len > pci_rp->pci_size_low) ||
580 	    (offset + len > pci_rp->pci_size_low)) {
581 		return (DDI_FAILURE);
582 	}
583 
584 	/*
585 	 * Adjust offset and length
586 	 * A non-zero length means override the one in the regspec.
587 	 */
588 	pci_rp->pci_phys_low += (uint_t)offset;
589 	if (len != 0)
590 		pci_rp->pci_size_low = len;
591 
592 	/*
593 	 * convert the pci regsec into the generic regspec used by the
594 	 * parent root nexus driver.
595 	 */
596 	switch (space) {
597 	case PCI_ADDR_IO:
598 		reg.regspec_bustype = 1;
599 		break;
600 	case PCI_ADDR_MEM64:
601 		/*
602 		 * We can't handle 64-bit devices that are mapped above
603 		 * 4G or that are larger than 4G.
604 		 */
605 		if (pci_rp->pci_phys_mid != 0 ||
606 		    pci_rp->pci_size_hi != 0)
607 			return (DDI_FAILURE);
608 		/*
609 		 * Other than that, we can treat them as 32-bit mappings
610 		 */
611 		/* FALLTHROUGH */
612 	case PCI_ADDR_MEM32:
613 		reg.regspec_bustype = 0;
614 		break;
615 	default:
616 		return (DDI_FAILURE);
617 	}
618 	reg.regspec_addr = pci_rp->pci_phys_low;
619 	reg.regspec_size = pci_rp->pci_size_low;
620 
621 	mp->map_obj.rp = &reg;
622 	return (ddi_map(dip, mp, (off_t)0, (off_t)0, vaddrp));
623 }
624 
625 
626 /*
627  * pci_get_priority:
628  *	Figure out the priority of the device
629  */
630 static int
631 pci_get_priority(dev_info_t *dip, int inum, int *pri)
632 {
633 	struct intrspec *ispec;
634 
635 	DDI_INTR_NEXDBG((CE_CONT, "pci_get_priority: dip = 0x%p\n",
636 	    (void *)dip));
637 
638 	if ((ispec = (struct intrspec *)pci_intx_get_ispec(dip, dip, inum)) ==
639 	    NULL)
640 		return (DDI_FAILURE);
641 
642 	*pri = ispec->intrspec_pri;
643 
644 	return (DDI_SUCCESS);
645 }
646 
647 
648 /*
649  * pci_get_nintrs:
650  *	Figure out how many interrupts the device supports
651  */
652 static int
653 pci_get_nintrs(dev_info_t *dip, int type, int *nintrs)
654 {
655 	int	ret;
656 
657 	*nintrs = 0;
658 
659 	if (DDI_INTR_IS_MSI_OR_MSIX(type))
660 		ret = pci_msi_get_nintrs(dip, type, nintrs);
661 	else {
662 		ret = DDI_FAILURE;
663 		if (ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
664 		    "interrupts", -1) != -1) {
665 			*nintrs = 1;
666 			ret = DDI_SUCCESS;
667 		}
668 	}
669 
670 	return (ret);
671 }
672 
673 
674 /*
675  * pci_intr_ops: bus_intr_op() function for interrupt support
676  */
677 /* ARGSUSED */
678 static int
679 pci_intr_ops(dev_info_t *pdip, dev_info_t *rdip, ddi_intr_op_t intr_op,
680 	ddi_intr_handle_impl_t *hdlp, void *result)
681 {
682 	int			priority = 0;
683 	int			psm_status = 0;
684 	int			pci_status = 0;
685 	int			pci_rval, psm_rval = PSM_FAILURE;
686 	int			types = 0;
687 	int			i, j;
688 	int			behavior;
689 	ddi_intrspec_t		isp;
690 	struct intrspec		*ispec;
691 	ddi_intr_handle_impl_t	tmp_hdl;
692 	ddi_intr_msix_t		*msix_p;
693 
694 	DDI_INTR_NEXDBG((CE_CONT,
695 	    "pci_intr_ops: pdip 0x%p, rdip 0x%p, op %x handle 0x%p\n",
696 	    (void *)pdip, (void *)rdip, intr_op, (void *)hdlp));
697 
698 	/* Process the request */
699 	switch (intr_op) {
700 	case DDI_INTROP_SUPPORTED_TYPES:
701 		/* Fixed supported by default */
702 		*(int *)result = DDI_INTR_TYPE_FIXED;
703 
704 		/* Figure out if MSI or MSI-X is supported? */
705 		if (pci_msi_get_supported_type(rdip, &types) != DDI_SUCCESS)
706 			return (DDI_SUCCESS);
707 
708 		if (psm_intr_ops != NULL) {
709 			/* MSI or MSI-X is supported, OR it in */
710 			*(int *)result |= types;
711 
712 			tmp_hdl.ih_type = *(int *)result;
713 			(void) (*psm_intr_ops)(rdip, &tmp_hdl,
714 			    PSM_INTR_OP_CHECK_MSI, result);
715 			DDI_INTR_NEXDBG((CE_CONT, "pci_intr_ops: rdip: 0x%p "
716 			    "supported types: 0x%x\n", (void *)rdip,
717 			    *(int *)result));
718 		}
719 		break;
720 	case DDI_INTROP_NINTRS:
721 		if (pci_get_nintrs(rdip, hdlp->ih_type, result) != DDI_SUCCESS)
722 			return (DDI_FAILURE);
723 		break;
724 	case DDI_INTROP_ALLOC:
725 		/*
726 		 * MSI or MSIX (figure out number of vectors available)
727 		 * FIXED interrupts: just return available interrupts
728 		 */
729 		if (DDI_INTR_IS_MSI_OR_MSIX(hdlp->ih_type) &&
730 		    (psm_intr_ops != NULL) &&
731 		    (pci_get_priority(rdip, hdlp->ih_inum,
732 		    &priority) == DDI_SUCCESS)) {
733 			hdlp->ih_pri = priority;
734 			behavior = hdlp->ih_scratch2;
735 			(void) (*psm_intr_ops)(rdip, hdlp,
736 			    PSM_INTR_OP_ALLOC_VECTORS, result);
737 
738 			/* verify behavior flag and take appropriate action */
739 			if ((behavior == DDI_INTR_ALLOC_STRICT) &&
740 			    (*(int *)result < hdlp->ih_scratch1)) {
741 				DDI_INTR_NEXDBG((CE_CONT, "pci_intr_ops: "
742 				    "behavior %x, couldn't get enough intrs\n",
743 				    behavior));
744 				hdlp->ih_scratch1 = *(int *)result;
745 				(void) (*psm_intr_ops)(rdip, hdlp,
746 				    PSM_INTR_OP_FREE_VECTORS, NULL);
747 				return (DDI_EAGAIN);
748 			}
749 
750 			if (hdlp->ih_type == DDI_INTR_TYPE_MSIX) {
751 				if (!(msix_p = i_ddi_get_msix(hdlp->ih_dip))) {
752 					msix_p = pci_msix_init(hdlp->ih_dip);
753 					if (msix_p)
754 						i_ddi_set_msix(hdlp->ih_dip,
755 						    msix_p);
756 				}
757 				msix_p->msix_intrs_in_use += *(int *)result;
758 			}
759 
760 		} else if (hdlp->ih_type == DDI_INTR_TYPE_FIXED) {
761 			/* Figure out if this device supports MASKING */
762 			pci_rval = pci_intx_get_cap(rdip, &pci_status);
763 			if (pci_rval == DDI_SUCCESS && pci_status)
764 				hdlp->ih_cap |= pci_status;
765 			*(int *)result = 1;	/* DDI_INTR_TYPE_FIXED */
766 		} else
767 			return (DDI_FAILURE);
768 		break;
769 	case DDI_INTROP_FREE:
770 		if (DDI_INTR_IS_MSI_OR_MSIX(hdlp->ih_type) &&
771 		    (psm_intr_ops != NULL)) {
772 			(void) (*psm_intr_ops)(rdip, hdlp,
773 			    PSM_INTR_OP_FREE_VECTORS, NULL);
774 
775 			if (hdlp->ih_type == DDI_INTR_TYPE_MSIX) {
776 				msix_p = i_ddi_get_msix(hdlp->ih_dip);
777 				if (msix_p &&
778 				    --msix_p->msix_intrs_in_use == 0) {
779 					pci_msix_fini(msix_p);
780 					i_ddi_set_msix(hdlp->ih_dip, NULL);
781 				}
782 			}
783 		}
784 		break;
785 	case DDI_INTROP_GETPRI:
786 		if (pci_get_priority(rdip, hdlp->ih_inum, &priority) !=
787 		    DDI_SUCCESS)	/* Get the priority */
788 			return (DDI_FAILURE);
789 		DDI_INTR_NEXDBG((CE_CONT, "pci_intr_ops: priority = 0x%x\n",
790 		    priority));
791 		*(int *)result = priority;
792 		break;
793 	case DDI_INTROP_SETPRI:
794 		/* Validate the interrupt priority passed */
795 		if (*(int *)result > LOCK_LEVEL)
796 			return (DDI_FAILURE);
797 
798 		/* Ensure that PSM is all initialized */
799 		if (psm_intr_ops == NULL)
800 			return (DDI_FAILURE);
801 
802 		/* Change the priority */
803 		if ((*psm_intr_ops)(rdip, hdlp, PSM_INTR_OP_SET_PRI, result) ==
804 		    PSM_FAILURE)
805 			return (DDI_FAILURE);
806 
807 		/* update ispec */
808 		isp = pci_intx_get_ispec(pdip, rdip, (int)hdlp->ih_inum);
809 		ispec = (struct intrspec *)isp;
810 		ispec->intrspec_pri = *(int *)result;
811 		break;
812 	case DDI_INTROP_ADDISR:
813 		/* update ispec */
814 		isp = pci_intx_get_ispec(pdip, rdip, (int)hdlp->ih_inum);
815 		ispec = (struct intrspec *)isp;
816 		ispec->intrspec_func = hdlp->ih_cb_func;
817 		break;
818 	case DDI_INTROP_REMISR:
819 		/* Get the interrupt structure pointer */
820 		isp = pci_intx_get_ispec(pdip, rdip, (int)hdlp->ih_inum);
821 		ispec = (struct intrspec *)isp;
822 		ispec->intrspec_func = (uint_t (*)()) 0;
823 		break;
824 	case DDI_INTROP_GETCAP:
825 		/*
826 		 * First check the config space and/or
827 		 * MSI capability register(s)
828 		 */
829 		if (DDI_INTR_IS_MSI_OR_MSIX(hdlp->ih_type))
830 			pci_rval = pci_msi_get_cap(rdip, hdlp->ih_type,
831 			    &pci_status);
832 		else if (hdlp->ih_type == DDI_INTR_TYPE_FIXED)
833 			pci_rval = pci_intx_get_cap(rdip, &pci_status);
834 
835 		/* next check with pcplusmp */
836 		if (psm_intr_ops != NULL)
837 			psm_rval = (*psm_intr_ops)(rdip, hdlp,
838 			    PSM_INTR_OP_GET_CAP, &psm_status);
839 
840 		DDI_INTR_NEXDBG((CE_CONT, "pci: GETCAP returned psm_rval = %x, "
841 		    "psm_status = %x, pci_rval = %x, pci_status = %x\n",
842 		    psm_rval, psm_status, pci_rval, pci_status));
843 
844 		if (psm_rval == PSM_FAILURE && pci_rval == DDI_FAILURE) {
845 			*(int *)result = 0;
846 			return (DDI_FAILURE);
847 		}
848 
849 		if (psm_rval == PSM_SUCCESS)
850 			*(int *)result = psm_status;
851 
852 		if (pci_rval == DDI_SUCCESS)
853 			*(int *)result |= pci_status;
854 
855 		DDI_INTR_NEXDBG((CE_CONT, "pci: GETCAP returned = %x\n",
856 		    *(int *)result));
857 		break;
858 	case DDI_INTROP_SETCAP:
859 		DDI_INTR_NEXDBG((CE_CONT, "pci_intr_ops: SETCAP cap=0x%x\n",
860 		    *(int *)result));
861 		if (psm_intr_ops == NULL)
862 			return (DDI_FAILURE);
863 
864 		if ((*psm_intr_ops)(rdip, hdlp, PSM_INTR_OP_SET_CAP, result)) {
865 			DDI_INTR_NEXDBG((CE_CONT, "GETCAP: psm_intr_ops"
866 			    " returned failure\n"));
867 			return (DDI_FAILURE);
868 		}
869 		break;
870 	case DDI_INTROP_ENABLE:
871 		DDI_INTR_NEXDBG((CE_CONT, "pci_intr_ops: ENABLE\n"));
872 		if (psm_intr_ops == NULL)
873 			return (DDI_FAILURE);
874 
875 		if (pci_enable_intr(pdip, rdip, hdlp, hdlp->ih_inum) !=
876 		    DDI_SUCCESS)
877 			return (DDI_FAILURE);
878 
879 		DDI_INTR_NEXDBG((CE_CONT, "pci_intr_ops: ENABLE vector=0x%x\n",
880 		    hdlp->ih_vector));
881 		break;
882 	case DDI_INTROP_DISABLE:
883 		DDI_INTR_NEXDBG((CE_CONT, "pci_intr_ops: DISABLE\n"));
884 		if (psm_intr_ops == NULL)
885 			return (DDI_FAILURE);
886 
887 		pci_disable_intr(pdip, rdip, hdlp, hdlp->ih_inum);
888 		DDI_INTR_NEXDBG((CE_CONT, "pci_intr_ops: DISABLE vector = %x\n",
889 		    hdlp->ih_vector));
890 		break;
891 	case DDI_INTROP_BLOCKENABLE:
892 		DDI_INTR_NEXDBG((CE_CONT, "pci_intr_ops: BLOCKENABLE\n"));
893 		if (hdlp->ih_type != DDI_INTR_TYPE_MSI) {
894 			DDI_INTR_NEXDBG((CE_CONT, "BLOCKENABLE: not MSI\n"));
895 			return (DDI_FAILURE);
896 		}
897 
898 		/* Check if psm_intr_ops is NULL? */
899 		if (psm_intr_ops == NULL)
900 			return (DDI_FAILURE);
901 
902 		for (i = 0; i < hdlp->ih_scratch1; i++) {
903 			if (pci_enable_intr(pdip, rdip, hdlp,
904 			    hdlp->ih_inum + i) != DDI_SUCCESS) {
905 				DDI_INTR_NEXDBG((CE_CONT, "BLOCKENABLE: "
906 				    "pci_enable_intr failed for %d\n", i));
907 				for (j = 0; j < i; j++)
908 					pci_disable_intr(pdip, rdip, hdlp,
909 					    hdlp->ih_inum + j);
910 				return (DDI_FAILURE);
911 			}
912 			DDI_INTR_NEXDBG((CE_CONT, "pci_intr_ops: BLOCKENABLE "
913 			    "inum %x done\n", hdlp->ih_inum + i));
914 		}
915 		break;
916 	case DDI_INTROP_BLOCKDISABLE:
917 		DDI_INTR_NEXDBG((CE_CONT, "pci_intr_ops: BLOCKDISABLE\n"));
918 		if (hdlp->ih_type != DDI_INTR_TYPE_MSI) {
919 			DDI_INTR_NEXDBG((CE_CONT, "BLOCKDISABLE: not MSI\n"));
920 			return (DDI_FAILURE);
921 		}
922 
923 		/* Check if psm_intr_ops is present */
924 		if (psm_intr_ops == NULL)
925 			return (DDI_FAILURE);
926 
927 		for (i = 0; i < hdlp->ih_scratch1; i++) {
928 			pci_disable_intr(pdip, rdip, hdlp, hdlp->ih_inum + i);
929 			DDI_INTR_NEXDBG((CE_CONT, "pci_intr_ops: BLOCKDISABLE "
930 			    "inum %x done\n", hdlp->ih_inum + i));
931 		}
932 		break;
933 	case DDI_INTROP_SETMASK:
934 	case DDI_INTROP_CLRMASK:
935 		/*
936 		 * First handle in the config space
937 		 */
938 		if (intr_op == DDI_INTROP_SETMASK) {
939 			if (DDI_INTR_IS_MSI_OR_MSIX(hdlp->ih_type))
940 				pci_status = pci_msi_set_mask(rdip,
941 				    hdlp->ih_type, hdlp->ih_inum);
942 			else if (hdlp->ih_type == DDI_INTR_TYPE_FIXED)
943 				pci_status = pci_intx_set_mask(rdip);
944 		} else {
945 			if (DDI_INTR_IS_MSI_OR_MSIX(hdlp->ih_type))
946 				pci_status = pci_msi_clr_mask(rdip,
947 				    hdlp->ih_type, hdlp->ih_inum);
948 			else if (hdlp->ih_type == DDI_INTR_TYPE_FIXED)
949 				pci_status = pci_intx_clr_mask(rdip);
950 		}
951 
952 		/* For MSI/X; no need to check with pcplusmp */
953 		if (hdlp->ih_type != DDI_INTR_TYPE_FIXED)
954 			return (pci_status);
955 
956 		/* For fixed interrupts only: handle config space first */
957 		if (hdlp->ih_type == DDI_INTR_TYPE_FIXED &&
958 		    pci_status == DDI_SUCCESS)
959 			break;
960 
961 		/* For fixed interrupts only: confer with pcplusmp next */
962 		if (psm_intr_ops != NULL) {
963 			/* If interrupt is shared; do nothing */
964 			psm_rval = (*psm_intr_ops)(rdip, hdlp,
965 			    PSM_INTR_OP_GET_SHARED, &psm_status);
966 
967 			if (psm_rval == PSM_FAILURE || psm_status == 1)
968 				return (pci_status);
969 
970 			/* Now, pcplusmp should try to set/clear the mask */
971 			if (intr_op == DDI_INTROP_SETMASK)
972 				psm_rval = (*psm_intr_ops)(rdip, hdlp,
973 				    PSM_INTR_OP_SET_MASK, NULL);
974 			else
975 				psm_rval = (*psm_intr_ops)(rdip, hdlp,
976 				    PSM_INTR_OP_CLEAR_MASK, NULL);
977 		}
978 		return ((psm_rval == PSM_FAILURE) ? DDI_FAILURE : DDI_SUCCESS);
979 	case DDI_INTROP_GETPENDING:
980 		/*
981 		 * First check the config space and/or
982 		 * MSI capability register(s)
983 		 */
984 		if (DDI_INTR_IS_MSI_OR_MSIX(hdlp->ih_type))
985 			pci_rval = pci_msi_get_pending(rdip, hdlp->ih_type,
986 			    hdlp->ih_inum, &pci_status);
987 		else if (hdlp->ih_type == DDI_INTR_TYPE_FIXED)
988 			pci_rval = pci_intx_get_pending(rdip, &pci_status);
989 
990 		/* On failure; next try with pcplusmp */
991 		if (pci_rval != DDI_SUCCESS && psm_intr_ops != NULL)
992 			psm_rval = (*psm_intr_ops)(rdip, hdlp,
993 			    PSM_INTR_OP_GET_PENDING, &psm_status);
994 
995 		DDI_INTR_NEXDBG((CE_CONT, "pci: GETPENDING returned "
996 		    "psm_rval = %x, psm_status = %x, pci_rval = %x, "
997 		    "pci_status = %x\n", psm_rval, psm_status, pci_rval,
998 		    pci_status));
999 		if (psm_rval == PSM_FAILURE && pci_rval == DDI_FAILURE) {
1000 			*(int *)result = 0;
1001 			return (DDI_FAILURE);
1002 		}
1003 
1004 		if (psm_rval != PSM_FAILURE)
1005 			*(int *)result = psm_status;
1006 		else if (pci_rval != DDI_FAILURE)
1007 			*(int *)result = pci_status;
1008 		DDI_INTR_NEXDBG((CE_CONT, "pci: GETPENDING returned = %x\n",
1009 		    *(int *)result));
1010 		break;
1011 	case DDI_INTROP_NAVAIL:
1012 		if ((psm_intr_ops != NULL) && (pci_get_priority(rdip,
1013 		    hdlp->ih_inum, &priority) == DDI_SUCCESS)) {
1014 			/* Priority in the handle not initialized yet */
1015 			hdlp->ih_pri = priority;
1016 			(void) (*psm_intr_ops)(rdip, hdlp,
1017 			    PSM_INTR_OP_NAVAIL_VECTORS, result);
1018 		} else {
1019 			*(int *)result = 1;
1020 		}
1021 		DDI_INTR_NEXDBG((CE_CONT, "pci: NAVAIL returned = %x\n",
1022 		    *(int *)result));
1023 		break;
1024 	default:
1025 		return (i_ddi_intr_ops(pdip, rdip, intr_op, hdlp, result));
1026 	}
1027 
1028 	return (DDI_SUCCESS);
1029 }
1030 
1031 
1032 static int
1033 pci_enable_intr(dev_info_t *pdip, dev_info_t *rdip,
1034 	ddi_intr_handle_impl_t *hdlp, uint32_t inum)
1035 {
1036 	int		vector;
1037 	struct intrspec	*ispec;
1038 
1039 	DDI_INTR_NEXDBG((CE_CONT, "pci_enable_intr: hdlp %p inum %x\n",
1040 	    (void *)hdlp, inum));
1041 
1042 	/* Translate the interrupt if needed */
1043 	ispec = (struct intrspec *)pci_intx_get_ispec(pdip, rdip, (int)inum);
1044 	if (DDI_INTR_IS_MSI_OR_MSIX(hdlp->ih_type))
1045 		ispec->intrspec_vec = inum;
1046 	hdlp->ih_private = (void *)ispec;
1047 
1048 	/* translate the interrupt if needed */
1049 	(void) (*psm_intr_ops)(rdip, hdlp, PSM_INTR_OP_XLATE_VECTOR, &vector);
1050 	DDI_INTR_NEXDBG((CE_CONT, "pci_enable_intr: priority=%x vector=%x\n",
1051 	    hdlp->ih_pri, vector));
1052 
1053 	/* Add the interrupt handler */
1054 	if (!add_avintr((void *)hdlp, hdlp->ih_pri, hdlp->ih_cb_func,
1055 	    DEVI(rdip)->devi_name, vector, hdlp->ih_cb_arg1,
1056 	    hdlp->ih_cb_arg2, rdip))
1057 		return (DDI_FAILURE);
1058 
1059 	return (DDI_SUCCESS);
1060 }
1061 
1062 
1063 static void
1064 pci_disable_intr(dev_info_t *pdip, dev_info_t *rdip,
1065 	ddi_intr_handle_impl_t *hdlp, uint32_t inum)
1066 {
1067 	int		vector;
1068 	struct intrspec	*ispec;
1069 
1070 	DDI_INTR_NEXDBG((CE_CONT, "pci_disable_intr: \n"));
1071 	ispec = (struct intrspec *)pci_intx_get_ispec(pdip, rdip, (int)inum);
1072 	if (DDI_INTR_IS_MSI_OR_MSIX(hdlp->ih_type))
1073 		ispec->intrspec_vec = inum;
1074 	hdlp->ih_private = (void *)ispec;
1075 
1076 	/* translate the interrupt if needed */
1077 	(void) (*psm_intr_ops)(rdip, hdlp, PSM_INTR_OP_XLATE_VECTOR, &vector);
1078 
1079 	/* Disable the interrupt handler */
1080 	rem_avintr((void *)hdlp, hdlp->ih_pri, hdlp->ih_cb_func, vector);
1081 }
1082 
1083 
1084 /*ARGSUSED*/
1085 static int
1086 pci_ctlops(dev_info_t *dip, dev_info_t *rdip,
1087 	ddi_ctl_enum_t ctlop, void *arg, void *result)
1088 {
1089 	pci_regspec_t *drv_regp;
1090 	uint_t	reglen;
1091 	int	rn;
1092 	int	totreg;
1093 
1094 	switch (ctlop) {
1095 	case DDI_CTLOPS_REPORTDEV:
1096 		if (rdip == (dev_info_t *)0)
1097 			return (DDI_FAILURE);
1098 		cmn_err(CE_CONT, "?PCI-device: %s@%s, %s%d\n",
1099 		    ddi_node_name(rdip), ddi_get_name_addr(rdip),
1100 		    ddi_driver_name(rdip),
1101 		    ddi_get_instance(rdip));
1102 		return (DDI_SUCCESS);
1103 
1104 	case DDI_CTLOPS_INITCHILD:
1105 		return (pci_initchild((dev_info_t *)arg));
1106 
1107 	case DDI_CTLOPS_UNINITCHILD:
1108 		return (pci_removechild((dev_info_t *)arg));
1109 
1110 	case DDI_CTLOPS_SIDDEV:
1111 		return (DDI_SUCCESS);
1112 
1113 	case DDI_CTLOPS_REGSIZE:
1114 	case DDI_CTLOPS_NREGS:
1115 		if (rdip == (dev_info_t *)0)
1116 			return (DDI_FAILURE);
1117 
1118 		*(int *)result = 0;
1119 		if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, rdip,
1120 				DDI_PROP_DONTPASS, "reg", (int **)&drv_regp,
1121 				&reglen) != DDI_PROP_SUCCESS) {
1122 			return (DDI_FAILURE);
1123 		}
1124 
1125 		totreg = (reglen * sizeof (int)) / sizeof (pci_regspec_t);
1126 		if (ctlop == DDI_CTLOPS_NREGS)
1127 			*(int *)result = totreg;
1128 		else if (ctlop == DDI_CTLOPS_REGSIZE) {
1129 			rn = *(int *)arg;
1130 			if (rn >= totreg) {
1131 				ddi_prop_free(drv_regp);
1132 				return (DDI_FAILURE);
1133 			}
1134 			*(off_t *)result = drv_regp[rn].pci_size_low;
1135 		}
1136 		ddi_prop_free(drv_regp);
1137 
1138 		return (DDI_SUCCESS);
1139 
1140 	case DDI_CTLOPS_POWER: {
1141 		power_req_t	*reqp = (power_req_t *)arg;
1142 		/*
1143 		 * We currently understand reporting of PCI_PM_IDLESPEED
1144 		 * capability. Everything else is passed up.
1145 		 */
1146 		if ((reqp->request_type == PMR_REPORT_PMCAP) &&
1147 		    (reqp->req.report_pmcap_req.cap ==  PCI_PM_IDLESPEED)) {
1148 
1149 			return (DDI_SUCCESS);
1150 		}
1151 		return (ddi_ctlops(dip, rdip, ctlop, arg, result));
1152 	}
1153 
1154 	default:
1155 		return (ddi_ctlops(dip, rdip, ctlop, arg, result));
1156 	}
1157 
1158 	/* NOTREACHED */
1159 
1160 }
1161 
1162 /*
1163  * Assign the address portion of the node name
1164  */
1165 static int
1166 pci_name_child(dev_info_t *child, char *name, int namelen)
1167 {
1168 	pci_regspec_t *pci_rp;
1169 	char **unit_addr;
1170 	int dev, func, length;
1171 	uint_t n;
1172 
1173 	if (ndi_dev_is_persistent_node(child) == 0) {
1174 		/*
1175 		 * For .conf node, use "unit-address" property
1176 		 */
1177 		if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, child,
1178 		    DDI_PROP_DONTPASS, "unit-address", &unit_addr, &n) !=
1179 		    DDI_PROP_SUCCESS) {
1180 			cmn_err(CE_WARN,
1181 			    "cannot find unit-address in %s.conf",
1182 			    ddi_get_name(child));
1183 			return (DDI_FAILURE);
1184 		}
1185 		if (n != 1 || *unit_addr == NULL || **unit_addr == 0) {
1186 			cmn_err(CE_WARN, "unit-address property in %s.conf"
1187 			    " not well-formed", ddi_get_name(child));
1188 			ddi_prop_free(unit_addr);
1189 			return (DDI_FAILURE);
1190 		}
1191 		(void) snprintf(name, namelen, "%s", *unit_addr);
1192 		ddi_prop_free(unit_addr);
1193 		return (DDI_SUCCESS);
1194 	}
1195 
1196 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, child,
1197 	    DDI_PROP_DONTPASS, "reg", (int **)&pci_rp,
1198 	    (uint_t *)&length) != DDI_PROP_SUCCESS) {
1199 		cmn_err(CE_WARN, "cannot find reg property in %s",
1200 		    ddi_get_name(child));
1201 		return (DDI_FAILURE);
1202 	}
1203 
1204 	/* copy the device identifications */
1205 	dev = PCI_REG_DEV_G(pci_rp->pci_phys_hi);
1206 	func = PCI_REG_FUNC_G(pci_rp->pci_phys_hi);
1207 
1208 	/*
1209 	 * free the memory allocated by ddi_prop_lookup_int_array
1210 	 */
1211 	ddi_prop_free(pci_rp);
1212 
1213 	if (func != 0) {
1214 		(void) snprintf(name, namelen, "%x,%x", dev, func);
1215 	} else {
1216 		(void) snprintf(name, namelen, "%x", dev);
1217 	}
1218 
1219 	return (DDI_SUCCESS);
1220 }
1221 
1222 static int
1223 pci_initchild(dev_info_t *child)
1224 {
1225 	struct ddi_parent_private_data *pdptr;
1226 	char name[80];
1227 	ddi_acc_handle_t config_handle;
1228 	ushort_t command_preserve, command;
1229 
1230 	if (pci_name_child(child, name, 80) != DDI_SUCCESS) {
1231 		return (DDI_FAILURE);
1232 	}
1233 	ddi_set_name_addr(child, name);
1234 
1235 	/*
1236 	 * Pseudo nodes indicate a prototype node with per-instance
1237 	 * properties to be merged into the real h/w device node.
1238 	 * The interpretation of the unit-address is DD[,F]
1239 	 * where DD is the device id and F is the function.
1240 	 */
1241 	if (ndi_dev_is_persistent_node(child) == 0) {
1242 		extern int pci_allow_pseudo_children;
1243 
1244 		ddi_set_parent_data(child, NULL);
1245 
1246 		/*
1247 		 * Try to merge the properties from this prototype
1248 		 * node into real h/w nodes.
1249 		 */
1250 		if (ndi_merge_node(child, pci_name_child) == DDI_SUCCESS) {
1251 			/*
1252 			 * Merged ok - return failure to remove the node.
1253 			 */
1254 			ddi_set_name_addr(child, NULL);
1255 			return (DDI_FAILURE);
1256 		}
1257 
1258 		/* workaround for ddivs to run under PCI */
1259 		if (pci_allow_pseudo_children) {
1260 			/*
1261 			 * If the "interrupts" property doesn't exist,
1262 			 * this must be the ddivs no-intr case, and it returns
1263 			 * DDI_SUCCESS instead of DDI_FAILURE.
1264 			 */
1265 			if (ddi_prop_get_int(DDI_DEV_T_ANY, child,
1266 			    DDI_PROP_DONTPASS, "interrupts", -1) == -1)
1267 				return (DDI_SUCCESS);
1268 			/*
1269 			 * Create the ddi_parent_private_data for a pseudo
1270 			 * child.
1271 			 */
1272 			pdptr = (struct ddi_parent_private_data *)kmem_zalloc(
1273 			    (sizeof (struct ddi_parent_private_data) +
1274 			    sizeof (struct intrspec)), KM_SLEEP);
1275 			pdptr->par_intr = (struct intrspec *)(pdptr + 1);
1276 			pdptr->par_nintr = 1;
1277 			ddi_set_parent_data(child, pdptr);
1278 			return (DDI_SUCCESS);
1279 		}
1280 
1281 		/*
1282 		 * The child was not merged into a h/w node,
1283 		 * but there's not much we can do with it other
1284 		 * than return failure to cause the node to be removed.
1285 		 */
1286 		cmn_err(CE_WARN, "!%s@%s: %s.conf properties not merged",
1287 		    ddi_get_name(child), ddi_get_name_addr(child),
1288 		    ddi_get_name(child));
1289 		ddi_set_name_addr(child, NULL);
1290 		return (DDI_NOT_WELL_FORMED);
1291 	}
1292 
1293 	if (ddi_prop_get_int(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS,
1294 	    "interrupts", -1) != -1) {
1295 		pdptr = (struct ddi_parent_private_data *)
1296 		    kmem_zalloc((sizeof (struct ddi_parent_private_data) +
1297 		    sizeof (struct intrspec)), KM_SLEEP);
1298 		pdptr->par_intr = (struct intrspec *)(pdptr + 1);
1299 		pdptr->par_nintr = 1;
1300 		ddi_set_parent_data(child, pdptr);
1301 	} else
1302 		ddi_set_parent_data(child, NULL);
1303 
1304 	/*
1305 	 * initialize command register
1306 	 */
1307 	if (pci_config_setup(child, &config_handle) != DDI_SUCCESS)
1308 		return (DDI_FAILURE);
1309 
1310 	/*
1311 	 * Support for the "command-preserve" property.
1312 	 */
1313 	command_preserve = ddi_prop_get_int(DDI_DEV_T_ANY, child,
1314 						DDI_PROP_DONTPASS,
1315 						"command-preserve", 0);
1316 	command = pci_config_get16(config_handle, PCI_CONF_COMM);
1317 	command &= (command_preserve | PCI_COMM_BACK2BACK_ENAB);
1318 	command |= (pci_command_default & ~command_preserve);
1319 	pci_config_put16(config_handle, PCI_CONF_COMM, command);
1320 
1321 	pci_config_teardown(&config_handle);
1322 	return (DDI_SUCCESS);
1323 }
1324 
1325 static int
1326 pci_removechild(dev_info_t *dip)
1327 {
1328 	struct ddi_parent_private_data *pdptr;
1329 
1330 	if ((pdptr = ddi_get_parent_data(dip)) != NULL) {
1331 		kmem_free(pdptr, (sizeof (*pdptr) + sizeof (struct intrspec)));
1332 		ddi_set_parent_data(dip, NULL);
1333 	}
1334 	ddi_set_name_addr(dip, NULL);
1335 
1336 	/*
1337 	 * Strip the node to properly convert it back to prototype form
1338 	 */
1339 	ddi_remove_minor_node(dip, NULL);
1340 
1341 	impl_rem_dev_props(dip);
1342 
1343 	return (DDI_SUCCESS);
1344 }
1345 
1346 
1347 /*
1348  * These are the get and put functions to be shared with drivers. The
1349  * mutex locking is done inside the functions referenced, rather than
1350  * here, and is thus shared across PCI child drivers and any other
1351  * consumers of PCI config space (such as the ACPI subsystem).
1352  *
1353  * The configuration space addresses come in as pointers.  This is fine on
1354  * a 32-bit system, where the VM space and configuration space are the same
1355  * size.  It's not such a good idea on a 64-bit system, where memory
1356  * addresses are twice as large as configuration space addresses.  At some
1357  * point in the call tree we need to take a stand and say "you are 32-bit
1358  * from this time forth", and this seems like a nice self-contained place.
1359  */
1360 
1361 static uint8_t
1362 pci_config_rd8(ddi_acc_impl_t *hdlp, uint8_t *addr)
1363 {
1364 	pci_acc_cfblk_t *cfp;
1365 	uint8_t	rval;
1366 	int reg;
1367 
1368 	ASSERT64(((uintptr_t)addr >> 32) == 0);
1369 
1370 	reg = (int)(uintptr_t)addr;
1371 
1372 	cfp = (pci_acc_cfblk_t *)&hdlp->ahi_common.ah_bus_private;
1373 
1374 	rval = (*pci_getb_func)(cfp->c_busnum, cfp->c_devnum, cfp->c_funcnum,
1375 	    reg);
1376 
1377 	return (rval);
1378 }
1379 
1380 static void
1381 pci_config_rep_rd8(ddi_acc_impl_t *hdlp, uint8_t *host_addr,
1382 	uint8_t *dev_addr, size_t repcount, uint_t flags)
1383 {
1384 	uint8_t *h, *d;
1385 
1386 	h = host_addr;
1387 	d = dev_addr;
1388 
1389 	if (flags == DDI_DEV_AUTOINCR)
1390 		for (; repcount; repcount--)
1391 			*h++ = pci_config_rd8(hdlp, d++);
1392 	else
1393 		for (; repcount; repcount--)
1394 			*h++ = pci_config_rd8(hdlp, d);
1395 }
1396 
1397 static uint16_t
1398 pci_config_rd16(ddi_acc_impl_t *hdlp, uint16_t *addr)
1399 {
1400 	pci_acc_cfblk_t *cfp;
1401 	uint16_t rval;
1402 	int reg;
1403 
1404 	ASSERT64(((uintptr_t)addr >> 32) == 0);
1405 
1406 	reg = (int)(uintptr_t)addr;
1407 
1408 	cfp = (pci_acc_cfblk_t *)&hdlp->ahi_common.ah_bus_private;
1409 
1410 	rval = (*pci_getw_func)(cfp->c_busnum, cfp->c_devnum, cfp->c_funcnum,
1411 	    reg);
1412 
1413 	return (rval);
1414 }
1415 
1416 static void
1417 pci_config_rep_rd16(ddi_acc_impl_t *hdlp, uint16_t *host_addr,
1418 	uint16_t *dev_addr, size_t repcount, uint_t flags)
1419 {
1420 	uint16_t *h, *d;
1421 
1422 	h = host_addr;
1423 	d = dev_addr;
1424 
1425 	if (flags == DDI_DEV_AUTOINCR)
1426 		for (; repcount; repcount--)
1427 			*h++ = pci_config_rd16(hdlp, d++);
1428 	else
1429 		for (; repcount; repcount--)
1430 			*h++ = pci_config_rd16(hdlp, d);
1431 }
1432 
1433 static uint32_t
1434 pci_config_rd32(ddi_acc_impl_t *hdlp, uint32_t *addr)
1435 {
1436 	pci_acc_cfblk_t *cfp;
1437 	uint32_t rval;
1438 	int reg;
1439 
1440 	ASSERT64(((uintptr_t)addr >> 32) == 0);
1441 
1442 	reg = (int)(uintptr_t)addr;
1443 
1444 	cfp = (pci_acc_cfblk_t *)&hdlp->ahi_common.ah_bus_private;
1445 
1446 	rval = (*pci_getl_func)(cfp->c_busnum, cfp->c_devnum,
1447 	    cfp->c_funcnum, reg);
1448 
1449 	return (rval);
1450 }
1451 
1452 static void
1453 pci_config_rep_rd32(ddi_acc_impl_t *hdlp, uint32_t *host_addr,
1454 	uint32_t *dev_addr, size_t repcount, uint_t flags)
1455 {
1456 	uint32_t *h, *d;
1457 
1458 	h = host_addr;
1459 	d = dev_addr;
1460 
1461 	if (flags == DDI_DEV_AUTOINCR)
1462 		for (; repcount; repcount--)
1463 			*h++ = pci_config_rd32(hdlp, d++);
1464 	else
1465 		for (; repcount; repcount--)
1466 			*h++ = pci_config_rd32(hdlp, d);
1467 }
1468 
1469 
1470 static void
1471 pci_config_wr8(ddi_acc_impl_t *hdlp, uint8_t *addr, uint8_t value)
1472 {
1473 	pci_acc_cfblk_t *cfp;
1474 	int reg;
1475 
1476 	ASSERT64(((uintptr_t)addr >> 32) == 0);
1477 
1478 	reg = (int)(uintptr_t)addr;
1479 
1480 	cfp = (pci_acc_cfblk_t *)&hdlp->ahi_common.ah_bus_private;
1481 
1482 	(*pci_putb_func)(cfp->c_busnum, cfp->c_devnum,
1483 	    cfp->c_funcnum, reg, value);
1484 }
1485 
1486 static void
1487 pci_config_rep_wr8(ddi_acc_impl_t *hdlp, uint8_t *host_addr,
1488 	uint8_t *dev_addr, size_t repcount, uint_t flags)
1489 {
1490 	uint8_t *h, *d;
1491 
1492 	h = host_addr;
1493 	d = dev_addr;
1494 
1495 	if (flags == DDI_DEV_AUTOINCR)
1496 		for (; repcount; repcount--)
1497 			pci_config_wr8(hdlp, d++, *h++);
1498 	else
1499 		for (; repcount; repcount--)
1500 			pci_config_wr8(hdlp, d, *h++);
1501 }
1502 
1503 static void
1504 pci_config_wr16(ddi_acc_impl_t *hdlp, uint16_t *addr, uint16_t value)
1505 {
1506 	pci_acc_cfblk_t *cfp;
1507 	int reg;
1508 
1509 	ASSERT64(((uintptr_t)addr >> 32) == 0);
1510 
1511 	reg = (int)(uintptr_t)addr;
1512 
1513 	cfp = (pci_acc_cfblk_t *)&hdlp->ahi_common.ah_bus_private;
1514 
1515 	(*pci_putw_func)(cfp->c_busnum, cfp->c_devnum,
1516 	    cfp->c_funcnum, reg, value);
1517 }
1518 
1519 static void
1520 pci_config_rep_wr16(ddi_acc_impl_t *hdlp, uint16_t *host_addr,
1521 	uint16_t *dev_addr, size_t repcount, uint_t flags)
1522 {
1523 	uint16_t *h, *d;
1524 
1525 	h = host_addr;
1526 	d = dev_addr;
1527 
1528 	if (flags == DDI_DEV_AUTOINCR)
1529 		for (; repcount; repcount--)
1530 			pci_config_wr16(hdlp, d++, *h++);
1531 	else
1532 		for (; repcount; repcount--)
1533 			pci_config_wr16(hdlp, d, *h++);
1534 }
1535 
1536 static void
1537 pci_config_wr32(ddi_acc_impl_t *hdlp, uint32_t *addr, uint32_t value)
1538 {
1539 	pci_acc_cfblk_t *cfp;
1540 	int reg;
1541 
1542 	ASSERT64(((uintptr_t)addr >> 32) == 0);
1543 
1544 	reg = (int)(uintptr_t)addr;
1545 
1546 	cfp = (pci_acc_cfblk_t *)&hdlp->ahi_common.ah_bus_private;
1547 
1548 	(*pci_putl_func)(cfp->c_busnum, cfp->c_devnum,
1549 	    cfp->c_funcnum, reg, value);
1550 }
1551 
1552 static void
1553 pci_config_rep_wr32(ddi_acc_impl_t *hdlp, uint32_t *host_addr,
1554 	uint32_t *dev_addr, size_t repcount, uint_t flags)
1555 {
1556 	uint32_t *h, *d;
1557 
1558 	h = host_addr;
1559 	d = dev_addr;
1560 
1561 	if (flags == DDI_DEV_AUTOINCR)
1562 		for (; repcount; repcount--)
1563 			pci_config_wr32(hdlp, d++, *h++);
1564 	else
1565 		for (; repcount; repcount--)
1566 			pci_config_wr32(hdlp, d, *h++);
1567 }
1568 
1569 static uint64_t
1570 pci_config_rd64(ddi_acc_impl_t *hdlp, uint64_t *addr)
1571 {
1572 	uint32_t lw_val;
1573 	uint32_t hi_val;
1574 	uint32_t *dp;
1575 	uint64_t val;
1576 
1577 	dp = (uint32_t *)addr;
1578 	lw_val = pci_config_rd32(hdlp, dp);
1579 	dp++;
1580 	hi_val = pci_config_rd32(hdlp, dp);
1581 	val = ((uint64_t)hi_val << 32) | lw_val;
1582 	return (val);
1583 }
1584 
1585 static void
1586 pci_config_wr64(ddi_acc_impl_t *hdlp, uint64_t *addr, uint64_t value)
1587 {
1588 	uint32_t lw_val;
1589 	uint32_t hi_val;
1590 	uint32_t *dp;
1591 
1592 	dp = (uint32_t *)addr;
1593 	lw_val = (uint32_t)(value & 0xffffffff);
1594 	hi_val = (uint32_t)(value >> 32);
1595 	pci_config_wr32(hdlp, dp, lw_val);
1596 	dp++;
1597 	pci_config_wr32(hdlp, dp, hi_val);
1598 }
1599 
1600 static void
1601 pci_config_rep_rd64(ddi_acc_impl_t *hdlp, uint64_t *host_addr,
1602 	uint64_t *dev_addr, size_t repcount, uint_t flags)
1603 {
1604 	if (flags == DDI_DEV_AUTOINCR) {
1605 		for (; repcount; repcount--)
1606 			*host_addr++ = pci_config_rd64(hdlp, dev_addr++);
1607 	} else {
1608 		for (; repcount; repcount--)
1609 			*host_addr++ = pci_config_rd64(hdlp, dev_addr);
1610 	}
1611 }
1612 
1613 static void
1614 pci_config_rep_wr64(ddi_acc_impl_t *hdlp, uint64_t *host_addr,
1615 	uint64_t *dev_addr, size_t repcount, uint_t flags)
1616 {
1617 	if (flags == DDI_DEV_AUTOINCR) {
1618 		for (; repcount; repcount--)
1619 			pci_config_wr64(hdlp, host_addr++, *dev_addr++);
1620 	} else {
1621 		for (; repcount; repcount--)
1622 			pci_config_wr64(hdlp, host_addr++, *dev_addr);
1623 	}
1624 }
1625 
1626 /*
1627  * When retrofitting this module for pci_tools, functions such as open, close,
1628  * and ioctl are now pulled into this module.  Before this, the functions in
1629  * the pcihp module were referenced directly.  Now they are called or
1630  * referenced through the pcihp cb_ops structure from functions in this module.
1631  */
1632 
1633 static int
1634 pci_open(dev_t *devp, int flags, int otyp, cred_t *credp)
1635 {
1636 	return ((pcihp_cb_ops.cb_open)(devp, flags, otyp, credp));
1637 }
1638 
1639 static int
1640 pci_close(dev_t dev, int flags, int otyp, cred_t *credp)
1641 {
1642 	return ((pcihp_cb_ops.cb_close)(dev, flags, otyp, credp));
1643 }
1644 
1645 static int
1646 pci_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
1647 	int *rvalp)
1648 {
1649 	int rv = ENOTTY;
1650 
1651 	minor_t minor = getminor(dev);
1652 
1653 	switch (PCIHP_AP_MINOR_NUM_TO_PCI_DEVNUM(minor)) {
1654 	case PCI_TOOL_REG_MINOR_NUM:
1655 
1656 		switch (cmd) {
1657 		case PCITOOL_DEVICE_SET_REG:
1658 		case PCITOOL_DEVICE_GET_REG:
1659 
1660 			/* Require full privileges. */
1661 			if (secpolicy_kmdb(credp))
1662 				rv = EPERM;
1663 			else
1664 				rv = pcitool_dev_reg_ops(
1665 				    dev, (void *)arg, cmd, mode);
1666 			break;
1667 
1668 		case PCITOOL_NEXUS_SET_REG:
1669 		case PCITOOL_NEXUS_GET_REG:
1670 
1671 			/* Require full privileges. */
1672 			if (secpolicy_kmdb(credp))
1673 				rv = EPERM;
1674 			else
1675 				rv = pcitool_bus_reg_ops(
1676 				    dev, (void *)arg, cmd, mode);
1677 			break;
1678 		}
1679 		break;
1680 
1681 	case PCI_TOOL_INTR_MINOR_NUM:
1682 
1683 		switch (cmd) {
1684 		case PCITOOL_DEVICE_SET_INTR:
1685 
1686 			/* Require PRIV_SYS_RES_CONFIG, same as psradm */
1687 			if (secpolicy_ponline(credp)) {
1688 				rv = EPERM;
1689 				break;
1690 			}
1691 
1692 		/*FALLTHRU*/
1693 		/* These require no special privileges. */
1694 		case PCITOOL_DEVICE_GET_INTR:
1695 		case PCITOOL_DEVICE_NUM_INTR:
1696 			rv = pcitool_intr_admn(dev, (void *)arg, cmd, mode);
1697 			break;
1698 		}
1699 		break;
1700 
1701 	/*
1702 	 * All non-PCItool ioctls go through here, including:
1703 	 *   devctl ioctls with minor number PCIHP_DEVCTL_MINOR and
1704 	 *   those for attachment points with where minor number is the
1705 	 *   device number.
1706 	 */
1707 	default:
1708 		rv = (pcihp_cb_ops.cb_ioctl)(dev, cmd, arg, mode,
1709 		    credp, rvalp);
1710 		break;
1711 	}
1712 
1713 	return (rv);
1714 }
1715 
1716 static int
1717 pci_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op,
1718 	int flags, char *name, caddr_t valuep, int *lengthp)
1719 {
1720 	return ((pcihp_cb_ops.cb_prop_op)(dev, dip, prop_op, flags,
1721 	    name, valuep, lengthp));
1722 }
1723 
1724 static int
1725 pci_info(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
1726 {
1727 	return (pcihp_info(dip, cmd, arg, result));
1728 }
1729