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