xref: /illumos-gate/usr/src/uts/sun4/io/ebus.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 #include <sys/types.h>
30 #include <sys/conf.h>
31 #include <sys/ddi.h>
32 #include <sys/sunddi.h>
33 #include <sys/ddi_impldefs.h>
34 #include <sys/ddi_subrdefs.h>
35 #include <sys/pci.h>
36 #include <sys/autoconf.h>
37 #include <sys/cmn_err.h>
38 #include <sys/errno.h>
39 #include <sys/kmem.h>
40 #include <sys/debug.h>
41 #include <sys/sysmacros.h>
42 #include <sys/ebus.h>
43 #include <sys/open.h>
44 #include <sys/stat.h>
45 #include <sys/file.h>
46 #include <sys/sunndi.h>
47 
48 #ifdef DEBUG
49 uint64_t ebus_debug_flags = 0;
50 #endif
51 
52 /*
53  * The values of the following variables are used to initialize
54  * the cache line size and latency timer registers in the ebus
55  * configuration header.  Variables are used instead of constants
56  * to allow tuning from the /etc/system file.
57  */
58 static uint8_t ebus_cache_line_size = 0x10;	/* 64 bytes */
59 static uint8_t ebus_latency_timer = 0x40;	/* 64 PCI cycles */
60 
61 /*
62  * function prototypes for bus ops routines:
63  */
64 static int
65 ebus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
66 	off_t offset, off_t len, caddr_t *addrp);
67 static int
68 ebus_ctlops(dev_info_t *dip, dev_info_t *rdip,
69 	ddi_ctl_enum_t op, void *arg, void *result);
70 static int
71 ebus_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t intr_op,
72     ddi_intr_handle_impl_t *hdlp, void *result);
73 
74 /*
75  * function prototypes for dev ops routines:
76  */
77 static int ebus_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
78 static int ebus_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
79 static int ebus_info(dev_info_t *dip, ddi_info_cmd_t infocmd,
80 	void *arg, void **result);
81 
82 /*
83  * general function prototypes:
84  */
85 static int ebus_config(ebus_devstate_t *ebus_p);
86 static int ebus_apply_range(ebus_devstate_t *ebus_p, dev_info_t *rdip,
87     ebus_regspec_t *ebus_rp, pci_regspec_t *rp);
88 static int febus_apply_range(ebus_devstate_t *ebus_p, dev_info_t *rdip,
89     ebus_regspec_t *ebus_rp, struct regspec *rp);
90 int get_ranges_prop(ebus_devstate_t *ebus_p);
91 
92 #define	getprop(dip, name, addr, intp)		\
93 		ddi_getlongprop(DDI_DEV_T_NONE, (dip), DDI_PROP_DONTPASS, \
94 				(name), (caddr_t)(addr), (intp))
95 
96 static int ebus_open(dev_t *devp, int flags, int otyp, cred_t *credp);
97 static int ebus_close(dev_t dev, int flags, int otyp, cred_t *credp);
98 static int ebus_ioctl(dev_t dev, int cmd, intptr_t arg, int mode,
99 						cred_t *credp, int *rvalp);
100 struct cb_ops ebus_cb_ops = {
101 	ebus_open,			/* open */
102 	ebus_close,			/* close */
103 	nodev,				/* strategy */
104 	nodev,				/* print */
105 	nodev,				/* dump */
106 	nodev,				/* read */
107 	nodev,				/* write */
108 	ebus_ioctl,			/* ioctl */
109 	nodev,				/* devmap */
110 	nodev,				/* mmap */
111 	nodev,				/* segmap */
112 	nochpoll,			/* poll */
113 	ddi_prop_op,			/* cb_prop_op */
114 	NULL,				/* streamtab */
115 	D_NEW | D_MP | D_HOTPLUG,	/* Driver compatibility flag */
116 	CB_REV,				/* rev */
117 	nodev,				/* int (*cb_aread)() */
118 	nodev				/* int (*cb_awrite)() */
119 };
120 
121 /*
122  * bus ops and dev ops structures:
123  */
124 static struct bus_ops ebus_bus_ops = {
125 	BUSO_REV,
126 	ebus_map,
127 	NULL,
128 	NULL,
129 	NULL,
130 	i_ddi_map_fault,
131 	ddi_dma_map,
132 	ddi_dma_allochdl,
133 	ddi_dma_freehdl,
134 	ddi_dma_bindhdl,
135 	ddi_dma_unbindhdl,
136 	ddi_dma_flush,
137 	ddi_dma_win,
138 	ddi_dma_mctl,
139 	ebus_ctlops,
140 	ddi_bus_prop_op,
141 	ndi_busop_get_eventcookie,
142 	ndi_busop_add_eventcall,
143 	ndi_busop_remove_eventcall,
144 	ndi_post_event,
145 	0,
146 	0,
147 	0,
148 	0,
149 	0,
150 	0,
151 	0,
152 	0,
153 	ebus_intr_ops
154 };
155 
156 static struct dev_ops ebus_ops = {
157 	DEVO_REV,
158 	0,
159 	ebus_info,
160 	nulldev,
161 	nulldev,
162 	ebus_attach,
163 	ebus_detach,
164 	nodev,
165 	&ebus_cb_ops,
166 	&ebus_bus_ops
167 };
168 
169 /*
170  * module definitions:
171  */
172 #include <sys/modctl.h>
173 extern struct mod_ops mod_driverops;
174 
175 static struct modldrv modldrv = {
176 	&mod_driverops, 	/* Type of module.  This one is a driver */
177 	"ebus nexus driver %I%", /* Name of module. */
178 	&ebus_ops,		/* driver ops */
179 };
180 
181 static struct modlinkage modlinkage = {
182 	MODREV_1, (void *)&modldrv, NULL
183 };
184 
185 /*
186  * driver global data:
187  */
188 static void *per_ebus_state;		/* per-ebus soft state pointer */
189 
190 
191 int
192 _init(void)
193 {
194 	int e;
195 
196 	/*
197 	 * Initialize per-ebus soft state pointer.
198 	 */
199 	e = ddi_soft_state_init(&per_ebus_state, sizeof (ebus_devstate_t), 1);
200 	if (e != 0)
201 		return (e);
202 
203 	/*
204 	 * Install the module.
205 	 */
206 	e = mod_install(&modlinkage);
207 	if (e != 0)
208 		ddi_soft_state_fini(&per_ebus_state);
209 	return (e);
210 }
211 
212 int
213 _fini(void)
214 {
215 	int e;
216 
217 	/*
218 	 * Remove the module.
219 	 */
220 	e = mod_remove(&modlinkage);
221 	if (e != 0)
222 		return (e);
223 
224 	/*
225 	 * Free the soft state info.
226 	 */
227 	ddi_soft_state_fini(&per_ebus_state);
228 	return (e);
229 }
230 
231 int
232 _info(struct modinfo *modinfop)
233 {
234 	return (mod_info(&modlinkage, modinfop));
235 }
236 
237 /* device driver entry points */
238 
239 /*ARGSUSED*/
240 static int
241 ebus_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
242 {
243 	ebus_devstate_t *ebus_p;	/* per ebus state pointer */
244 	int instance;
245 
246 	instance = getminor((dev_t)arg);
247 	ebus_p = get_ebus_soft_state(instance);
248 
249 	switch (infocmd) {
250 	default:
251 		return (DDI_FAILURE);
252 
253 	case DDI_INFO_DEVT2INSTANCE:
254 		*result = (void *)instance;
255 		return (DDI_SUCCESS);
256 
257 	case DDI_INFO_DEVT2DEVINFO:
258 		if (ebus_p == NULL)
259 			return (DDI_FAILURE);
260 		*result = (void *)ebus_p->dip;
261 		return (DDI_SUCCESS);
262 	}
263 }
264 
265 /*
266  * attach entry point:
267  *
268  * normal attach:
269  *
270  *	create soft state structure (dip, reg, nreg and state fields)
271  *	map in configuration header
272  *	make sure device is properly configured
273  *	report device
274  */
275 static int
276 ebus_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
277 {
278 	ebus_devstate_t *ebus_p;	/* per ebus state pointer */
279 	int instance;
280 
281 	DBG1(D_ATTACH, NULL, "dip=%p\n", dip);
282 
283 	switch (cmd) {
284 	case DDI_ATTACH:
285 
286 		/*
287 		 * Allocate soft state for this instance.
288 		 */
289 		instance = ddi_get_instance(dip);
290 		if (ddi_soft_state_zalloc(per_ebus_state, instance)
291 				!= DDI_SUCCESS) {
292 			DBG(D_ATTACH, NULL, "failed to alloc soft state\n");
293 			return (DDI_FAILURE);
294 		}
295 		ebus_p = get_ebus_soft_state(instance);
296 		ebus_p->dip = dip;
297 		mutex_init(&ebus_p->ebus_mutex, NULL, MUTEX_DRIVER, NULL);
298 		ebus_p->ebus_soft_state = EBUS_SOFT_STATE_CLOSED;
299 
300 		/* Set ebus type field based on ddi name info */
301 		if (strcmp(ddi_get_name(dip), "jbus-ebus") == 0) {
302 			ebus_p->type = FEBUS_TYPE;
303 		} else {
304 			ebus_p->type = EBUS_TYPE;
305 		}
306 
307 		(void) ddi_prop_create(DDI_DEV_T_NONE, dip,
308 			DDI_PROP_CANSLEEP, "no-dma-interrupt-sync", NULL, 0);
309 		/* Get our ranges property for mapping child registers. */
310 		if (get_ranges_prop(ebus_p) != DDI_SUCCESS) {
311 			mutex_destroy(&ebus_p->ebus_mutex);
312 			free_ebus_soft_state(instance);
313 			return (DDI_FAILURE);
314 		}
315 
316 		/*
317 		 * create minor node for devctl interfaces
318 		 */
319 		if (ddi_create_minor_node(dip, "devctl", S_IFCHR, instance,
320 		    DDI_NT_NEXUS, 0) != DDI_SUCCESS) {
321 			mutex_destroy(&ebus_p->ebus_mutex);
322 			free_ebus_soft_state(instance);
323 			return (DDI_FAILURE);
324 		}
325 		/*
326 		 * Make sure the master enable and memory access enable
327 		 * bits are set in the config command register.
328 		 */
329 		if (ebus_p->type == EBUS_TYPE) {
330 			if (!ebus_config(ebus_p)) {
331 				ddi_remove_minor_node(dip, "devctl");
332 				mutex_destroy(&ebus_p->ebus_mutex);
333 				free_ebus_soft_state(instance);
334 				return (DDI_FAILURE);
335 			}
336 		}
337 
338 		/*
339 		 * Make the pci_report_pmcap() call only for RIO
340 		 * implementations.
341 		 */
342 		if (IS_RIO(dip)) {
343 			(void) pci_report_pmcap(dip, PCI_PM_IDLESPEED,
344 			    (void *)EBUS_4MHZ);
345 		}
346 
347 		/*
348 		 * Make the state as attached and report the device.
349 		 */
350 		ebus_p->state = ATTACHED;
351 		ddi_report_dev(dip);
352 		DBG(D_ATTACH, ebus_p, "returning\n");
353 
354 		return (DDI_SUCCESS);
355 
356 	case DDI_RESUME:
357 
358 		instance = ddi_get_instance(dip);
359 		ebus_p = get_ebus_soft_state(instance);
360 
361 		/*
362 		 * Make sure the master enable and memory access enable
363 		 * bits are set in the config command register.
364 		 */
365 		if (ebus_p->type == EBUS_TYPE) {
366 			if (!ebus_config(ebus_p)) {
367 				free_ebus_soft_state(instance);
368 				return (DDI_FAILURE);
369 			}
370 		}
371 
372 		ebus_p->state = RESUMED;
373 		return (DDI_SUCCESS);
374 	}
375 	return (DDI_FAILURE);
376 }
377 
378 /*
379  * detach entry point:
380  */
381 static int
382 ebus_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
383 {
384 	int instance = ddi_get_instance(dip);
385 	ebus_devstate_t *ebus_p = get_ebus_soft_state(instance);
386 
387 	switch (cmd) {
388 	case DDI_DETACH:
389 		DBG1(D_DETACH, ebus_p, "DDI_DETACH dip=%p\n", dip);
390 
391 		switch (ebus_p->type) {
392 		case EBUS_TYPE:
393 			kmem_free(ebus_p->rangespec.rangep, ebus_p->range_cnt *
394 				sizeof (struct ebus_pci_rangespec));
395 			break;
396 		case FEBUS_TYPE:
397 			kmem_free(ebus_p->rangespec.ferangep,
398 				ebus_p->range_cnt *
399 				sizeof (struct febus_rangespec));
400 			break;
401 		default:
402 			DBG(D_ATTACH, NULL, "failed to recognize ebus type\n");
403 			return (DDI_FAILURE);
404 		}
405 
406 		ddi_remove_minor_node(dip, "devctl");
407 		mutex_destroy(&ebus_p->ebus_mutex);
408 		free_ebus_soft_state(instance);
409 		return (DDI_SUCCESS);
410 
411 	case DDI_SUSPEND:
412 		DBG1(D_DETACH, ebus_p, "DDI_SUSPEND dip=%p\n", dip);
413 		ebus_p->state = SUSPENDED;
414 		return (DDI_SUCCESS);
415 	}
416 	DBG(D_ATTACH, NULL, "failed to recognize ebus detach command\n");
417 	return (DDI_FAILURE);
418 }
419 
420 
421 int
422 get_ranges_prop(ebus_devstate_t *ebus_p)
423 {
424 	int nrange, range_len;
425 	struct ebus_pci_rangespec *rangep;
426 	struct febus_rangespec *ferangep;
427 
428 	switch (ebus_p->type) {
429 	case EBUS_TYPE:
430 		if (ddi_getlongprop(DDI_DEV_T_ANY,
431 			ebus_p->dip, DDI_PROP_DONTPASS,
432 			"ranges", (caddr_t)&rangep,
433 			&range_len) != DDI_SUCCESS) {
434 				cmn_err(CE_WARN, "Can't get %s ranges property",
435 					ddi_get_name(ebus_p->dip));
436 				return (DDI_ME_REGSPEC_RANGE);
437 		}
438 
439 		nrange = range_len / sizeof (struct ebus_pci_rangespec);
440 
441 		if (nrange == 0)  {
442 			kmem_free(rangep, range_len);
443 			DBG(D_ATTACH, NULL, "range is equal to zero\n");
444 			return (DDI_FAILURE);
445 		}
446 
447 #ifdef DEBUG
448 		{
449 			int i;
450 
451 			for (i = 0; i < nrange; i++) {
452 				DBG5(D_MAP, ebus_p,
453 					"ebus range addr 0x%x.0x%x PCI range "
454 					"addr 0x%x.0x%x.0x%x ",
455 					rangep[i].ebus_phys_hi,
456 					rangep[i].ebus_phys_low,
457 					rangep[i].pci_phys_hi,
458 					rangep[i].pci_phys_mid,
459 					rangep[i].pci_phys_low);
460 				DBG1(D_MAP, ebus_p,
461 					"Size 0x%x\n", rangep[i].rng_size);
462 			}
463 		}
464 #endif /* DEBUG */
465 
466 		ebus_p->rangespec.rangep = rangep;
467 		ebus_p->range_cnt = nrange;
468 		return (DDI_SUCCESS);
469 
470 	case FEBUS_TYPE:
471 		if (ddi_getlongprop(DDI_DEV_T_ANY, ebus_p->dip,
472 			DDI_PROP_DONTPASS, "ranges",
473 			(caddr_t)&ferangep, &range_len) != DDI_SUCCESS) {
474 			cmn_err(CE_WARN, "Can't get %s ranges property",
475 				ddi_get_name(ebus_p->dip));
476 				return (DDI_ME_REGSPEC_RANGE);
477 		}
478 
479 		nrange = range_len / sizeof (struct febus_rangespec);
480 
481 		if (nrange == 0)  {
482 			kmem_free(ferangep, range_len);
483 			return (DDI_FAILURE);
484 		}
485 
486 #ifdef	DEBUG
487 		{
488 			int i;
489 
490 			for (i = 0; i < nrange; i++) {
491 				DBG4(D_MAP, ebus_p,
492 					"ebus range addr 0x%x.0x%x"
493 					" Parent range "
494 					"addr 0x%x.0x%x ",
495 					ferangep[i].febus_phys_hi,
496 					ferangep[i].febus_phys_low,
497 					ferangep[i].parent_phys_hi,
498 					ferangep[i].parent_phys_low);
499 				DBG1(D_MAP, ebus_p, "Size 0x%x\n",
500 					ferangep[i].rng_size);
501 			}
502 		}
503 #endif /* DEBUG */
504 		ebus_p->rangespec.ferangep = ferangep;
505 		ebus_p->range_cnt = nrange;
506 		return (DDI_SUCCESS);
507 
508 	default:
509 		DBG(D_MAP, NULL, "failed to recognize ebus type\n");
510 		return (DDI_FAILURE);
511 	}
512 }
513 
514 /* bus driver entry points */
515 
516 /*
517  * bus map entry point:
518  *
519  * 	if map request is for an rnumber
520  *		get the corresponding regspec from device node
521  * 	build a new regspec in our parent's format
522  *	build a new map_req with the new regspec
523  *	call up the tree to complete the mapping
524  */
525 static int
526 ebus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
527 	off_t off, off_t len, caddr_t *addrp)
528 {
529 	ebus_devstate_t *ebus_p = get_ebus_soft_state(ddi_get_instance(dip));
530 	ebus_regspec_t *ebus_rp, *ebus_regs;
531 	struct regspec reg;
532 	pci_regspec_t pci_reg;
533 	ddi_map_req_t p_map_request;
534 	int rnumber, i, n;
535 	int rval = DDI_SUCCESS;
536 
537 	/*
538 	 * Handle the mapping according to its type.
539 	 */
540 	DBG4(D_MAP, ebus_p, "rdip=%s%d: off=%x len=%x\n",
541 	    ddi_get_name(rdip), ddi_get_instance(rdip), off, len);
542 	switch (mp->map_type) {
543 	case DDI_MT_REGSPEC:
544 
545 		/*
546 		 * We assume the register specification is in ebus format.
547 		 * We must convert it into a PCI format regspec and pass
548 		 * the request to our parent.
549 		 */
550 		DBG3(D_MAP, ebus_p, "rdip=%s%d: REGSPEC - handlep=%p\n",
551 			ddi_get_name(rdip), ddi_get_instance(rdip),
552 			mp->map_handlep);
553 		ebus_rp = (ebus_regspec_t *)mp->map_obj.rp;
554 		break;
555 
556 	case DDI_MT_RNUMBER:
557 
558 		/*
559 		 * Get the "reg" property from the device node and convert
560 		 * it to our parent's format.
561 		 */
562 		rnumber = mp->map_obj.rnumber;
563 		DBG4(D_MAP, ebus_p, "rdip=%s%d: rnumber=%x handlep=%p\n",
564 			ddi_get_name(rdip), ddi_get_instance(rdip),
565 			rnumber, mp->map_handlep);
566 
567 		if (getprop(rdip, "reg", &ebus_regs, &i) != DDI_SUCCESS) {
568 			DBG(D_MAP, ebus_p, "can't get reg property\n");
569 			return (DDI_ME_RNUMBER_RANGE);
570 		}
571 		n = i / sizeof (ebus_regspec_t);
572 
573 		if (rnumber < 0 || rnumber >= n) {
574 			DBG(D_MAP, ebus_p, "rnumber out of range\n");
575 			return (DDI_ME_RNUMBER_RANGE);
576 		}
577 		ebus_rp = &ebus_regs[rnumber];
578 		break;
579 
580 	default:
581 		return (DDI_ME_INVAL);
582 
583 	}
584 
585 	/* Adjust our reg property with offset and length */
586 	ebus_rp->addr_low += off;
587 	if (len)
588 		ebus_rp->size = len;
589 
590 	/*
591 	 * Now we have a copy the "reg" entry we're attempting to map.
592 	 * Translate this into our parents PCI address using the ranges
593 	 * property.
594 	 */
595 	switch (ebus_p->type) {
596 	case EBUS_TYPE:
597 		rval = ebus_apply_range(ebus_p, rdip, ebus_rp, &pci_reg);
598 		break;
599 	case FEBUS_TYPE:
600 		rval = febus_apply_range(ebus_p, rdip, ebus_rp, &reg);
601 		break;
602 	default:
603 		DBG(D_MAP, NULL, "failed to recognize ebus type\n");
604 		rval = DDI_FAILURE;
605 	}
606 
607 	if (mp->map_type == DDI_MT_RNUMBER)
608 		kmem_free(ebus_regs, i);
609 
610 	if (rval != DDI_SUCCESS)
611 		return (rval);
612 
613 #ifdef DEBUG
614 	switch (ebus_p->type) {
615 	case EBUS_TYPE:
616 		DBG5(D_MAP, ebus_p, "(%x,%x,%x)(%x,%x)\n",
617 			pci_reg.pci_phys_hi,
618 			pci_reg.pci_phys_mid,
619 			pci_reg.pci_phys_low,
620 			pci_reg.pci_size_hi,
621 			pci_reg.pci_size_low);
622 		break;
623 
624 	case FEBUS_TYPE:
625 		DBG3(D_MAP, ebus_p, "%x,%x,%x\n",
626 			reg.regspec_bustype,
627 			reg.regspec_addr,
628 			reg.regspec_size);
629 		break;
630 	}
631 #endif
632 
633 	p_map_request = *mp;
634 	p_map_request.map_type = DDI_MT_REGSPEC;
635 
636 	switch (ebus_p->type) {
637 	case EBUS_TYPE:
638 		p_map_request.map_obj.rp = (struct regspec *)&pci_reg;
639 		break;
640 	case FEBUS_TYPE:
641 		p_map_request.map_obj.rp = &reg;
642 		break;
643 	default:
644 		DBG(D_MAP, NULL, "failed to recognize ebus type\n");
645 		return (DDI_FAILURE);
646 	}
647 
648 	rval = ddi_map(dip, &p_map_request, 0, 0, addrp);
649 	DBG1(D_MAP, ebus_p, "parent returned %x\n", rval);
650 	return (rval);
651 }
652 
653 
654 static int
655 ebus_apply_range(ebus_devstate_t *ebus_p, dev_info_t *rdip,
656     ebus_regspec_t *ebus_rp, pci_regspec_t *rp)
657 {
658 	int b;
659 	int rval = DDI_SUCCESS;
660 	struct ebus_pci_rangespec *rangep = ebus_p->rangespec.rangep;
661 	int nrange = ebus_p->range_cnt;
662 	static char out_of_range[] =
663 	    "Out of range register specification from device node <%s>";
664 
665 	DBG3(D_MAP, ebus_p, "Range Matching Addr 0x%x.%x size 0x%x\n",
666 	    ebus_rp->addr_hi, ebus_rp->addr_low, ebus_rp->size);
667 
668 	for (b = 0; b < nrange; ++b, ++rangep) {
669 
670 		/* Check for the correct space */
671 		if (ebus_rp->addr_hi == rangep->ebus_phys_hi)
672 			/* See if we fit in this range */
673 			if ((ebus_rp->addr_low >=
674 			    rangep->ebus_phys_low) &&
675 			    ((ebus_rp->addr_low + ebus_rp->size - 1)
676 				<= (rangep->ebus_phys_low +
677 				    rangep->rng_size - 1))) {
678 				uint_t addr_offset = ebus_rp->addr_low -
679 				    rangep->ebus_phys_low;
680 				/*
681 				 * Use the range entry to translate
682 				 * the EBUS physical address into the
683 				 * parents PCI space.
684 				 */
685 				rp->pci_phys_hi =
686 				rangep->pci_phys_hi;
687 				rp->pci_phys_mid = rangep->pci_phys_mid;
688 				rp->pci_phys_low =
689 					rangep->pci_phys_low + addr_offset;
690 				rp->pci_size_hi = 0;
691 				rp->pci_size_low =
692 					min(ebus_rp->size, (rangep->rng_size -
693 					addr_offset));
694 
695 				DBG2(D_MAP, ebus_p, "Child hi0x%x lo0x%x ",
696 					rangep->ebus_phys_hi,
697 					rangep->ebus_phys_low);
698 				DBG4(D_MAP, ebus_p, "Parent hi0x%x "
699 					"mid0x%x lo0x%x size 0x%x\n",
700 					rangep->pci_phys_hi,
701 					rangep->pci_phys_mid,
702 					rangep->pci_phys_low,
703 					rangep->rng_size);
704 
705 				break;
706 			}
707 	}
708 
709 	if (b == nrange)  {
710 		cmn_err(CE_WARN, out_of_range, ddi_get_name(rdip));
711 		return (DDI_ME_REGSPEC_RANGE);
712 	}
713 
714 	return (rval);
715 }
716 
717 static int
718 febus_apply_range(ebus_devstate_t *ebus_p, dev_info_t *rdip,
719 		ebus_regspec_t *ebus_rp, struct regspec *rp) {
720 	int b;
721 	int rval = DDI_SUCCESS;
722 	struct febus_rangespec *rangep = ebus_p->rangespec.ferangep;
723 	int nrange = ebus_p->range_cnt;
724 	static char out_of_range[] =
725 		"Out of range register specification from device node <%s>";
726 
727 	DBG3(D_MAP, ebus_p, "Range Matching Addr 0x%x.%x size 0x%x\n",
728 	ebus_rp->addr_hi, ebus_rp->addr_low, ebus_rp->size);
729 
730 	for (b = 0; b < nrange; ++b, ++rangep) {
731 		/* Check for the correct space */
732 		if (ebus_rp->addr_hi == rangep->febus_phys_hi)
733 			/* See if we fit in this range */
734 			if ((ebus_rp->addr_low >=
735 				rangep->febus_phys_low) &&
736 				((ebus_rp->addr_low + ebus_rp->size - 1)
737 				<= (rangep->febus_phys_low +
738 				rangep->rng_size - 1))) {
739 					uint_t addr_offset = ebus_rp->addr_low -
740 					rangep->febus_phys_low;
741 
742 				/*
743 				 * Use the range entry to translate
744 				 * the FEBUS physical address into the
745 				 * parents space.
746 				 */
747 				rp->regspec_bustype =
748 					rangep->parent_phys_hi;
749 				rp->regspec_addr =
750 				rangep->parent_phys_low + addr_offset;
751 				rp->regspec_size =
752 					min(ebus_rp->size, (rangep->rng_size -
753 					addr_offset));
754 
755 				DBG2(D_MAP, ebus_p, "Child hi0x%x lo0x%x ",
756 					rangep->febus_phys_hi,
757 					rangep->febus_phys_low);
758 				DBG3(D_MAP, ebus_p, "Parent hi0x%x "
759 					"lo0x%x size 0x%x\n",
760 					rangep->parent_phys_hi,
761 					rangep->parent_phys_low,
762 					rangep->rng_size);
763 
764 				break;
765 			}
766 	}
767 
768 	if (b == nrange)  {
769 		cmn_err(CE_WARN, out_of_range, ddi_get_name(rdip));
770 		return (DDI_ME_REGSPEC_RANGE);
771 	}
772 
773 	return (rval);
774 }
775 
776 
777 static int
778 ebus_name_child(dev_info_t *child, char *name, int namelen)
779 {
780 	ebus_regspec_t *ebus_rp;
781 	int reglen;
782 
783 	/*
784 	 * Get the address portion of the node name based on the
785 	 * address/offset.
786 	 */
787 	if (ddi_getlongprop(DDI_DEV_T_NONE, child, DDI_PROP_DONTPASS,
788 	    "reg", (caddr_t)&ebus_rp, &reglen) != DDI_SUCCESS) {
789 		return (DDI_FAILURE);
790 	}
791 
792 	(void) snprintf(name, namelen, "%x,%x", ebus_rp->addr_hi,
793 	    ebus_rp->addr_low);
794 	kmem_free(ebus_rp, reglen);
795 
796 	return (DDI_SUCCESS);
797 }
798 
799 /*
800  * control ops entry point:
801  *
802  * Requests handled completely:
803  *	DDI_CTLOPS_INITCHILD
804  *	DDI_CTLOPS_UNINITCHILD
805  *	DDI_CTLOPS_REPORTDEV
806  *	DDI_CTLOPS_REGSIZE
807  *	DDI_CTLOPS_NREGS
808  *
809  * All others passed to parent.
810  */
811 static int
812 ebus_ctlops(dev_info_t *dip, dev_info_t *rdip,
813 	ddi_ctl_enum_t op, void *arg, void *result)
814 {
815 #ifdef DEBUG
816 	ebus_devstate_t *ebus_p = get_ebus_soft_state(ddi_get_instance(dip));
817 #endif
818 	ebus_regspec_t *ebus_rp;
819 	int i, n;
820 	char name[10];
821 
822 	switch (op) {
823 	case DDI_CTLOPS_INITCHILD: {
824 		dev_info_t *child = (dev_info_t *)arg;
825 		/*
826 		 * Set the address portion of the node name based on the
827 		 * address/offset.
828 		 */
829 		DBG2(D_CTLOPS, ebus_p, "DDI_CTLOPS_INITCHILD: rdip=%s%d\n",
830 		    ddi_get_name(child), ddi_get_instance(child));
831 
832 		if (ebus_name_child(child, name, 10) != DDI_SUCCESS) {
833 			DBG(D_CTLOPS, ebus_p, "can't name child\n");
834 			return (DDI_FAILURE);
835 		}
836 
837 		ddi_set_name_addr(child, name);
838 		ddi_set_parent_data(child, NULL);
839 		return (DDI_SUCCESS);
840 	}
841 
842 	case DDI_CTLOPS_UNINITCHILD:
843 		DBG2(D_CTLOPS, ebus_p, "DDI_CTLOPS_UNINITCHILD: rdip=%s%d\n",
844 			ddi_get_name((dev_info_t *)arg),
845 			ddi_get_instance((dev_info_t *)arg));
846 		ddi_set_name_addr((dev_info_t *)arg, NULL);
847 		ddi_remove_minor_node((dev_info_t *)arg, NULL);
848 		impl_rem_dev_props((dev_info_t *)arg);
849 		return (DDI_SUCCESS);
850 
851 	case DDI_CTLOPS_REPORTDEV:
852 
853 		DBG2(D_CTLOPS, ebus_p, "DDI_CTLOPS_REPORTDEV: rdip=%s%d\n",
854 			ddi_get_name(rdip), ddi_get_instance(rdip));
855 		cmn_err(CE_CONT, "?%s%d at %s%d: offset %s\n",
856 			ddi_driver_name(rdip), ddi_get_instance(rdip),
857 			ddi_driver_name(dip), ddi_get_instance(dip),
858 			ddi_get_name_addr(rdip));
859 		return (DDI_SUCCESS);
860 
861 	case DDI_CTLOPS_REGSIZE:
862 
863 		DBG2(D_CTLOPS, ebus_p, "DDI_CTLOPS_REGSIZE: rdip=%s%d\n",
864 			ddi_get_name(rdip), ddi_get_instance(rdip));
865 		if (getprop(rdip, "reg", &ebus_rp, &i) != DDI_SUCCESS) {
866 			DBG(D_CTLOPS, ebus_p, "can't get reg property\n");
867 			return (DDI_FAILURE);
868 		}
869 		n = i / sizeof (ebus_regspec_t);
870 		if (*(int *)arg < 0 || *(int *)arg >= n) {
871 			DBG(D_MAP, ebus_p, "rnumber out of range\n");
872 			kmem_free(ebus_rp, i);
873 			return (DDI_FAILURE);
874 		}
875 		*((off_t *)result) = ebus_rp[*(int *)arg].size;
876 		kmem_free(ebus_rp, i);
877 		return (DDI_SUCCESS);
878 
879 	case DDI_CTLOPS_NREGS:
880 
881 		DBG2(D_CTLOPS, ebus_p, "DDI_CTLOPS_NREGS: rdip=%s%d\n",
882 			ddi_get_name(rdip), ddi_get_instance(rdip));
883 		if (getprop(rdip, "reg", &ebus_rp, &i) != DDI_SUCCESS) {
884 			DBG(D_CTLOPS, ebus_p, "can't get reg property\n");
885 			return (DDI_FAILURE);
886 		}
887 		*((uint_t *)result) = i / sizeof (ebus_regspec_t);
888 		kmem_free(ebus_rp, i);
889 		return (DDI_SUCCESS);
890 	}
891 
892 	/*
893 	 * Now pass the request up to our parent.
894 	 */
895 	DBG2(D_CTLOPS, ebus_p, "passing request to parent: rdip=%s%d\n",
896 		ddi_get_name(rdip), ddi_get_instance(rdip));
897 	return (ddi_ctlops(dip, rdip, op, arg, result));
898 }
899 
900 struct ebus_string_to_pil {
901 	int8_t *string;
902 	uint32_t pil;
903 };
904 
905 static struct ebus_string_to_pil ebus_name_to_pil[] = {{"SUNW,CS4231", 9},
906 							{"audio", 9},
907 							{"fdthree", 8},
908 							{"floppy", 8},
909 							{"ecpp", 3},
910 							{"parallel", 3},
911 							{"su", 12},
912 							{"se", 12},
913 							{"serial", 12},
914 							{"power", 14}};
915 
916 static struct ebus_string_to_pil ebus_device_type_to_pil[] = {{"serial", 12},
917 								{"block", 8}};
918 
919 static int
920 ebus_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t intr_op,
921     ddi_intr_handle_impl_t *hdlp, void *result)
922 {
923 #ifdef DEBUG
924 	ebus_devstate_t *ebus_p = get_ebus_soft_state(ddi_get_instance(dip));
925 #endif
926 	ddi_ispec_t		*ip = (ddi_ispec_t *)hdlp->ih_private;
927 	int32_t			i, max_children, max_device_types, len;
928 	char			*name_p, *device_type_p;
929 
930 	DBG1(D_INTR, ebus_p, "ip 0x%p\n", ip);
931 
932 	/*
933 	 * NOTE: These ops below will never be supported in this nexus
934 	 * driver, hence they always return immediately.
935 	 */
936 	switch (intr_op) {
937 	case DDI_INTROP_GETCAP:
938 		*(int *)result = 0;
939 		return (DDI_SUCCESS);
940 	case DDI_INTROP_SETCAP:
941 	case DDI_INTROP_SETMASK:
942 	case DDI_INTROP_CLRMASK:
943 	case DDI_INTROP_GETPENDING:
944 		return (DDI_ENOTSUP);
945 	default:
946 		break;
947 	}
948 
949 	if ((intr_op == DDI_INTROP_SUPPORTED_TYPES) || ip->is_pil)
950 		goto done;
951 
952 	/*
953 	 * This is a hack to set the PIL for the devices under ebus.
954 	 * We first look up a device by it's specific name, if we can't
955 	 * match the name, we try and match it's device_type property.
956 	 * Lastly we default a PIL level of 1.
957 	 */
958 	name_p = ddi_node_name(rdip);
959 	max_children = sizeof (ebus_name_to_pil) /
960 	    sizeof (struct ebus_string_to_pil);
961 
962 	for (i = 0; i < max_children; i++) {
963 		if (strcmp(ebus_name_to_pil[i].string, name_p) == 0) {
964 			DBG2(D_INTR, ebus_p, "child name %s; match PIL %d\n",
965 			    ebus_name_to_pil[i].string,
966 			    ebus_name_to_pil[i].pil);
967 
968 			ip->is_pil = ebus_name_to_pil[i].pil;
969 			goto done;
970 		}
971 	}
972 
973 	if (ddi_getlongprop(DDI_DEV_T_NONE, rdip, DDI_PROP_DONTPASS,
974 	    "device_type", (caddr_t)&device_type_p, &len) == DDI_SUCCESS) {
975 
976 		max_device_types = sizeof (ebus_device_type_to_pil) /
977 		    sizeof (struct ebus_string_to_pil);
978 
979 		for (i = 0; i < max_device_types; i++) {
980 			if (strcmp(ebus_device_type_to_pil[i].string,
981 			    device_type_p) == 0) {
982 				DBG2(D_INTR, ebus_p, "Device type %s; match "
983 				    "PIL %d\n", ebus_device_type_to_pil[i].
984 				    string, ebus_device_type_to_pil[i].pil);
985 
986 				ip->is_pil = ebus_device_type_to_pil[i].pil;
987 				break;
988 			}
989 		}
990 
991 		kmem_free(device_type_p, len);
992 	}
993 
994 	/*
995 	 * If we get here, we need to set a default value
996 	 * for the PIL.
997 	 */
998 	if (ip->is_pil == 0) {
999 		ip->is_pil = 1;
1000 
1001 		cmn_err(CE_WARN, "%s%d assigning default interrupt level %d "
1002 		    "for device %s%d", ddi_get_name(dip), ddi_get_instance(dip),
1003 		    ip->is_pil, ddi_get_name(rdip), ddi_get_instance(rdip));
1004 	}
1005 
1006 done:
1007 	/* Pass up the request to our parent. */
1008 	return (i_ddi_intr_ops(dip, rdip, intr_op, hdlp, result));
1009 }
1010 
1011 
1012 static int
1013 ebus_config(ebus_devstate_t *ebus_p)
1014 {
1015 	ddi_acc_handle_t conf_handle;
1016 	uint16_t comm;
1017 
1018 	/*
1019 	 * Make sure the master enable and memory access enable
1020 	 * bits are set in the config command register.
1021 	 */
1022 	if (pci_config_setup(ebus_p->dip, &conf_handle) != DDI_SUCCESS)
1023 		return (0);
1024 
1025 	comm = pci_config_get16(conf_handle, PCI_CONF_COMM),
1026 #ifdef DEBUG
1027 	    DBG1(D_MAP, ebus_p, "command register was 0x%x\n", comm);
1028 #endif
1029 	comm |= (PCI_COMM_ME|PCI_COMM_MAE|PCI_COMM_SERR_ENABLE|
1030 	    PCI_COMM_PARITY_DETECT);
1031 	pci_config_put16(conf_handle, PCI_CONF_COMM, comm),
1032 #ifdef DEBUG
1033 	    DBG1(D_MAP, ebus_p, "command register is now 0x%x\n", comm);
1034 #endif
1035 	pci_config_put8(conf_handle, PCI_CONF_CACHE_LINESZ,
1036 	    (uchar_t)ebus_cache_line_size);
1037 	pci_config_put8(conf_handle, PCI_CONF_LATENCY_TIMER,
1038 	    (uchar_t)ebus_latency_timer);
1039 	pci_config_teardown(&conf_handle);
1040 	return (1);
1041 }
1042 
1043 #ifdef DEBUG
1044 extern void prom_printf(const char *, ...);
1045 
1046 static void
1047 ebus_debug(uint_t flag, ebus_devstate_t *ebus_p, char *fmt,
1048 	uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5)
1049 {
1050 	char *s;
1051 
1052 	if (ebus_debug_flags & flag) {
1053 		switch (flag) {
1054 		case D_ATTACH:
1055 			s = "attach"; break;
1056 		case D_DETACH:
1057 			s = "detach"; break;
1058 		case D_MAP:
1059 			s = "map"; break;
1060 		case D_CTLOPS:
1061 			s = "ctlops"; break;
1062 		case D_INTR:
1063 			s = "intr"; break;
1064 		}
1065 		if (ebus_p)
1066 			cmn_err(CE_CONT, "%s%d: %s: ",
1067 				ddi_get_name(ebus_p->dip),
1068 				ddi_get_instance(ebus_p->dip), s);
1069 		else
1070 			cmn_err(CE_CONT, "ebus: ");
1071 		cmn_err(CE_CONT, fmt, a1, a2, a3, a4, a5);
1072 	}
1073 }
1074 #endif
1075 
1076 /* ARGSUSED3 */
1077 static int
1078 ebus_open(dev_t *devp, int flags, int otyp, cred_t *credp)
1079 {
1080 	ebus_devstate_t *ebus_p;
1081 
1082 	/*
1083 	 * Make sure the open is for the right file type.
1084 	 */
1085 	if (otyp != OTYP_CHR)
1086 		return (EINVAL);
1087 
1088 	/*
1089 	 * Get the soft state structure for the device.
1090 	 */
1091 	ebus_p = get_ebus_soft_state(getminor(*devp));
1092 	if (ebus_p == NULL)
1093 		return (ENXIO);
1094 
1095 	/*
1096 	 * Handle the open by tracking the device state.
1097 	 */
1098 	mutex_enter(&ebus_p->ebus_mutex);
1099 	if (flags & FEXCL) {
1100 		if (ebus_p->ebus_soft_state != EBUS_SOFT_STATE_CLOSED) {
1101 			mutex_exit(&ebus_p->ebus_mutex);
1102 			return (EBUSY);
1103 		}
1104 		ebus_p->ebus_soft_state = EBUS_SOFT_STATE_OPEN_EXCL;
1105 	} else {
1106 		if (ebus_p->ebus_soft_state == EBUS_SOFT_STATE_OPEN_EXCL) {
1107 			mutex_exit(&ebus_p->ebus_mutex);
1108 			return (EBUSY);
1109 		}
1110 		ebus_p->ebus_soft_state = EBUS_SOFT_STATE_OPEN;
1111 	}
1112 	mutex_exit(&ebus_p->ebus_mutex);
1113 	return (0);
1114 }
1115 
1116 
1117 /* ARGSUSED */
1118 static int
1119 ebus_close(dev_t dev, int flags, int otyp, cred_t *credp)
1120 {
1121 	ebus_devstate_t *ebus_p;
1122 
1123 	if (otyp != OTYP_CHR)
1124 		return (EINVAL);
1125 
1126 	ebus_p = get_ebus_soft_state(getminor(dev));
1127 	if (ebus_p == NULL)
1128 		return (ENXIO);
1129 
1130 	mutex_enter(&ebus_p->ebus_mutex);
1131 	ebus_p->ebus_soft_state = EBUS_SOFT_STATE_CLOSED;
1132 	mutex_exit(&ebus_p->ebus_mutex);
1133 	return (0);
1134 }
1135 
1136 
1137 /*
1138  * ebus_ioctl: devctl hotplug controls
1139  */
1140 /* ARGSUSED */
1141 static int
1142 ebus_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
1143 	int *rvalp)
1144 {
1145 	ebus_devstate_t *ebus_p;
1146 	dev_info_t *self;
1147 	struct devctl_iocdata *dcp;
1148 	uint_t bus_state;
1149 	int rv = 0;
1150 
1151 	ebus_p = get_ebus_soft_state(getminor(dev));
1152 	if (ebus_p == NULL)
1153 		return (ENXIO);
1154 
1155 	self = ebus_p->dip;
1156 
1157 	/*
1158 	 * We can use the generic implementation for these ioctls
1159 	 */
1160 	switch (cmd) {
1161 	case DEVCTL_DEVICE_GETSTATE:
1162 	case DEVCTL_DEVICE_ONLINE:
1163 	case DEVCTL_DEVICE_OFFLINE:
1164 	case DEVCTL_BUS_GETSTATE:
1165 		return (ndi_devctl_ioctl(self, cmd, arg, mode, 0));
1166 	}
1167 
1168 	/*
1169 	 * read devctl ioctl data
1170 	 */
1171 	if (ndi_dc_allochdl((void *)arg, &dcp) != NDI_SUCCESS)
1172 		return (EFAULT);
1173 
1174 	switch (cmd) {
1175 
1176 	case DEVCTL_DEVICE_RESET:
1177 		rv = ENOTSUP;
1178 		break;
1179 
1180 	case DEVCTL_BUS_QUIESCE:
1181 		if (ndi_get_bus_state(self, &bus_state) == NDI_SUCCESS)
1182 			if (bus_state == BUS_QUIESCED)
1183 				break;
1184 		(void) ndi_set_bus_state(self, BUS_QUIESCED);
1185 		break;
1186 
1187 	case DEVCTL_BUS_UNQUIESCE:
1188 		if (ndi_get_bus_state(self, &bus_state) == NDI_SUCCESS)
1189 			if (bus_state == BUS_ACTIVE)
1190 				break;
1191 		(void) ndi_set_bus_state(self, BUS_ACTIVE);
1192 		break;
1193 
1194 	case DEVCTL_BUS_RESET:
1195 		rv = ENOTSUP;
1196 		break;
1197 
1198 	case DEVCTL_BUS_RESETALL:
1199 		rv = ENOTSUP;
1200 		break;
1201 
1202 	default:
1203 		rv = ENOTTY;
1204 	}
1205 
1206 	ndi_dc_freehdl(dcp);
1207 	return (rv);
1208 }
1209