xref: /titanic_51/usr/src/uts/i86pc/io/pci/pci.c (revision bdfc6d18da790deeec2e0eb09c625902defe2498)
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_NINTRS:
1111 		if (ddi_get_parent_data(rdip))
1112 			*(int *)result = 1;
1113 		else
1114 			*(int *)result = 0;
1115 		return (DDI_SUCCESS);
1116 
1117 	case DDI_CTLOPS_XLATE_INTRS:
1118 		return (DDI_SUCCESS);
1119 
1120 	case DDI_CTLOPS_SIDDEV:
1121 		return (DDI_SUCCESS);
1122 
1123 	case DDI_CTLOPS_REGSIZE:
1124 	case DDI_CTLOPS_NREGS:
1125 		if (rdip == (dev_info_t *)0)
1126 			return (DDI_FAILURE);
1127 
1128 		*(int *)result = 0;
1129 		if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, rdip,
1130 				DDI_PROP_DONTPASS, "reg", (int **)&drv_regp,
1131 				&reglen) != DDI_PROP_SUCCESS) {
1132 			return (DDI_FAILURE);
1133 		}
1134 
1135 		totreg = (reglen * sizeof (int)) / sizeof (pci_regspec_t);
1136 		if (ctlop == DDI_CTLOPS_NREGS)
1137 			*(int *)result = totreg;
1138 		else if (ctlop == DDI_CTLOPS_REGSIZE) {
1139 			rn = *(int *)arg;
1140 			if (rn >= totreg) {
1141 				ddi_prop_free(drv_regp);
1142 				return (DDI_FAILURE);
1143 			}
1144 			*(off_t *)result = drv_regp[rn].pci_size_low;
1145 		}
1146 		ddi_prop_free(drv_regp);
1147 
1148 		return (DDI_SUCCESS);
1149 
1150 	case DDI_CTLOPS_POWER: {
1151 		power_req_t	*reqp = (power_req_t *)arg;
1152 		/*
1153 		 * We currently understand reporting of PCI_PM_IDLESPEED
1154 		 * capability. Everything else is passed up.
1155 		 */
1156 		if ((reqp->request_type == PMR_REPORT_PMCAP) &&
1157 		    (reqp->req.report_pmcap_req.cap ==  PCI_PM_IDLESPEED)) {
1158 
1159 			return (DDI_SUCCESS);
1160 		}
1161 		return (ddi_ctlops(dip, rdip, ctlop, arg, result));
1162 	}
1163 
1164 	default:
1165 		return (ddi_ctlops(dip, rdip, ctlop, arg, result));
1166 	}
1167 
1168 	/* NOTREACHED */
1169 
1170 }
1171 
1172 /*
1173  * Assign the address portion of the node name
1174  */
1175 static int
1176 pci_name_child(dev_info_t *child, char *name, int namelen)
1177 {
1178 	pci_regspec_t *pci_rp;
1179 	char **unit_addr;
1180 	int dev, func, length;
1181 	uint_t n;
1182 
1183 	if (ndi_dev_is_persistent_node(child) == 0) {
1184 		/*
1185 		 * For .conf node, use "unit-address" property
1186 		 */
1187 		if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, child,
1188 		    DDI_PROP_DONTPASS, "unit-address", &unit_addr, &n) !=
1189 		    DDI_PROP_SUCCESS) {
1190 			cmn_err(CE_WARN,
1191 			    "cannot find unit-address in %s.conf",
1192 			    ddi_get_name(child));
1193 			return (DDI_FAILURE);
1194 		}
1195 		if (n != 1 || *unit_addr == NULL || **unit_addr == 0) {
1196 			cmn_err(CE_WARN, "unit-address property in %s.conf"
1197 			    " not well-formed", ddi_get_name(child));
1198 			ddi_prop_free(unit_addr);
1199 			return (DDI_FAILURE);
1200 		}
1201 		(void) snprintf(name, namelen, "%s", *unit_addr);
1202 		ddi_prop_free(unit_addr);
1203 		return (DDI_SUCCESS);
1204 	}
1205 
1206 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, child,
1207 	    DDI_PROP_DONTPASS, "reg", (int **)&pci_rp,
1208 	    (uint_t *)&length) != DDI_PROP_SUCCESS) {
1209 		cmn_err(CE_WARN, "cannot find reg property in %s",
1210 		    ddi_get_name(child));
1211 		return (DDI_FAILURE);
1212 	}
1213 
1214 	/* copy the device identifications */
1215 	dev = PCI_REG_DEV_G(pci_rp->pci_phys_hi);
1216 	func = PCI_REG_FUNC_G(pci_rp->pci_phys_hi);
1217 
1218 	/*
1219 	 * free the memory allocated by ddi_prop_lookup_int_array
1220 	 */
1221 	ddi_prop_free(pci_rp);
1222 
1223 	if (func != 0) {
1224 		(void) snprintf(name, namelen, "%x,%x", dev, func);
1225 	} else {
1226 		(void) snprintf(name, namelen, "%x", dev);
1227 	}
1228 
1229 	return (DDI_SUCCESS);
1230 }
1231 
1232 static int
1233 pci_initchild(dev_info_t *child)
1234 {
1235 	struct ddi_parent_private_data *pdptr;
1236 	char name[80];
1237 	ddi_acc_handle_t config_handle;
1238 	ushort_t command_preserve, command;
1239 
1240 	if (pci_name_child(child, name, 80) != DDI_SUCCESS) {
1241 		return (DDI_FAILURE);
1242 	}
1243 	ddi_set_name_addr(child, name);
1244 
1245 	/*
1246 	 * Pseudo nodes indicate a prototype node with per-instance
1247 	 * properties to be merged into the real h/w device node.
1248 	 * The interpretation of the unit-address is DD[,F]
1249 	 * where DD is the device id and F is the function.
1250 	 */
1251 	if (ndi_dev_is_persistent_node(child) == 0) {
1252 		extern int pci_allow_pseudo_children;
1253 
1254 		ddi_set_parent_data(child, NULL);
1255 
1256 		/*
1257 		 * Try to merge the properties from this prototype
1258 		 * node into real h/w nodes.
1259 		 */
1260 		if (ndi_merge_node(child, pci_name_child) == DDI_SUCCESS) {
1261 			/*
1262 			 * Merged ok - return failure to remove the node.
1263 			 */
1264 			ddi_set_name_addr(child, NULL);
1265 			return (DDI_FAILURE);
1266 		}
1267 
1268 		/* workaround for ddivs to run under PCI */
1269 		if (pci_allow_pseudo_children) {
1270 			/*
1271 			 * If the "interrupts" property doesn't exist,
1272 			 * this must be the ddivs no-intr case, and it returns
1273 			 * DDI_SUCCESS instead of DDI_FAILURE.
1274 			 */
1275 			if (ddi_prop_get_int(DDI_DEV_T_ANY, child,
1276 			    DDI_PROP_DONTPASS, "interrupts", -1) == -1)
1277 				return (DDI_SUCCESS);
1278 			/*
1279 			 * Create the ddi_parent_private_data for a pseudo
1280 			 * child.
1281 			 */
1282 			pdptr = (struct ddi_parent_private_data *)kmem_zalloc(
1283 			    (sizeof (struct ddi_parent_private_data) +
1284 			    sizeof (struct intrspec)), KM_SLEEP);
1285 			pdptr->par_intr = (struct intrspec *)(pdptr + 1);
1286 			pdptr->par_nintr = 1;
1287 			ddi_set_parent_data(child, pdptr);
1288 			return (DDI_SUCCESS);
1289 		}
1290 
1291 		/*
1292 		 * The child was not merged into a h/w node,
1293 		 * but there's not much we can do with it other
1294 		 * than return failure to cause the node to be removed.
1295 		 */
1296 		cmn_err(CE_WARN, "!%s@%s: %s.conf properties not merged",
1297 		    ddi_get_name(child), ddi_get_name_addr(child),
1298 		    ddi_get_name(child));
1299 		ddi_set_name_addr(child, NULL);
1300 		return (DDI_NOT_WELL_FORMED);
1301 	}
1302 
1303 	if (ddi_prop_get_int(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS,
1304 	    "interrupts", -1) != -1) {
1305 		pdptr = (struct ddi_parent_private_data *)
1306 		    kmem_zalloc((sizeof (struct ddi_parent_private_data) +
1307 		    sizeof (struct intrspec)), KM_SLEEP);
1308 		pdptr->par_intr = (struct intrspec *)(pdptr + 1);
1309 		pdptr->par_nintr = 1;
1310 		ddi_set_parent_data(child, pdptr);
1311 	} else
1312 		ddi_set_parent_data(child, NULL);
1313 
1314 	/*
1315 	 * initialize command register
1316 	 */
1317 	if (pci_config_setup(child, &config_handle) != DDI_SUCCESS)
1318 		return (DDI_FAILURE);
1319 
1320 	/*
1321 	 * Support for the "command-preserve" property.
1322 	 */
1323 	command_preserve = ddi_prop_get_int(DDI_DEV_T_ANY, child,
1324 						DDI_PROP_DONTPASS,
1325 						"command-preserve", 0);
1326 	command = pci_config_get16(config_handle, PCI_CONF_COMM);
1327 	command &= (command_preserve | PCI_COMM_BACK2BACK_ENAB);
1328 	command |= (pci_command_default & ~command_preserve);
1329 	pci_config_put16(config_handle, PCI_CONF_COMM, command);
1330 
1331 	pci_config_teardown(&config_handle);
1332 	return (DDI_SUCCESS);
1333 }
1334 
1335 static int
1336 pci_removechild(dev_info_t *dip)
1337 {
1338 	struct ddi_parent_private_data *pdptr;
1339 
1340 	if ((pdptr = ddi_get_parent_data(dip)) != NULL) {
1341 		kmem_free(pdptr, (sizeof (*pdptr) + sizeof (struct intrspec)));
1342 		ddi_set_parent_data(dip, NULL);
1343 	}
1344 	ddi_set_name_addr(dip, NULL);
1345 
1346 	/*
1347 	 * Strip the node to properly convert it back to prototype form
1348 	 */
1349 	ddi_remove_minor_node(dip, NULL);
1350 
1351 	impl_rem_dev_props(dip);
1352 
1353 	return (DDI_SUCCESS);
1354 }
1355 
1356 
1357 /*
1358  * These are the get and put functions to be shared with drivers. The
1359  * mutex locking is done inside the functions referenced, rather than
1360  * here, and is thus shared across PCI child drivers and any other
1361  * consumers of PCI config space (such as the ACPI subsystem).
1362  *
1363  * The configuration space addresses come in as pointers.  This is fine on
1364  * a 32-bit system, where the VM space and configuration space are the same
1365  * size.  It's not such a good idea on a 64-bit system, where memory
1366  * addresses are twice as large as configuration space addresses.  At some
1367  * point in the call tree we need to take a stand and say "you are 32-bit
1368  * from this time forth", and this seems like a nice self-contained place.
1369  */
1370 
1371 static uint8_t
1372 pci_config_rd8(ddi_acc_impl_t *hdlp, uint8_t *addr)
1373 {
1374 	pci_acc_cfblk_t *cfp;
1375 	uint8_t	rval;
1376 	int reg;
1377 
1378 	ASSERT64(((uintptr_t)addr >> 32) == 0);
1379 
1380 	reg = (int)(uintptr_t)addr;
1381 
1382 	cfp = (pci_acc_cfblk_t *)&hdlp->ahi_common.ah_bus_private;
1383 
1384 	rval = (*pci_getb_func)(cfp->c_busnum, cfp->c_devnum, cfp->c_funcnum,
1385 	    reg);
1386 
1387 	return (rval);
1388 }
1389 
1390 static void
1391 pci_config_rep_rd8(ddi_acc_impl_t *hdlp, uint8_t *host_addr,
1392 	uint8_t *dev_addr, size_t repcount, uint_t flags)
1393 {
1394 	uint8_t *h, *d;
1395 
1396 	h = host_addr;
1397 	d = dev_addr;
1398 
1399 	if (flags == DDI_DEV_AUTOINCR)
1400 		for (; repcount; repcount--)
1401 			*h++ = pci_config_rd8(hdlp, d++);
1402 	else
1403 		for (; repcount; repcount--)
1404 			*h++ = pci_config_rd8(hdlp, d);
1405 }
1406 
1407 static uint16_t
1408 pci_config_rd16(ddi_acc_impl_t *hdlp, uint16_t *addr)
1409 {
1410 	pci_acc_cfblk_t *cfp;
1411 	uint16_t rval;
1412 	int reg;
1413 
1414 	ASSERT64(((uintptr_t)addr >> 32) == 0);
1415 
1416 	reg = (int)(uintptr_t)addr;
1417 
1418 	cfp = (pci_acc_cfblk_t *)&hdlp->ahi_common.ah_bus_private;
1419 
1420 	rval = (*pci_getw_func)(cfp->c_busnum, cfp->c_devnum, cfp->c_funcnum,
1421 	    reg);
1422 
1423 	return (rval);
1424 }
1425 
1426 static void
1427 pci_config_rep_rd16(ddi_acc_impl_t *hdlp, uint16_t *host_addr,
1428 	uint16_t *dev_addr, size_t repcount, uint_t flags)
1429 {
1430 	uint16_t *h, *d;
1431 
1432 	h = host_addr;
1433 	d = dev_addr;
1434 
1435 	if (flags == DDI_DEV_AUTOINCR)
1436 		for (; repcount; repcount--)
1437 			*h++ = pci_config_rd16(hdlp, d++);
1438 	else
1439 		for (; repcount; repcount--)
1440 			*h++ = pci_config_rd16(hdlp, d);
1441 }
1442 
1443 static uint32_t
1444 pci_config_rd32(ddi_acc_impl_t *hdlp, uint32_t *addr)
1445 {
1446 	pci_acc_cfblk_t *cfp;
1447 	uint32_t rval;
1448 	int reg;
1449 
1450 	ASSERT64(((uintptr_t)addr >> 32) == 0);
1451 
1452 	reg = (int)(uintptr_t)addr;
1453 
1454 	cfp = (pci_acc_cfblk_t *)&hdlp->ahi_common.ah_bus_private;
1455 
1456 	rval = (*pci_getl_func)(cfp->c_busnum, cfp->c_devnum,
1457 	    cfp->c_funcnum, reg);
1458 
1459 	return (rval);
1460 }
1461 
1462 static void
1463 pci_config_rep_rd32(ddi_acc_impl_t *hdlp, uint32_t *host_addr,
1464 	uint32_t *dev_addr, size_t repcount, uint_t flags)
1465 {
1466 	uint32_t *h, *d;
1467 
1468 	h = host_addr;
1469 	d = dev_addr;
1470 
1471 	if (flags == DDI_DEV_AUTOINCR)
1472 		for (; repcount; repcount--)
1473 			*h++ = pci_config_rd32(hdlp, d++);
1474 	else
1475 		for (; repcount; repcount--)
1476 			*h++ = pci_config_rd32(hdlp, d);
1477 }
1478 
1479 
1480 static void
1481 pci_config_wr8(ddi_acc_impl_t *hdlp, uint8_t *addr, uint8_t value)
1482 {
1483 	pci_acc_cfblk_t *cfp;
1484 	int reg;
1485 
1486 	ASSERT64(((uintptr_t)addr >> 32) == 0);
1487 
1488 	reg = (int)(uintptr_t)addr;
1489 
1490 	cfp = (pci_acc_cfblk_t *)&hdlp->ahi_common.ah_bus_private;
1491 
1492 	(*pci_putb_func)(cfp->c_busnum, cfp->c_devnum,
1493 	    cfp->c_funcnum, reg, value);
1494 }
1495 
1496 static void
1497 pci_config_rep_wr8(ddi_acc_impl_t *hdlp, uint8_t *host_addr,
1498 	uint8_t *dev_addr, size_t repcount, uint_t flags)
1499 {
1500 	uint8_t *h, *d;
1501 
1502 	h = host_addr;
1503 	d = dev_addr;
1504 
1505 	if (flags == DDI_DEV_AUTOINCR)
1506 		for (; repcount; repcount--)
1507 			pci_config_wr8(hdlp, d++, *h++);
1508 	else
1509 		for (; repcount; repcount--)
1510 			pci_config_wr8(hdlp, d, *h++);
1511 }
1512 
1513 static void
1514 pci_config_wr16(ddi_acc_impl_t *hdlp, uint16_t *addr, uint16_t value)
1515 {
1516 	pci_acc_cfblk_t *cfp;
1517 	int reg;
1518 
1519 	ASSERT64(((uintptr_t)addr >> 32) == 0);
1520 
1521 	reg = (int)(uintptr_t)addr;
1522 
1523 	cfp = (pci_acc_cfblk_t *)&hdlp->ahi_common.ah_bus_private;
1524 
1525 	(*pci_putw_func)(cfp->c_busnum, cfp->c_devnum,
1526 	    cfp->c_funcnum, reg, value);
1527 }
1528 
1529 static void
1530 pci_config_rep_wr16(ddi_acc_impl_t *hdlp, uint16_t *host_addr,
1531 	uint16_t *dev_addr, size_t repcount, uint_t flags)
1532 {
1533 	uint16_t *h, *d;
1534 
1535 	h = host_addr;
1536 	d = dev_addr;
1537 
1538 	if (flags == DDI_DEV_AUTOINCR)
1539 		for (; repcount; repcount--)
1540 			pci_config_wr16(hdlp, d++, *h++);
1541 	else
1542 		for (; repcount; repcount--)
1543 			pci_config_wr16(hdlp, d, *h++);
1544 }
1545 
1546 static void
1547 pci_config_wr32(ddi_acc_impl_t *hdlp, uint32_t *addr, uint32_t value)
1548 {
1549 	pci_acc_cfblk_t *cfp;
1550 	int reg;
1551 
1552 	ASSERT64(((uintptr_t)addr >> 32) == 0);
1553 
1554 	reg = (int)(uintptr_t)addr;
1555 
1556 	cfp = (pci_acc_cfblk_t *)&hdlp->ahi_common.ah_bus_private;
1557 
1558 	(*pci_putl_func)(cfp->c_busnum, cfp->c_devnum,
1559 	    cfp->c_funcnum, reg, value);
1560 }
1561 
1562 static void
1563 pci_config_rep_wr32(ddi_acc_impl_t *hdlp, uint32_t *host_addr,
1564 	uint32_t *dev_addr, size_t repcount, uint_t flags)
1565 {
1566 	uint32_t *h, *d;
1567 
1568 	h = host_addr;
1569 	d = dev_addr;
1570 
1571 	if (flags == DDI_DEV_AUTOINCR)
1572 		for (; repcount; repcount--)
1573 			pci_config_wr32(hdlp, d++, *h++);
1574 	else
1575 		for (; repcount; repcount--)
1576 			pci_config_wr32(hdlp, d, *h++);
1577 }
1578 
1579 static uint64_t
1580 pci_config_rd64(ddi_acc_impl_t *hdlp, uint64_t *addr)
1581 {
1582 	uint32_t lw_val;
1583 	uint32_t hi_val;
1584 	uint32_t *dp;
1585 	uint64_t val;
1586 
1587 	dp = (uint32_t *)addr;
1588 	lw_val = pci_config_rd32(hdlp, dp);
1589 	dp++;
1590 	hi_val = pci_config_rd32(hdlp, dp);
1591 	val = ((uint64_t)hi_val << 32) | lw_val;
1592 	return (val);
1593 }
1594 
1595 static void
1596 pci_config_wr64(ddi_acc_impl_t *hdlp, uint64_t *addr, uint64_t value)
1597 {
1598 	uint32_t lw_val;
1599 	uint32_t hi_val;
1600 	uint32_t *dp;
1601 
1602 	dp = (uint32_t *)addr;
1603 	lw_val = (uint32_t)(value & 0xffffffff);
1604 	hi_val = (uint32_t)(value >> 32);
1605 	pci_config_wr32(hdlp, dp, lw_val);
1606 	dp++;
1607 	pci_config_wr32(hdlp, dp, hi_val);
1608 }
1609 
1610 static void
1611 pci_config_rep_rd64(ddi_acc_impl_t *hdlp, uint64_t *host_addr,
1612 	uint64_t *dev_addr, size_t repcount, uint_t flags)
1613 {
1614 	if (flags == DDI_DEV_AUTOINCR) {
1615 		for (; repcount; repcount--)
1616 			*host_addr++ = pci_config_rd64(hdlp, dev_addr++);
1617 	} else {
1618 		for (; repcount; repcount--)
1619 			*host_addr++ = pci_config_rd64(hdlp, dev_addr);
1620 	}
1621 }
1622 
1623 static void
1624 pci_config_rep_wr64(ddi_acc_impl_t *hdlp, uint64_t *host_addr,
1625 	uint64_t *dev_addr, size_t repcount, uint_t flags)
1626 {
1627 	if (flags == DDI_DEV_AUTOINCR) {
1628 		for (; repcount; repcount--)
1629 			pci_config_wr64(hdlp, host_addr++, *dev_addr++);
1630 	} else {
1631 		for (; repcount; repcount--)
1632 			pci_config_wr64(hdlp, host_addr++, *dev_addr);
1633 	}
1634 }
1635 
1636 /*
1637  * When retrofitting this module for pci_tools, functions such as open, close,
1638  * and ioctl are now pulled into this module.  Before this, the functions in
1639  * the pcihp module were referenced directly.  Now they are called or
1640  * referenced through the pcihp cb_ops structure from functions in this module.
1641  */
1642 
1643 static int
1644 pci_open(dev_t *devp, int flags, int otyp, cred_t *credp)
1645 {
1646 	return ((pcihp_cb_ops.cb_open)(devp, flags, otyp, credp));
1647 }
1648 
1649 static int
1650 pci_close(dev_t dev, int flags, int otyp, cred_t *credp)
1651 {
1652 	return ((pcihp_cb_ops.cb_close)(dev, flags, otyp, credp));
1653 }
1654 
1655 static int
1656 pci_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
1657 	int *rvalp)
1658 {
1659 	int rv = ENOTTY;
1660 
1661 	minor_t minor = getminor(dev);
1662 
1663 	switch (PCIHP_AP_MINOR_NUM_TO_PCI_DEVNUM(minor)) {
1664 	case PCIHP_DEVCTL_MINOR:
1665 		if (IS_DEVCTL(cmd))
1666 			rv = (pcihp_cb_ops.cb_ioctl)(dev, cmd, arg, mode,
1667 			    credp, rvalp);
1668 		break;
1669 
1670 	case PCI_TOOL_REG_MINOR_NUM:
1671 
1672 		switch (cmd) {
1673 		case PCITOOL_DEVICE_SET_REG:
1674 		case PCITOOL_DEVICE_GET_REG:
1675 
1676 			/* Require full privileges. */
1677 			if (secpolicy_kmdb(credp))
1678 				rv = EPERM;
1679 			else
1680 				rv = pcitool_dev_reg_ops(
1681 				    dev, (void *)arg, cmd, mode);
1682 			break;
1683 
1684 		case PCITOOL_NEXUS_SET_REG:
1685 		case PCITOOL_NEXUS_GET_REG:
1686 
1687 			/* Require full privileges. */
1688 			if (secpolicy_kmdb(credp))
1689 				rv = EPERM;
1690 			else
1691 				rv = pcitool_bus_reg_ops(
1692 				    dev, (void *)arg, cmd, mode);
1693 			break;
1694 		}
1695 		break;
1696 
1697 	case PCI_TOOL_INTR_MINOR_NUM:
1698 
1699 		switch (cmd) {
1700 		case PCITOOL_DEVICE_SET_INTR:
1701 
1702 			/* Require PRIV_SYS_RES_CONFIG, same as psradm */
1703 			if (secpolicy_ponline(credp)) {
1704 				rv = EPERM;
1705 				break;
1706 			}
1707 
1708 		/*FALLTHRU*/
1709 		/* These require no special privileges. */
1710 		case PCITOOL_DEVICE_GET_INTR:
1711 		case PCITOOL_DEVICE_NUM_INTR:
1712 			rv = pcitool_intr_admn(dev, (void *)arg, cmd, mode);
1713 			break;
1714 		}
1715 		break;
1716 
1717 	default:
1718 		break;
1719 	}
1720 
1721 	return (rv);
1722 }
1723 
1724 static int
1725 pci_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op,
1726 	int flags, char *name, caddr_t valuep, int *lengthp)
1727 {
1728 	return ((pcihp_cb_ops.cb_prop_op)(dev, dip, prop_op, flags,
1729 	    name, valuep, lengthp));
1730 }
1731 
1732 static int
1733 pci_info(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
1734 {
1735 	return (pcihp_info(dip, cmd, arg, result));
1736 }
1737