xref: /titanic_44/usr/src/uts/i86pc/io/pci/pci.c (revision f56c1286e5113aa46bd6e723da14d30c123153f2)
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/modctl.h>
35 #include <sys/pci.h>
36 #include <sys/pci_impl.h>
37 #include <sys/sysmacros.h>
38 #include <sys/sunndi.h>
39 #include <sys/hotplug/pci/pcihp.h>
40 #include <sys/pci_cfgspace.h>
41 #include <io/pci/pci_common.h>
42 #include <io/pci/pci_tools_ext.h>
43 
44 /* Save minimal state. */
45 void *pci_statep;
46 
47 /*
48  * Bus Operation functions
49  */
50 static int	pci_bus_map(dev_info_t *, dev_info_t *, ddi_map_req_t *,
51 		    off_t, off_t, caddr_t *);
52 static int	pci_ctlops(dev_info_t *, dev_info_t *, ddi_ctl_enum_t,
53 		    void *, void *);
54 static int	pci_intr_ops(dev_info_t *, dev_info_t *, ddi_intr_op_t,
55 		    ddi_intr_handle_impl_t *, void *);
56 
57 struct bus_ops pci_bus_ops = {
58 	BUSO_REV,
59 	pci_bus_map,
60 	NULL,
61 	NULL,
62 	NULL,
63 	i_ddi_map_fault,
64 	ddi_dma_map,
65 	ddi_dma_allochdl,
66 	ddi_dma_freehdl,
67 	ddi_dma_bindhdl,
68 	ddi_dma_unbindhdl,
69 	ddi_dma_flush,
70 	ddi_dma_win,
71 	ddi_dma_mctl,
72 	pci_ctlops,
73 	ddi_bus_prop_op,
74 	0,		/* (*bus_get_eventcookie)();	*/
75 	0,		/* (*bus_add_eventcall)();	*/
76 	0,		/* (*bus_remove_eventcall)();	*/
77 	0,		/* (*bus_post_event)();		*/
78 	0,		/* (*bus_intr_ctl)(); */
79 	0,		/* (*bus_config)(); */
80 	0,		/* (*bus_unconfig)(); */
81 	NULL,		/* (*bus_fm_init)(); */
82 	NULL,		/* (*bus_fm_fini)(); */
83 	NULL,		/* (*bus_fm_access_enter)(); */
84 	NULL,		/* (*bus_fm_access_exit)(); */
85 	NULL,		/* (*bus_power)(); */
86 	pci_intr_ops	/* (*bus_intr_op)(); */
87 };
88 
89 /*
90  * One goal here is to leverage off of the pcihp.c source without making
91  * changes to it.  Call into it's cb_ops directly if needed, piggybacking
92  * anything else needed by the pci_tools.c module.  Only pci_tools and pcihp
93  * will be opening PCI nexus driver file descriptors.
94  */
95 static int	pci_open(dev_t *, int, int, cred_t *);
96 static int	pci_close(dev_t, int, int, cred_t *);
97 static int	pci_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
98 static int	pci_prop_op(dev_t, dev_info_t *, ddi_prop_op_t, int, char *,
99 		    caddr_t, int *);
100 static int	pci_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
101 
102 struct cb_ops pci_cb_ops = {
103 	pci_open,			/* open */
104 	pci_close,			/* close */
105 	nodev,				/* strategy */
106 	nodev,				/* print */
107 	nodev,				/* dump */
108 	nodev,				/* read */
109 	nodev,				/* write */
110 	pci_ioctl,			/* ioctl */
111 	nodev,				/* devmap */
112 	nodev,				/* mmap */
113 	nodev,				/* segmap */
114 	nochpoll,			/* poll */
115 	pci_prop_op,			/* cb_prop_op */
116 	NULL,				/* streamtab */
117 	D_NEW | D_MP | D_HOTPLUG,	/* Driver compatibility flag */
118 	CB_REV,				/* rev */
119 	nodev,				/* int (*cb_aread)() */
120 	nodev				/* int (*cb_awrite)() */
121 };
122 
123 /*
124  * Device Node Operation functions
125  */
126 static int pci_attach(dev_info_t *devi, ddi_attach_cmd_t cmd);
127 static int pci_detach(dev_info_t *devi, ddi_detach_cmd_t cmd);
128 
129 struct dev_ops pci_ops = {
130 	DEVO_REV,		/* devo_rev */
131 	0,			/* refcnt  */
132 	pci_info,		/* info */
133 	nulldev,		/* identify */
134 	nulldev,		/* probe */
135 	pci_attach,		/* attach */
136 	pci_detach,		/* detach */
137 	nulldev,		/* reset */
138 	&pci_cb_ops,		/* driver operations */
139 	&pci_bus_ops		/* bus operations */
140 };
141 
142 /*
143  * This variable controls the default setting of the command register
144  * for pci devices.  See pci_initchild() for details.
145  */
146 static ushort_t pci_command_default = PCI_COMM_ME |
147 					PCI_COMM_MAE |
148 					PCI_COMM_IO;
149 
150 /*
151  * Internal routines in support of particular pci_ctlops.
152  */
153 static int pci_removechild(dev_info_t *child);
154 static int pci_initchild(dev_info_t *child);
155 
156 /*
157  * These are the access routines.  The pci_bus_map sets the handle
158  * to point to these.
159  */
160 static uint8_t pci_config_rd8(ddi_acc_impl_t *hdlp, uint8_t *addr);
161 static uint16_t pci_config_rd16(ddi_acc_impl_t *hdlp, uint16_t *addr);
162 static uint32_t pci_config_rd32(ddi_acc_impl_t *hdlp, uint32_t *addr);
163 static uint64_t pci_config_rd64(ddi_acc_impl_t *hdlp, uint64_t *addr);
164 
165 static void pci_config_wr8(ddi_acc_impl_t *hdlp, uint8_t *addr,
166 				uint8_t value);
167 static void pci_config_wr16(ddi_acc_impl_t *hdlp, uint16_t *addr,
168 				uint16_t value);
169 static void pci_config_wr32(ddi_acc_impl_t *hdlp, uint32_t *addr,
170 				uint32_t value);
171 static void pci_config_wr64(ddi_acc_impl_t *hdlp, uint64_t *addr,
172 				uint64_t value);
173 
174 static void pci_config_rep_rd8(ddi_acc_impl_t *hdlp, uint8_t *host_addr,
175 	uint8_t *dev_addr, size_t repcount, uint_t flags);
176 static void pci_config_rep_rd16(ddi_acc_impl_t *hdlp, uint16_t *host_addr,
177 	uint16_t *dev_addr, size_t repcount, uint_t flags);
178 static void pci_config_rep_rd32(ddi_acc_impl_t *hdlp, uint32_t *host_addr,
179 	uint32_t *dev_addr, size_t repcount, uint_t flags);
180 static void pci_config_rep_rd64(ddi_acc_impl_t *hdlp, uint64_t *host_addr,
181 	uint64_t *dev_addr, size_t repcount, uint_t flags);
182 
183 static void pci_config_rep_wr8(ddi_acc_impl_t *hdlp, uint8_t *host_addr,
184 	uint8_t *dev_addr, size_t repcount, uint_t flags);
185 static void pci_config_rep_wr16(ddi_acc_impl_t *hdlp, uint16_t *host_addr,
186 	uint16_t *dev_addr, size_t repcount, uint_t flags);
187 static void pci_config_rep_wr32(ddi_acc_impl_t *hdlp, uint32_t *host_addr,
188 	uint32_t *dev_addr, size_t repcount, uint_t flags);
189 static void pci_config_rep_wr64(ddi_acc_impl_t *hdlp, uint64_t *host_addr,
190 	uint64_t *dev_addr, size_t repcount, uint_t flags);
191 
192 /*
193  * Module linkage information for the kernel.
194  */
195 
196 static struct modldrv modldrv = {
197 	&mod_driverops, /* Type of module */
198 	"host to PCI nexus driver %I%",
199 	&pci_ops,	/* driver ops */
200 };
201 
202 static struct modlinkage modlinkage = {
203 	MODREV_1,
204 	(void *)&modldrv,
205 	NULL
206 };
207 
208 int
209 _init(void)
210 {
211 	int e;
212 
213 	/*
214 	 * Initialize per-pci bus soft state pointer.
215 	 */
216 	e = ddi_soft_state_init(&pci_statep, sizeof (pci_state_t), 1);
217 	if (e != 0)
218 		return (e);
219 
220 	if ((e = mod_install(&modlinkage)) != 0)
221 		ddi_soft_state_fini(&pci_statep);
222 
223 	return (e);
224 }
225 
226 int
227 _fini(void)
228 {
229 	int rc;
230 
231 	rc = mod_remove(&modlinkage);
232 	if (rc != 0)
233 		return (rc);
234 
235 	ddi_soft_state_fini(&pci_statep);
236 
237 	return (rc);
238 }
239 
240 int
241 _info(struct modinfo *modinfop)
242 {
243 	return (mod_info(&modlinkage, modinfop));
244 }
245 
246 /*ARGSUSED*/
247 static int
248 pci_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
249 {
250 	/*
251 	 * Use the minor number as constructed by pcihp, as the index value to
252 	 * ddi_soft_state_zalloc.
253 	 */
254 	int instance = ddi_get_instance(devi);
255 	pci_state_t *pcip = NULL;
256 
257 	if (ddi_prop_update_string(DDI_DEV_T_NONE, devi, "device_type", "pci")
258 	    != DDI_PROP_SUCCESS) {
259 		cmn_err(CE_WARN, "pci:  'device_type' prop create failed");
260 	}
261 
262 	if (ddi_soft_state_zalloc(pci_statep, instance) == DDI_SUCCESS) {
263 		pcip = ddi_get_soft_state(pci_statep, instance);
264 	}
265 
266 	if (pcip == NULL) {
267 		goto bad_soft_state;
268 	}
269 
270 	pcip->pci_dip = devi;
271 
272 	/*
273 	 * Initialize hotplug support on this bus. At minimum
274 	 * (for non hotplug bus) this would create ":devctl" minor
275 	 * node to support DEVCTL_DEVICE_* and DEVCTL_BUS_* ioctls
276 	 * to this bus.
277 	 */
278 	if (pcihp_init(devi) != DDI_SUCCESS) {
279 		cmn_err(CE_WARN, "pci: Failed to setup hotplug framework");
280 		goto bad_pcihp_init;
281 	}
282 
283 	/* Second arg: initialize for pci, not pci_express */
284 	if (pcitool_init(devi, B_FALSE) != DDI_SUCCESS) {
285 		goto bad_pcitool_init;
286 	}
287 
288 	ddi_report_dev(devi);
289 
290 	return (DDI_SUCCESS);
291 
292 bad_pcitool_init:
293 	(void) pcihp_uninit(devi);
294 bad_pcihp_init:
295 	ddi_soft_state_free(pci_statep, instance);
296 bad_soft_state:
297 	return (DDI_FAILURE);
298 }
299 
300 /*ARGSUSED*/
301 static int
302 pci_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
303 {
304 	int instance = ddi_get_instance(devi);
305 
306 	/* Uninitialize pcitool support. */
307 	pcitool_uninit(devi);
308 
309 	/* Uninitialize hotplug support on this bus. */
310 	(void) pcihp_uninit(devi);
311 
312 	ddi_soft_state_free(pci_statep, instance);
313 
314 	return (DDI_SUCCESS);
315 }
316 
317 static int
318 pci_bus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
319 	off_t offset, off_t len, caddr_t *vaddrp)
320 {
321 	struct regspec reg;
322 	ddi_map_req_t mr;
323 	ddi_acc_hdl_t *hp;
324 	ddi_acc_impl_t *ap;
325 	pci_regspec_t pci_reg;
326 	pci_regspec_t *pci_rp;
327 	int 	rnumber;
328 	int	length;
329 	pci_acc_cfblk_t *cfp;
330 	int	space;
331 
332 
333 	mr = *mp; /* Get private copy of request */
334 	mp = &mr;
335 
336 	/*
337 	 * check for register number
338 	 */
339 	switch (mp->map_type) {
340 	case DDI_MT_REGSPEC:
341 		pci_reg = *(pci_regspec_t *)(mp->map_obj.rp);
342 		pci_rp = &pci_reg;
343 		if (pci_common_get_reg_prop(rdip, pci_rp) != DDI_SUCCESS)
344 			return (DDI_FAILURE);
345 		break;
346 	case DDI_MT_RNUMBER:
347 		rnumber = mp->map_obj.rnumber;
348 		/*
349 		 * get ALL "reg" properties for dip, select the one of
350 		 * of interest. In x86, "assigned-addresses" property
351 		 * is identical to the "reg" property, so there is no
352 		 * need to cross check the two to determine the physical
353 		 * address of the registers.
354 		 * This routine still performs some validity checks to
355 		 * make sure that everything is okay.
356 		 */
357 		if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, rdip,
358 		    DDI_PROP_DONTPASS, "reg", (int **)&pci_rp,
359 		    (uint_t *)&length) != DDI_PROP_SUCCESS)
360 			return (DDI_FAILURE);
361 
362 		/*
363 		 * validate the register number.
364 		 */
365 		length /= (sizeof (pci_regspec_t) / sizeof (int));
366 		if (rnumber >= length) {
367 			ddi_prop_free(pci_rp);
368 			return (DDI_FAILURE);
369 		}
370 
371 		/*
372 		 * copy the required entry.
373 		 */
374 		pci_reg = pci_rp[rnumber];
375 
376 		/*
377 		 * free the memory allocated by ddi_prop_lookup_int_array
378 		 */
379 		ddi_prop_free(pci_rp);
380 
381 		pci_rp = &pci_reg;
382 		if (pci_common_get_reg_prop(rdip, pci_rp) != DDI_SUCCESS)
383 			return (DDI_FAILURE);
384 		mp->map_type = DDI_MT_REGSPEC;
385 		break;
386 	default:
387 		return (DDI_ME_INVAL);
388 	}
389 
390 	space = pci_rp->pci_phys_hi & PCI_REG_ADDR_M;
391 
392 	/*
393 	 * check for unmap and unlock of address space
394 	 */
395 	if ((mp->map_op == DDI_MO_UNMAP) || (mp->map_op == DDI_MO_UNLOCK)) {
396 		/*
397 		 * Adjust offset and length
398 		 * A non-zero length means override the one in the regspec.
399 		 */
400 		pci_rp->pci_phys_low += (uint_t)offset;
401 		if (len != 0)
402 			pci_rp->pci_size_low = len;
403 
404 		switch (space) {
405 		case PCI_ADDR_CONFIG:
406 			/* No work required on unmap of Config space */
407 			return (DDI_SUCCESS);
408 
409 		case PCI_ADDR_IO:
410 			reg.regspec_bustype = 1;
411 			break;
412 
413 		case PCI_ADDR_MEM64:
414 			/*
415 			 * MEM64 requires special treatment on map, to check
416 			 * that the device is below 4G.  On unmap, however,
417 			 * we can assume that everything is OK... the map
418 			 * must have succeeded.
419 			 */
420 			/* FALLTHROUGH */
421 		case PCI_ADDR_MEM32:
422 			reg.regspec_bustype = 0;
423 			break;
424 
425 		default:
426 			return (DDI_FAILURE);
427 		}
428 		reg.regspec_addr = pci_rp->pci_phys_low;
429 		reg.regspec_size = pci_rp->pci_size_low;
430 
431 		mp->map_obj.rp = &reg;
432 		return (ddi_map(dip, mp, (off_t)0, (off_t)0, vaddrp));
433 
434 	}
435 
436 	/* check for user mapping request - not legal for Config */
437 	if (mp->map_op == DDI_MO_MAP_HANDLE && space == PCI_ADDR_CONFIG) {
438 		return (DDI_FAILURE);
439 	}
440 
441 	/*
442 	 * check for config space
443 	 * On x86, CONFIG is not mapped via MMU and there is
444 	 * no endian-ness issues. Set the attr field in the handle to
445 	 * indicate that the common routines to call the nexus driver.
446 	 */
447 	if (space == PCI_ADDR_CONFIG) {
448 		hp = (ddi_acc_hdl_t *)mp->map_handlep;
449 
450 		/* Can't map config space without a handle */
451 		if (hp == NULL)
452 			return (DDI_FAILURE);
453 
454 		ap = (ddi_acc_impl_t *)hp->ah_platform_private;
455 
456 		/* endian-ness check */
457 		if (hp->ah_acc.devacc_attr_endian_flags == DDI_STRUCTURE_BE_ACC)
458 			return (DDI_FAILURE);
459 
460 		/*
461 		 * range check
462 		 */
463 		if ((offset >= 256) || (len > 256) || (offset + len > 256))
464 			return (DDI_FAILURE);
465 		*vaddrp = (caddr_t)offset;
466 
467 		ap->ahi_acc_attr |= DDI_ACCATTR_CONFIG_SPACE;
468 		ap->ahi_put8 = pci_config_wr8;
469 		ap->ahi_get8 = pci_config_rd8;
470 		ap->ahi_put64 = pci_config_wr64;
471 		ap->ahi_get64 = pci_config_rd64;
472 		ap->ahi_rep_put8 = pci_config_rep_wr8;
473 		ap->ahi_rep_get8 = pci_config_rep_rd8;
474 		ap->ahi_rep_put64 = pci_config_rep_wr64;
475 		ap->ahi_rep_get64 = pci_config_rep_rd64;
476 		ap->ahi_get16 = pci_config_rd16;
477 		ap->ahi_get32 = pci_config_rd32;
478 		ap->ahi_put16 = pci_config_wr16;
479 		ap->ahi_put32 = pci_config_wr32;
480 		ap->ahi_rep_get16 = pci_config_rep_rd16;
481 		ap->ahi_rep_get32 = pci_config_rep_rd32;
482 		ap->ahi_rep_put16 = pci_config_rep_wr16;
483 		ap->ahi_rep_put32 = pci_config_rep_wr32;
484 
485 		/* Initialize to default check/notify functions */
486 		ap->ahi_fault_check = i_ddi_acc_fault_check;
487 		ap->ahi_fault_notify = i_ddi_acc_fault_notify;
488 		ap->ahi_fault = 0;
489 		impl_acc_err_init(hp);
490 
491 		/* record the device address for future reference */
492 		cfp = (pci_acc_cfblk_t *)&hp->ah_bus_private;
493 		cfp->c_busnum = PCI_REG_BUS_G(pci_rp->pci_phys_hi);
494 		cfp->c_devnum = PCI_REG_DEV_G(pci_rp->pci_phys_hi);
495 		cfp->c_funcnum = PCI_REG_FUNC_G(pci_rp->pci_phys_hi);
496 
497 		return (DDI_SUCCESS);
498 	}
499 
500 	/*
501 	 * range check
502 	 */
503 	if ((offset >= pci_rp->pci_size_low) ||
504 	    (len > pci_rp->pci_size_low) ||
505 	    (offset + len > pci_rp->pci_size_low)) {
506 		return (DDI_FAILURE);
507 	}
508 
509 	/*
510 	 * Adjust offset and length
511 	 * A non-zero length means override the one in the regspec.
512 	 */
513 	pci_rp->pci_phys_low += (uint_t)offset;
514 	if (len != 0)
515 		pci_rp->pci_size_low = len;
516 
517 	/*
518 	 * convert the pci regsec into the generic regspec used by the
519 	 * parent root nexus driver.
520 	 */
521 	switch (space) {
522 	case PCI_ADDR_IO:
523 		reg.regspec_bustype = 1;
524 		break;
525 	case PCI_ADDR_MEM64:
526 		/*
527 		 * We can't handle 64-bit devices that are mapped above
528 		 * 4G or that are larger than 4G.
529 		 */
530 		if (pci_rp->pci_phys_mid != 0 ||
531 		    pci_rp->pci_size_hi != 0)
532 			return (DDI_FAILURE);
533 		/*
534 		 * Other than that, we can treat them as 32-bit mappings
535 		 */
536 		/* FALLTHROUGH */
537 	case PCI_ADDR_MEM32:
538 		reg.regspec_bustype = 0;
539 		break;
540 	default:
541 		return (DDI_FAILURE);
542 	}
543 	reg.regspec_addr = pci_rp->pci_phys_low;
544 	reg.regspec_size = pci_rp->pci_size_low;
545 
546 	mp->map_obj.rp = &reg;
547 	return (ddi_map(dip, mp, (off_t)0, (off_t)0, vaddrp));
548 }
549 
550 
551 /*ARGSUSED*/
552 static int
553 pci_ctlops(dev_info_t *dip, dev_info_t *rdip,
554 	ddi_ctl_enum_t ctlop, void *arg, void *result)
555 {
556 	pci_regspec_t *drv_regp;
557 	uint_t	reglen;
558 	int	rn;
559 	int	totreg;
560 
561 	switch (ctlop) {
562 	case DDI_CTLOPS_REPORTDEV:
563 		if (rdip == (dev_info_t *)0)
564 			return (DDI_FAILURE);
565 		cmn_err(CE_CONT, "?PCI-device: %s@%s, %s%d\n",
566 		    ddi_node_name(rdip), ddi_get_name_addr(rdip),
567 		    ddi_driver_name(rdip),
568 		    ddi_get_instance(rdip));
569 		return (DDI_SUCCESS);
570 
571 	case DDI_CTLOPS_INITCHILD:
572 		return (pci_initchild((dev_info_t *)arg));
573 
574 	case DDI_CTLOPS_UNINITCHILD:
575 		return (pci_removechild((dev_info_t *)arg));
576 
577 	case DDI_CTLOPS_SIDDEV:
578 		return (DDI_SUCCESS);
579 
580 	case DDI_CTLOPS_REGSIZE:
581 	case DDI_CTLOPS_NREGS:
582 		if (rdip == (dev_info_t *)0)
583 			return (DDI_FAILURE);
584 
585 		*(int *)result = 0;
586 		if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, rdip,
587 				DDI_PROP_DONTPASS, "reg", (int **)&drv_regp,
588 				&reglen) != DDI_PROP_SUCCESS) {
589 			return (DDI_FAILURE);
590 		}
591 
592 		totreg = (reglen * sizeof (int)) / sizeof (pci_regspec_t);
593 		if (ctlop == DDI_CTLOPS_NREGS)
594 			*(int *)result = totreg;
595 		else if (ctlop == DDI_CTLOPS_REGSIZE) {
596 			rn = *(int *)arg;
597 			if (rn >= totreg) {
598 				ddi_prop_free(drv_regp);
599 				return (DDI_FAILURE);
600 			}
601 			*(off_t *)result = drv_regp[rn].pci_size_low;
602 		}
603 		ddi_prop_free(drv_regp);
604 
605 		return (DDI_SUCCESS);
606 
607 	case DDI_CTLOPS_POWER: {
608 		power_req_t	*reqp = (power_req_t *)arg;
609 		/*
610 		 * We currently understand reporting of PCI_PM_IDLESPEED
611 		 * capability. Everything else is passed up.
612 		 */
613 		if ((reqp->request_type == PMR_REPORT_PMCAP) &&
614 		    (reqp->req.report_pmcap_req.cap ==  PCI_PM_IDLESPEED)) {
615 
616 			return (DDI_SUCCESS);
617 		}
618 		return (ddi_ctlops(dip, rdip, ctlop, arg, result));
619 	}
620 
621 	default:
622 		return (ddi_ctlops(dip, rdip, ctlop, arg, result));
623 	}
624 
625 	/* NOTREACHED */
626 
627 }
628 
629 /*
630  * pci_intr_ops
631  */
632 static int
633 pci_intr_ops(dev_info_t *pdip, dev_info_t *rdip, ddi_intr_op_t intr_op,
634     ddi_intr_handle_impl_t *hdlp, void *result)
635 {
636 	return (pci_common_intr_ops(pdip, rdip, intr_op, hdlp, result));
637 }
638 
639 
640 static int
641 pci_initchild(dev_info_t *child)
642 {
643 	char name[80];
644 	ddi_acc_handle_t config_handle;
645 	ushort_t command_preserve, command;
646 
647 	if (pci_common_name_child(child, name, 80) != DDI_SUCCESS) {
648 		return (DDI_FAILURE);
649 	}
650 	ddi_set_name_addr(child, name);
651 
652 	/*
653 	 * Pseudo nodes indicate a prototype node with per-instance
654 	 * properties to be merged into the real h/w device node.
655 	 * The interpretation of the unit-address is DD[,F]
656 	 * where DD is the device id and F is the function.
657 	 */
658 	if (ndi_dev_is_persistent_node(child) == 0) {
659 		extern int pci_allow_pseudo_children;
660 
661 		ddi_set_parent_data(child, NULL);
662 
663 		/*
664 		 * Try to merge the properties from this prototype
665 		 * node into real h/w nodes.
666 		 */
667 		if (ndi_merge_node(child, pci_common_name_child) ==
668 		    DDI_SUCCESS) {
669 			/*
670 			 * Merged ok - return failure to remove the node.
671 			 */
672 			ddi_set_name_addr(child, NULL);
673 			return (DDI_FAILURE);
674 		}
675 
676 		/* workaround for ddivs to run under PCI */
677 		if (pci_allow_pseudo_children) {
678 			/*
679 			 * If the "interrupts" property doesn't exist,
680 			 * this must be the ddivs no-intr case, and it returns
681 			 * DDI_SUCCESS instead of DDI_FAILURE.
682 			 */
683 			if (ddi_prop_get_int(DDI_DEV_T_ANY, child,
684 			    DDI_PROP_DONTPASS, "interrupts", -1) == -1)
685 				return (DDI_SUCCESS);
686 			/*
687 			 * Create the ddi_parent_private_data for a pseudo
688 			 * child.
689 			 */
690 			pci_common_set_parent_private_data(child);
691 			return (DDI_SUCCESS);
692 		}
693 
694 		/*
695 		 * The child was not merged into a h/w node,
696 		 * but there's not much we can do with it other
697 		 * than return failure to cause the node to be removed.
698 		 */
699 		cmn_err(CE_WARN, "!%s@%s: %s.conf properties not merged",
700 		    ddi_get_name(child), ddi_get_name_addr(child),
701 		    ddi_get_name(child));
702 		ddi_set_name_addr(child, NULL);
703 		return (DDI_NOT_WELL_FORMED);
704 	}
705 
706 	if (ddi_prop_get_int(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS,
707 	    "interrupts", -1) != -1)
708 		pci_common_set_parent_private_data(child);
709 	else
710 		ddi_set_parent_data(child, NULL);
711 
712 	/*
713 	 * initialize command register
714 	 */
715 	if (pci_config_setup(child, &config_handle) != DDI_SUCCESS)
716 		return (DDI_FAILURE);
717 
718 	/*
719 	 * Support for the "command-preserve" property.
720 	 */
721 	command_preserve = ddi_prop_get_int(DDI_DEV_T_ANY, child,
722 						DDI_PROP_DONTPASS,
723 						"command-preserve", 0);
724 	command = pci_config_get16(config_handle, PCI_CONF_COMM);
725 	command &= (command_preserve | PCI_COMM_BACK2BACK_ENAB);
726 	command |= (pci_command_default & ~command_preserve);
727 	pci_config_put16(config_handle, PCI_CONF_COMM, command);
728 
729 	pci_config_teardown(&config_handle);
730 	return (DDI_SUCCESS);
731 }
732 
733 static int
734 pci_removechild(dev_info_t *dip)
735 {
736 	struct ddi_parent_private_data *pdptr;
737 
738 	if ((pdptr = ddi_get_parent_data(dip)) != NULL) {
739 		kmem_free(pdptr, (sizeof (*pdptr) + sizeof (struct intrspec)));
740 		ddi_set_parent_data(dip, NULL);
741 	}
742 	ddi_set_name_addr(dip, NULL);
743 
744 	/*
745 	 * Strip the node to properly convert it back to prototype form
746 	 */
747 	ddi_remove_minor_node(dip, NULL);
748 
749 	impl_rem_dev_props(dip);
750 
751 	return (DDI_SUCCESS);
752 }
753 
754 
755 /*
756  * These are the get and put functions to be shared with drivers. The
757  * mutex locking is done inside the functions referenced, rather than
758  * here, and is thus shared across PCI child drivers and any other
759  * consumers of PCI config space (such as the ACPI subsystem).
760  *
761  * The configuration space addresses come in as pointers.  This is fine on
762  * a 32-bit system, where the VM space and configuration space are the same
763  * size.  It's not such a good idea on a 64-bit system, where memory
764  * addresses are twice as large as configuration space addresses.  At some
765  * point in the call tree we need to take a stand and say "you are 32-bit
766  * from this time forth", and this seems like a nice self-contained place.
767  */
768 
769 static uint8_t
770 pci_config_rd8(ddi_acc_impl_t *hdlp, uint8_t *addr)
771 {
772 	pci_acc_cfblk_t *cfp;
773 	uint8_t	rval;
774 	int reg;
775 
776 	ASSERT64(((uintptr_t)addr >> 32) == 0);
777 
778 	reg = (int)(uintptr_t)addr;
779 
780 	cfp = (pci_acc_cfblk_t *)&hdlp->ahi_common.ah_bus_private;
781 
782 	rval = (*pci_getb_func)(cfp->c_busnum, cfp->c_devnum, cfp->c_funcnum,
783 	    reg);
784 
785 	return (rval);
786 }
787 
788 static void
789 pci_config_rep_rd8(ddi_acc_impl_t *hdlp, uint8_t *host_addr,
790 	uint8_t *dev_addr, size_t repcount, uint_t flags)
791 {
792 	uint8_t *h, *d;
793 
794 	h = host_addr;
795 	d = dev_addr;
796 
797 	if (flags == DDI_DEV_AUTOINCR)
798 		for (; repcount; repcount--)
799 			*h++ = pci_config_rd8(hdlp, d++);
800 	else
801 		for (; repcount; repcount--)
802 			*h++ = pci_config_rd8(hdlp, d);
803 }
804 
805 static uint16_t
806 pci_config_rd16(ddi_acc_impl_t *hdlp, uint16_t *addr)
807 {
808 	pci_acc_cfblk_t *cfp;
809 	uint16_t rval;
810 	int reg;
811 
812 	ASSERT64(((uintptr_t)addr >> 32) == 0);
813 
814 	reg = (int)(uintptr_t)addr;
815 
816 	cfp = (pci_acc_cfblk_t *)&hdlp->ahi_common.ah_bus_private;
817 
818 	rval = (*pci_getw_func)(cfp->c_busnum, cfp->c_devnum, cfp->c_funcnum,
819 	    reg);
820 
821 	return (rval);
822 }
823 
824 static void
825 pci_config_rep_rd16(ddi_acc_impl_t *hdlp, uint16_t *host_addr,
826 	uint16_t *dev_addr, size_t repcount, uint_t flags)
827 {
828 	uint16_t *h, *d;
829 
830 	h = host_addr;
831 	d = dev_addr;
832 
833 	if (flags == DDI_DEV_AUTOINCR)
834 		for (; repcount; repcount--)
835 			*h++ = pci_config_rd16(hdlp, d++);
836 	else
837 		for (; repcount; repcount--)
838 			*h++ = pci_config_rd16(hdlp, d);
839 }
840 
841 static uint32_t
842 pci_config_rd32(ddi_acc_impl_t *hdlp, uint32_t *addr)
843 {
844 	pci_acc_cfblk_t *cfp;
845 	uint32_t rval;
846 	int reg;
847 
848 	ASSERT64(((uintptr_t)addr >> 32) == 0);
849 
850 	reg = (int)(uintptr_t)addr;
851 
852 	cfp = (pci_acc_cfblk_t *)&hdlp->ahi_common.ah_bus_private;
853 
854 	rval = (*pci_getl_func)(cfp->c_busnum, cfp->c_devnum,
855 	    cfp->c_funcnum, reg);
856 
857 	return (rval);
858 }
859 
860 static void
861 pci_config_rep_rd32(ddi_acc_impl_t *hdlp, uint32_t *host_addr,
862 	uint32_t *dev_addr, size_t repcount, uint_t flags)
863 {
864 	uint32_t *h, *d;
865 
866 	h = host_addr;
867 	d = dev_addr;
868 
869 	if (flags == DDI_DEV_AUTOINCR)
870 		for (; repcount; repcount--)
871 			*h++ = pci_config_rd32(hdlp, d++);
872 	else
873 		for (; repcount; repcount--)
874 			*h++ = pci_config_rd32(hdlp, d);
875 }
876 
877 
878 static void
879 pci_config_wr8(ddi_acc_impl_t *hdlp, uint8_t *addr, uint8_t value)
880 {
881 	pci_acc_cfblk_t *cfp;
882 	int reg;
883 
884 	ASSERT64(((uintptr_t)addr >> 32) == 0);
885 
886 	reg = (int)(uintptr_t)addr;
887 
888 	cfp = (pci_acc_cfblk_t *)&hdlp->ahi_common.ah_bus_private;
889 
890 	(*pci_putb_func)(cfp->c_busnum, cfp->c_devnum,
891 	    cfp->c_funcnum, reg, value);
892 }
893 
894 static void
895 pci_config_rep_wr8(ddi_acc_impl_t *hdlp, uint8_t *host_addr,
896 	uint8_t *dev_addr, size_t repcount, uint_t flags)
897 {
898 	uint8_t *h, *d;
899 
900 	h = host_addr;
901 	d = dev_addr;
902 
903 	if (flags == DDI_DEV_AUTOINCR)
904 		for (; repcount; repcount--)
905 			pci_config_wr8(hdlp, d++, *h++);
906 	else
907 		for (; repcount; repcount--)
908 			pci_config_wr8(hdlp, d, *h++);
909 }
910 
911 static void
912 pci_config_wr16(ddi_acc_impl_t *hdlp, uint16_t *addr, uint16_t value)
913 {
914 	pci_acc_cfblk_t *cfp;
915 	int reg;
916 
917 	ASSERT64(((uintptr_t)addr >> 32) == 0);
918 
919 	reg = (int)(uintptr_t)addr;
920 
921 	cfp = (pci_acc_cfblk_t *)&hdlp->ahi_common.ah_bus_private;
922 
923 	(*pci_putw_func)(cfp->c_busnum, cfp->c_devnum,
924 	    cfp->c_funcnum, reg, value);
925 }
926 
927 static void
928 pci_config_rep_wr16(ddi_acc_impl_t *hdlp, uint16_t *host_addr,
929 	uint16_t *dev_addr, size_t repcount, uint_t flags)
930 {
931 	uint16_t *h, *d;
932 
933 	h = host_addr;
934 	d = dev_addr;
935 
936 	if (flags == DDI_DEV_AUTOINCR)
937 		for (; repcount; repcount--)
938 			pci_config_wr16(hdlp, d++, *h++);
939 	else
940 		for (; repcount; repcount--)
941 			pci_config_wr16(hdlp, d, *h++);
942 }
943 
944 static void
945 pci_config_wr32(ddi_acc_impl_t *hdlp, uint32_t *addr, uint32_t value)
946 {
947 	pci_acc_cfblk_t *cfp;
948 	int reg;
949 
950 	ASSERT64(((uintptr_t)addr >> 32) == 0);
951 
952 	reg = (int)(uintptr_t)addr;
953 
954 	cfp = (pci_acc_cfblk_t *)&hdlp->ahi_common.ah_bus_private;
955 
956 	(*pci_putl_func)(cfp->c_busnum, cfp->c_devnum,
957 	    cfp->c_funcnum, reg, value);
958 }
959 
960 static void
961 pci_config_rep_wr32(ddi_acc_impl_t *hdlp, uint32_t *host_addr,
962 	uint32_t *dev_addr, size_t repcount, uint_t flags)
963 {
964 	uint32_t *h, *d;
965 
966 	h = host_addr;
967 	d = dev_addr;
968 
969 	if (flags == DDI_DEV_AUTOINCR)
970 		for (; repcount; repcount--)
971 			pci_config_wr32(hdlp, d++, *h++);
972 	else
973 		for (; repcount; repcount--)
974 			pci_config_wr32(hdlp, d, *h++);
975 }
976 
977 static uint64_t
978 pci_config_rd64(ddi_acc_impl_t *hdlp, uint64_t *addr)
979 {
980 	uint32_t lw_val;
981 	uint32_t hi_val;
982 	uint32_t *dp;
983 	uint64_t val;
984 
985 	dp = (uint32_t *)addr;
986 	lw_val = pci_config_rd32(hdlp, dp);
987 	dp++;
988 	hi_val = pci_config_rd32(hdlp, dp);
989 	val = ((uint64_t)hi_val << 32) | lw_val;
990 	return (val);
991 }
992 
993 static void
994 pci_config_wr64(ddi_acc_impl_t *hdlp, uint64_t *addr, uint64_t value)
995 {
996 	uint32_t lw_val;
997 	uint32_t hi_val;
998 	uint32_t *dp;
999 
1000 	dp = (uint32_t *)addr;
1001 	lw_val = (uint32_t)(value & 0xffffffff);
1002 	hi_val = (uint32_t)(value >> 32);
1003 	pci_config_wr32(hdlp, dp, lw_val);
1004 	dp++;
1005 	pci_config_wr32(hdlp, dp, hi_val);
1006 }
1007 
1008 static void
1009 pci_config_rep_rd64(ddi_acc_impl_t *hdlp, uint64_t *host_addr,
1010 	uint64_t *dev_addr, size_t repcount, uint_t flags)
1011 {
1012 	if (flags == DDI_DEV_AUTOINCR) {
1013 		for (; repcount; repcount--)
1014 			*host_addr++ = pci_config_rd64(hdlp, dev_addr++);
1015 	} else {
1016 		for (; repcount; repcount--)
1017 			*host_addr++ = pci_config_rd64(hdlp, dev_addr);
1018 	}
1019 }
1020 
1021 static void
1022 pci_config_rep_wr64(ddi_acc_impl_t *hdlp, uint64_t *host_addr,
1023 	uint64_t *dev_addr, size_t repcount, uint_t flags)
1024 {
1025 	if (flags == DDI_DEV_AUTOINCR) {
1026 		for (; repcount; repcount--)
1027 			pci_config_wr64(hdlp, host_addr++, *dev_addr++);
1028 	} else {
1029 		for (; repcount; repcount--)
1030 			pci_config_wr64(hdlp, host_addr++, *dev_addr);
1031 	}
1032 }
1033 
1034 
1035 /*
1036  * When retrofitting this module for pci_tools, functions such as open, close,
1037  * and ioctl are now pulled into this module.  Before this, the functions in
1038  * the pcihp module were referenced directly.  Now they are called or
1039  * referenced through the pcihp cb_ops structure from functions in this module.
1040  */
1041 
1042 static int
1043 pci_open(dev_t *devp, int flags, int otyp, cred_t *credp)
1044 {
1045 	return ((pcihp_get_cb_ops())->cb_open(devp, flags, otyp, credp));
1046 }
1047 
1048 static int
1049 pci_close(dev_t dev, int flags, int otyp, cred_t *credp)
1050 {
1051 	return ((pcihp_get_cb_ops())->cb_close(dev, flags, otyp, credp));
1052 }
1053 
1054 static int
1055 pci_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, int *rvalp)
1056 {
1057 	minor_t		minor = getminor(dev);
1058 	int		instance = PCIHP_AP_MINOR_NUM_TO_INSTANCE(minor);
1059 	pci_state_t	*pci_p = ddi_get_soft_state(pci_statep, instance);
1060 
1061 	if (pci_p == NULL)
1062 		return (ENXIO);
1063 
1064 	return (pci_common_ioctl(pci_p->pci_dip,
1065 	    dev, cmd, arg, mode, credp, rvalp));
1066 }
1067 
1068 
1069 static int
1070 pci_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op,
1071 	int flags, char *name, caddr_t valuep, int *lengthp)
1072 {
1073 	return ((pcihp_get_cb_ops())->cb_prop_op(dev, dip, prop_op, flags,
1074 	    name, valuep, lengthp));
1075 }
1076 
1077 static int
1078 pci_info(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
1079 {
1080 	return (pcihp_info(dip, cmd, arg, result));
1081 }
1082