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