xref: /titanic_52/usr/src/uts/sun4u/montecarlo/io/acebus.c (revision bf56214c0556fa6864189c826d39dbe156bb22a0)
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 (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2007 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/pci/pci_nexus.h>
37 #include <sys/autoconf.h>
38 #include <sys/cmn_err.h>
39 #include <sys/errno.h>
40 #include <sys/kmem.h>
41 #include <sys/debug.h>
42 #include <sys/sysmacros.h>
43 #include <sys/acebus.h>
44 
45 #ifdef DEBUG
46 static uint_t acebus_debug_flags = 0;
47 #endif
48 
49 /*
50  * The values of the following variables are used to initialize
51  * the cache line size and latency timer registers in the ebus
52  * configuration header.  Variables are used instead of constants
53  * to allow tuning from the /etc/system file.
54  */
55 static uint8_t acebus_cache_line_size = 0x10;	/* 64 bytes */
56 static uint8_t acebus_latency_timer = 0x40;	/* 64 PCI cycles */
57 
58 /*
59  * function prototypes for bus ops routines:
60  */
61 static int
62 acebus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
63 	off_t offset, off_t len, caddr_t *addrp);
64 static int
65 acebus_ctlops(dev_info_t *dip, dev_info_t *rdip,
66 	ddi_ctl_enum_t op, void *arg, void *result);
67 static int
68 acebus_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t intr_op,
69     ddi_intr_handle_impl_t *hdlp, void *result);
70 
71 /*
72  * function prototypes for dev ops routines:
73  */
74 static int acebus_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
75 static int acebus_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
76 
77 /*
78  * general function prototypes:
79  */
80 static int acebus_config(ebus_devstate_t *ebus_p);
81 static int acebus_apply_range(ebus_devstate_t *ebus_p, dev_info_t *rdip,
82     ebus_regspec_t *ebus_rp, pci_regspec_t *rp);
83 static int acebus_get_ranges_prop(ebus_devstate_t *ebus_p);
84 #ifdef	ACEBUS_HOTPLUG
85 static int acebus_update_props(ebus_devstate_t *ebus_p);
86 static int acebus_set_imap(dev_info_t *dip);
87 #endif
88 
89 #define	getprop(dip, name, addr, intp)		\
90 		ddi_getlongprop(DDI_DEV_T_ANY, (dip), DDI_PROP_DONTPASS, \
91 				(name), (caddr_t)(addr), (intp))
92 
93 /*
94  * bus ops and dev ops structures:
95  */
96 static struct bus_ops acebus_bus_ops = {
97 	BUSO_REV,
98 	acebus_map,
99 	NULL,
100 	NULL,
101 	NULL,
102 	i_ddi_map_fault,
103 	ddi_dma_map,
104 	ddi_dma_allochdl,
105 	ddi_dma_freehdl,
106 	ddi_dma_bindhdl,
107 	ddi_dma_unbindhdl,
108 	ddi_dma_flush,
109 	ddi_dma_win,
110 	ddi_dma_mctl,
111 	acebus_ctlops,
112 	ddi_bus_prop_op,
113 	0,				/* (*bus_get_eventcookie)();	*/
114 	0,				/* (*bus_add_eventcall)();	*/
115 	0,				/* (*bus_remove_eventcall)();	*/
116 	0,				/* (*bus_post_event)();		*/
117 	0,				/* (*bus_intr_ctl)();		*/
118 	NULL,				/* (*bus_config)();		*/
119 	NULL,				/* (*bus_unconfig)();		*/
120 	NULL,				/* (*bus_fm_init)();		*/
121 	NULL,				/* (*bus_fm_fini)();		*/
122 	NULL,				/* (*bus_fm_access_enter)();	*/
123 	NULL,				/* (*bus_fm_access_fini)();	*/
124 	NULL,				/* (*bus_power)();		*/
125 	acebus_intr_ops			/* (*bus_intr_op)();		*/
126 };
127 
128 static struct dev_ops acebus_ops = {
129 	DEVO_REV,
130 	0,
131 	ddi_no_info,
132 	nulldev,
133 	nulldev,
134 	acebus_attach,
135 	acebus_detach,
136 	nodev,
137 	(struct cb_ops *)0,
138 	&acebus_bus_ops
139 };
140 
141 /*
142  * module definitions:
143  */
144 #include <sys/modctl.h>
145 extern struct mod_ops mod_driverops;
146 
147 static struct modldrv modldrv = {
148 	&mod_driverops, 	/* Type of module.  This one is a driver */
149 	"Alarm Card ebus nexus v%I%",	/* Name of module. */
150 	&acebus_ops,		/* driver ops */
151 };
152 
153 static struct modlinkage modlinkage = {
154 	MODREV_1, (void *)&modldrv, NULL
155 };
156 
157 /*
158  * driver global data:
159  */
160 static void *per_acebus_state;		/* per-ebus soft state pointer */
161 
162 
163 int
164 _init(void)
165 {
166 	int e;
167 
168 	/*
169 	 * Initialize per-ebus soft state pointer.
170 	 */
171 	e = ddi_soft_state_init(&per_acebus_state, sizeof (ebus_devstate_t), 1);
172 	if (e != 0)
173 		return (e);
174 
175 	/*
176 	 * Install the module.
177 	 */
178 	e = mod_install(&modlinkage);
179 	if (e != 0)
180 		ddi_soft_state_fini(&per_acebus_state);
181 	return (e);
182 }
183 
184 int
185 _fini(void)
186 {
187 	int e;
188 
189 	/*
190 	 * Remove the module.
191 	 */
192 	e = mod_remove(&modlinkage);
193 	if (e != 0)
194 		return (e);
195 
196 	/*
197 	 * Free the soft state info.
198 	 */
199 	ddi_soft_state_fini(&per_acebus_state);
200 	return (e);
201 }
202 
203 int
204 _info(struct modinfo *modinfop)
205 {
206 	return (mod_info(&modlinkage, modinfop));
207 }
208 
209 /* device driver entry points */
210 
211 /*
212  * attach entry point:
213  *
214  * normal attach:
215  *
216  *	create soft state structure (dip, reg, nreg and state fields)
217  *	map in configuration header
218  *	make sure device is properly configured
219  *	report device
220  */
221 static int
222 acebus_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
223 {
224 	ebus_devstate_t *ebus_p;	/* per ebus state pointer */
225 	int instance;
226 
227 	DBG1(D_ATTACH, NULL, "dip=%x\n", dip);
228 	switch (cmd) {
229 	case DDI_ATTACH:
230 
231 		/*
232 		 * Allocate soft state for this instance.
233 		 */
234 		instance = ddi_get_instance(dip);
235 		if (ddi_soft_state_zalloc(per_acebus_state, instance)
236 				!= DDI_SUCCESS) {
237 			DBG(D_ATTACH, NULL, "failed to alloc soft state\n");
238 			return (DDI_FAILURE);
239 		}
240 		ebus_p = get_acebus_soft_state(instance);
241 		ebus_p->dip = dip;
242 
243 		/*
244 		 * Make sure the master enable and memory access enable
245 		 * bits are set in the config command register.
246 		 */
247 		if (!acebus_config(ebus_p)) {
248 			free_acebus_soft_state(instance);
249 			return (DDI_FAILURE);
250 		}
251 
252 		(void) ddi_prop_create(DDI_DEV_T_NONE, dip,
253 			DDI_PROP_CANSLEEP, "no-dma-interrupt-sync", NULL, 0);
254 		/* Get our ranges property for mapping child registers. */
255 		if (acebus_get_ranges_prop(ebus_p) != DDI_SUCCESS) {
256 			free_acebus_soft_state(instance);
257 			return (DDI_FAILURE);
258 		}
259 
260 		/*
261 		 * Make the state as attached and report the device.
262 		 */
263 		ebus_p->state = ATTACHED;
264 		ddi_report_dev(dip);
265 		DBG(D_ATTACH, ebus_p, "returning\n");
266 		return (DDI_SUCCESS);
267 
268 	case DDI_RESUME:
269 
270 		instance = ddi_get_instance(dip);
271 		ebus_p = get_acebus_soft_state(instance);
272 
273 		/*
274 		 * Make sure the master enable and memory access enable
275 		 * bits are set in the config command register.
276 		 */
277 		if (!acebus_config(ebus_p)) {
278 			free_acebus_soft_state(instance);
279 			return (DDI_FAILURE);
280 		}
281 
282 		ebus_p->state = RESUMED;
283 		return (DDI_SUCCESS);
284 	}
285 	return (DDI_FAILURE);
286 }
287 
288 /*
289  * detach entry point:
290  */
291 static int
292 acebus_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
293 {
294 	int instance = ddi_get_instance(dip);
295 	ebus_devstate_t *ebus_p = get_acebus_soft_state(instance);
296 
297 	switch (cmd) {
298 	case DDI_DETACH:
299 		DBG1(D_DETACH, ebus_p, "DDI_DETACH dip=%p\n", dip);
300 		ddi_prop_remove_all(dip);
301 		kmem_free(ebus_p->rangep, ebus_p->range_cnt *
302 		    sizeof (struct ebus_pci_rangespec));
303 		free_acebus_soft_state(instance);
304 		return (DDI_SUCCESS);
305 
306 	case DDI_SUSPEND:
307 		DBG1(D_DETACH, ebus_p, "DDI_SUSPEND dip=%p\n", dip);
308 		ebus_p->state = SUSPENDED;
309 		return (DDI_SUCCESS);
310 	}
311 	return (DDI_FAILURE);
312 }
313 
314 
315 static int
316 acebus_get_ranges_prop(ebus_devstate_t *ebus_p)
317 {
318 	struct ebus_pci_rangespec *rangep;
319 	int nrange, range_len;
320 
321 	if (ddi_getlongprop(DDI_DEV_T_ANY, ebus_p->dip, DDI_PROP_DONTPASS,
322 	    "ranges", (caddr_t)&rangep, &range_len) != DDI_SUCCESS) {
323 
324 		cmn_err(CE_WARN, "%s%d: can't get ranges property",
325 		    ddi_get_name(ebus_p->dip), ddi_get_instance(ebus_p->dip));
326 		return (DDI_ME_REGSPEC_RANGE);
327 	}
328 
329 	nrange = range_len / sizeof (struct ebus_pci_rangespec);
330 
331 	if (nrange == 0)  {
332 		kmem_free(rangep, range_len);
333 		return (DDI_FAILURE);
334 	}
335 
336 #ifdef	DEBUG
337 	/* */ {
338 	int i;
339 
340 	for (i = 0; i < nrange; i++) {
341 		DBG5(D_MAP, ebus_p, "ebus range addr 0x%x.0x%x PCI range "
342 			"addr 0x%x.0x%x.0x%x ", rangep[i].ebus_phys_hi,
343 			    rangep[i].ebus_phys_low, rangep[i].pci_phys_hi,
344 			    rangep[i].pci_phys_mid, rangep[i].pci_phys_low);
345 		DBG1(D_MAP, ebus_p, "Size 0x%x\n", rangep[i].rng_size);
346 	}
347 	}
348 #endif /* DEBUG */
349 
350 	ebus_p->rangep = rangep;
351 	ebus_p->range_cnt = nrange;
352 
353 	return (DDI_SUCCESS);
354 }
355 
356 
357 /* bus driver entry points */
358 
359 /*
360  * bus map entry point:
361  *
362  * 	if map request is for an rnumber
363  *		get the corresponding regspec from device node
364  * 	build a new regspec in our parent's format
365  *	build a new map_req with the new regspec
366  *	call up the tree to complete the mapping
367  */
368 static int
369 acebus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
370 	off_t off, off_t len, caddr_t *addrp)
371 {
372 	ebus_devstate_t *ebus_p = get_acebus_soft_state(ddi_get_instance(dip));
373 	ebus_regspec_t *ebus_rp, *ebus_regs;
374 	pci_regspec_t pci_reg;
375 	ddi_map_req_t p_map_request;
376 	int rnumber, i, n;
377 	int rval = DDI_SUCCESS;
378 
379 	/*
380 	 * Handle the mapping according to its type.
381 	 */
382 	DBG4(D_MAP, ebus_p, "rdip=%s%d: off=%x len=%x\n",
383 	    ddi_get_name(rdip), ddi_get_instance(rdip), off, len);
384 	switch (mp->map_type) {
385 	case DDI_MT_REGSPEC:
386 
387 		/*
388 		 * We assume the register specification is in ebus format.
389 		 * We must convert it into a PCI format regspec and pass
390 		 * the request to our parent.
391 		 */
392 		DBG3(D_MAP, ebus_p, "rdip=%s%d: REGSPEC - handlep=%x\n",
393 			ddi_get_name(rdip), ddi_get_instance(rdip),
394 			mp->map_handlep);
395 		ebus_rp = (ebus_regspec_t *)mp->map_obj.rp;
396 		break;
397 
398 	case DDI_MT_RNUMBER:
399 
400 		/*
401 		 * Get the "reg" property from the device node and convert
402 		 * it to our parent's format.
403 		 */
404 		rnumber = mp->map_obj.rnumber;
405 		DBG4(D_MAP, ebus_p, "rdip=%s%d: rnumber=%x handlep=%x\n",
406 			ddi_get_name(rdip), ddi_get_instance(rdip),
407 			rnumber, mp->map_handlep);
408 
409 		if (getprop(rdip, "reg", &ebus_regs, &i) != DDI_SUCCESS) {
410 			DBG(D_MAP, ebus_p, "can't get reg property\n");
411 			return (DDI_ME_RNUMBER_RANGE);
412 		}
413 		n = i / sizeof (ebus_regspec_t);
414 
415 		if (rnumber < 0 || rnumber >= n) {
416 			DBG(D_MAP, ebus_p, "rnumber out of range\n");
417 			return (DDI_ME_RNUMBER_RANGE);
418 		}
419 		ebus_rp = &ebus_regs[rnumber];
420 		break;
421 
422 	default:
423 		return (DDI_ME_INVAL);
424 
425 	}
426 
427 	/* Adjust our reg property with offset and length */
428 	ebus_rp->addr_low += off;
429 	if (len)
430 		ebus_rp->size = len;
431 
432 	/*
433 	 * Now we have a copy the "reg" entry we're attempting to map.
434 	 * Translate this into our parents PCI address using the ranges
435 	 * property.
436 	 */
437 	rval = acebus_apply_range(ebus_p, rdip, ebus_rp, &pci_reg);
438 
439 	if (mp->map_type == DDI_MT_RNUMBER)
440 		kmem_free((caddr_t)ebus_regs, i);
441 
442 	if (rval != DDI_SUCCESS)
443 		return (rval);
444 
445 #ifdef	ACEBUS_HOTPLUG
446 	/*
447 	 * The map operation provides a translated (not a re-assigned, or
448 	 * relocated) ebus address for the child in its address space(range).
449 	 * Ebus address space is relocatible but its child address space
450 	 * is not. As specified by their 'reg' properties, they reside
451 	 * at a fixed offset in their parent's (ebus's) space.
452 	 *
453 	 * By setting this bit, we will not run into HostPCI nexus
454 	 * trying to relocate a translated ebus address (which is already
455 	 * relocated) and failing the operation.
456 	 * The reason for doing this here is that the PCI hotplug configurator
457 	 * always marks the ebus space as relocatible (unlike OBP) and that
458 	 * information is implied for the child too, which is wrong.
459 	 */
460 	pci_reg.pci_phys_hi |= PCI_RELOCAT_B;
461 #endif
462 #ifdef DEBUG
463 	DBG5(D_MAP, ebus_p, "(%x,%x,%x)(%x,%x)\n",
464 		pci_reg.pci_phys_hi,
465 		pci_reg.pci_phys_mid,
466 		pci_reg.pci_phys_low,
467 		pci_reg.pci_size_hi,
468 		pci_reg.pci_size_low);
469 #endif
470 
471 	p_map_request = *mp;
472 	p_map_request.map_type = DDI_MT_REGSPEC;
473 	p_map_request.map_obj.rp = (struct regspec *)&pci_reg;
474 	rval = ddi_map(dip, &p_map_request, 0, 0, addrp);
475 	DBG1(D_MAP, ebus_p, "parent returned %x\n", rval);
476 	return (rval);
477 }
478 
479 
480 static int
481 acebus_apply_range(ebus_devstate_t *ebus_p, dev_info_t *rdip,
482     ebus_regspec_t *ebus_rp, pci_regspec_t *rp)
483 {
484 	int b;
485 	int rval = DDI_SUCCESS;
486 	struct ebus_pci_rangespec *rangep = ebus_p->rangep;
487 	int nrange = ebus_p->range_cnt;
488 	static const char out_of_range[] =
489 	    "Out of range register specification from device node <%s>";
490 
491 	DBG3(D_MAP, ebus_p, "Range Matching Addr 0x%x.%x size 0x%x\n",
492 	    ebus_rp->addr_hi, ebus_rp->addr_low, ebus_rp->size);
493 
494 	for (b = 0; b < nrange; ++b, ++rangep) {
495 
496 		/* Check for the correct space */
497 		if (ebus_rp->addr_hi == rangep->ebus_phys_hi)
498 			/* See if we fit in this range */
499 			if ((ebus_rp->addr_low >=
500 			    rangep->ebus_phys_low) &&
501 			    ((ebus_rp->addr_low + ebus_rp->size - 1)
502 				<= (rangep->ebus_phys_low +
503 				    rangep->rng_size - 1))) {
504 				uint_t addr_offset = ebus_rp->addr_low -
505 				    rangep->ebus_phys_low;
506 				/*
507 				 * Use the range entry to translate
508 				 * the EBUS physical address into the
509 				 * parents PCI space.
510 				 */
511 				rp->pci_phys_hi =
512 				    rangep->pci_phys_hi;
513 				rp->pci_phys_mid = rangep->pci_phys_mid;
514 				rp->pci_phys_low =
515 				    rangep->pci_phys_low + addr_offset;
516 				rp->pci_size_hi = 0;
517 				rp->pci_size_low =
518 				    min(ebus_rp->size, (rangep->rng_size -
519 					addr_offset));
520 
521 				DBG2(D_MAP, ebus_p, "Child hi0x%x lo0x%x ",
522 				    rangep->ebus_phys_hi,
523 				    rangep->ebus_phys_low);
524 				DBG4(D_MAP, ebus_p, "Parent hi0x%x "
525 					"mid0x%x lo0x%x size 0x%x\n",
526 					    rangep->pci_phys_hi,
527 					    rangep->pci_phys_mid,
528 					    rangep->pci_phys_low,
529 					    rangep->rng_size);
530 
531 				break;
532 			}
533 	}
534 
535 	if (b == nrange)  {
536 		cmn_err(CE_WARN, out_of_range, ddi_get_name(rdip));
537 		return (DDI_ME_REGSPEC_RANGE);
538 	}
539 
540 	return (rval);
541 }
542 
543 
544 /*
545  * control ops entry point:
546  *
547  * Requests handled completely:
548  *	DDI_CTLOPS_INITCHILD
549  *	DDI_CTLOPS_UNINITCHILD
550  *	DDI_CTLOPS_REPORTDEV
551  *	DDI_CTLOPS_REGSIZE
552  *	DDI_CTLOPS_NREGS
553  *
554  * All others passed to parent.
555  */
556 static int
557 acebus_ctlops(dev_info_t *dip, dev_info_t *rdip,
558 	ddi_ctl_enum_t op, void *arg, void *result)
559 {
560 #ifdef DEBUG
561 	ebus_devstate_t *ebus_p = get_acebus_soft_state(ddi_get_instance(dip));
562 #endif
563 	ebus_regspec_t *ebus_rp;
564 	int32_t reglen;
565 	int i, n;
566 	char name[10];
567 
568 	switch (op) {
569 	case DDI_CTLOPS_INITCHILD: {
570 		dev_info_t *child = (dev_info_t *)arg;
571 		/*
572 		 * Set the address portion of the node name based on the
573 		 * address/offset.
574 		 */
575 		DBG2(D_CTLOPS, ebus_p, "DDI_CTLOPS_INITCHILD: rdip=%s%d\n",
576 		    ddi_get_name(child), ddi_get_instance(child));
577 
578 		if (ddi_getlongprop(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS,
579 		    "reg", (caddr_t)&ebus_rp, &reglen) != DDI_SUCCESS) {
580 
581 			DBG(D_CTLOPS, ebus_p, "can't get reg property\n");
582 			return (DDI_FAILURE);
583 
584 		}
585 
586 		(void) sprintf(name, "%x,%x", ebus_rp->addr_hi,
587 		    ebus_rp->addr_low);
588 		ddi_set_name_addr(child, name);
589 		kmem_free((caddr_t)ebus_rp, reglen);
590 
591 		ddi_set_parent_data(child, NULL);
592 
593 		return (DDI_SUCCESS);
594 
595 	}
596 
597 	case DDI_CTLOPS_UNINITCHILD:
598 		DBG2(D_CTLOPS, ebus_p, "DDI_CTLOPS_UNINITCHILD: rdip=%s%d\n",
599 			ddi_get_name((dev_info_t *)arg),
600 			ddi_get_instance((dev_info_t *)arg));
601 		ddi_set_name_addr((dev_info_t *)arg, NULL);
602 		ddi_remove_minor_node((dev_info_t *)arg, NULL);
603 		impl_rem_dev_props((dev_info_t *)arg);
604 		return (DDI_SUCCESS);
605 
606 	case DDI_CTLOPS_REPORTDEV:
607 
608 		DBG2(D_CTLOPS, ebus_p, "DDI_CTLOPS_REPORTDEV: rdip=%s%d\n",
609 			ddi_get_name(rdip), ddi_get_instance(rdip));
610 		cmn_err(CE_CONT, "?%s%d at %s%d: offset %s\n",
611 			ddi_driver_name(rdip), ddi_get_instance(rdip),
612 			ddi_driver_name(dip), ddi_get_instance(dip),
613 			ddi_get_name_addr(rdip));
614 		return (DDI_SUCCESS);
615 
616 	case DDI_CTLOPS_REGSIZE:
617 
618 		DBG2(D_CTLOPS, ebus_p, "DDI_CTLOPS_REGSIZE: rdip=%s%d\n",
619 			ddi_get_name(rdip), ddi_get_instance(rdip));
620 		if (getprop(rdip, "reg", &ebus_rp, &i) != DDI_SUCCESS) {
621 			DBG(D_CTLOPS, ebus_p, "can't get reg property\n");
622 			return (DDI_FAILURE);
623 		}
624 		n = i / sizeof (ebus_regspec_t);
625 		if (*(int *)arg < 0 || *(int *)arg >= n) {
626 			DBG(D_MAP, ebus_p, "rnumber out of range\n");
627 			kmem_free((caddr_t)ebus_rp, i);
628 			return (DDI_FAILURE);
629 		}
630 		*((off_t *)result) = ebus_rp[*(int *)arg].size;
631 		kmem_free((caddr_t)ebus_rp, i);
632 		return (DDI_SUCCESS);
633 
634 	case DDI_CTLOPS_NREGS:
635 
636 		DBG2(D_CTLOPS, ebus_p, "DDI_CTLOPS_NREGS: rdip=%s%d\n",
637 			ddi_get_name(rdip), ddi_get_instance(rdip));
638 		if (getprop(rdip, "reg", &ebus_rp, &i) != DDI_SUCCESS) {
639 			DBG(D_CTLOPS, ebus_p, "can't get reg property\n");
640 			return (DDI_FAILURE);
641 		}
642 		*((uint_t *)result) = i / sizeof (ebus_regspec_t);
643 		kmem_free((caddr_t)ebus_rp, i);
644 		return (DDI_SUCCESS);
645 	}
646 
647 	/*
648 	 * Now pass the request up to our parent.
649 	 */
650 	DBG2(D_CTLOPS, ebus_p, "passing request to parent: rdip=%s%d\n",
651 		ddi_get_name(rdip), ddi_get_instance(rdip));
652 	return (ddi_ctlops(dip, rdip, op, arg, result));
653 }
654 
655 struct ebus_string_to_pil {
656 	int8_t *string;
657 	uint32_t pil;
658 };
659 
660 static struct ebus_string_to_pil acebus_name_to_pil[] = {{"SUNW,CS4231", 9},
661 						    {"fdthree", 8},
662 						    {"ecpp", 3},
663 						    {"su", 12},
664 						    {"se", 12},
665 						    {"power", 14}};
666 
667 static struct ebus_string_to_pil acebus_device_type_to_pil[] = {{"serial", 12},
668 								{"block", 8}};
669 
670 static int
671 acebus_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t intr_op,
672     ddi_intr_handle_impl_t *hdlp, void *result)
673 {
674 #ifdef DEBUG
675 	ebus_devstate_t *ebus_p = get_acebus_soft_state(ddi_get_instance(dip));
676 #endif
677 	int8_t		*name, *device_type;
678 	int32_t		i, max_children, max_device_types, len;
679 
680 	/*
681 	 * NOTE: These ops below will never be supported in this nexus
682 	 * driver, hence they always return immediately.
683 	 */
684 	switch (intr_op) {
685 	case DDI_INTROP_GETCAP:
686 		*(int *)result = DDI_INTR_FLAG_LEVEL;
687 		return (DDI_SUCCESS);
688 	case DDI_INTROP_SUPPORTED_TYPES:
689 		*(int *)result = i_ddi_get_intx_nintrs(rdip) ?
690 		    DDI_INTR_TYPE_FIXED : 0;
691 		return (DDI_SUCCESS);
692 	case DDI_INTROP_SETCAP:
693 	case DDI_INTROP_SETMASK:
694 	case DDI_INTROP_CLRMASK:
695 	case DDI_INTROP_GETPENDING:
696 		return (DDI_ENOTSUP);
697 	default:
698 		break;
699 	}
700 
701 	if (hdlp->ih_pri)
702 		goto done;
703 
704 	/*
705 	 * This is a hack to set the PIL for the devices under ebus.
706 	 * We first look up a device by it's specific name, if we can't
707 	 * match the name, we try and match it's device_type property.
708 	 * Lastly we default a PIL level of 1.
709 	 */
710 	DBG1(D_INTR, ebus_p, "ebus_p %p\n", ebus_p);
711 
712 	name = ddi_get_name(rdip);
713 	max_children = sizeof (acebus_name_to_pil) /
714 	    sizeof (struct ebus_string_to_pil);
715 
716 	for (i = 0; i < max_children; i++) {
717 		if (strcmp(acebus_name_to_pil[i].string, name) == 0) {
718 			DBG2(D_INTR, ebus_p, "child name %s; match PIL %d\n",
719 			    acebus_name_to_pil[i].string,
720 			    acebus_name_to_pil[i].pil);
721 
722 			hdlp->ih_pri = acebus_name_to_pil[i].pil;
723 			goto done;
724 		}
725 	}
726 
727 	if (ddi_getlongprop(DDI_DEV_T_ANY, rdip, DDI_PROP_DONTPASS,
728 	    "device_type", (caddr_t)&device_type, &len) == DDI_SUCCESS) {
729 
730 		max_device_types = sizeof (acebus_device_type_to_pil) /
731 		    sizeof (struct ebus_string_to_pil);
732 
733 		for (i = 0; i < max_device_types; i++) {
734 			if (strcmp(acebus_device_type_to_pil[i].string,
735 			    device_type) == 0) {
736 				DBG2(D_INTR, ebus_p,
737 				    "Device type %s; match PIL %d\n",
738 				    acebus_device_type_to_pil[i].string,
739 				    acebus_device_type_to_pil[i].pil);
740 
741 				hdlp->ih_pri = acebus_device_type_to_pil[i].pil;
742 				break;
743 			}
744 		}
745 
746 		kmem_free(device_type, len);
747 	}
748 
749 	/*
750 	 * If we get here, we need to set a default value
751 	 * for the PIL.
752 	 */
753 	if (hdlp->ih_pri == 0) {
754 		hdlp->ih_pri = 1;
755 		cmn_err(CE_WARN, "%s%d assigning default interrupt level %d "
756 		    "for device %s%d", ddi_driver_name(dip),
757 		    ddi_get_instance(dip), hdlp->ih_pri, ddi_driver_name(rdip),
758 		    ddi_get_instance(rdip));
759 	}
760 
761 done:
762 	/* Pass up the request to our parent. */
763 	return (i_ddi_intr_ops(dip, rdip, intr_op, hdlp, result));
764 }
765 
766 
767 static int
768 acebus_config(ebus_devstate_t *ebus_p)
769 {
770 	ddi_acc_handle_t conf_handle;
771 	uint16_t comm;
772 #ifdef	ACEBUS_HOTPLUG
773 	int tcr_reg;
774 	caddr_t csr_io;
775 	ddi_device_acc_attr_t csr_attr = {   /* CSR map attributes */
776 		DDI_DEVICE_ATTR_V0,
777 		DDI_STRUCTURE_LE_ACC,
778 		DDI_STRICTORDER_ACC
779 	};
780 	ddi_acc_handle_t csr_handle;
781 #endif
782 
783 	/*
784 	 * Make sure the master enable and memory access enable
785 	 * bits are set in the config command register.
786 	 */
787 	if (pci_config_setup(ebus_p->dip, &conf_handle) != DDI_SUCCESS)
788 		return (0);
789 
790 	comm = pci_config_get16(conf_handle, PCI_CONF_COMM),
791 #ifdef DEBUG
792 	    DBG1(D_ATTACH, ebus_p, "command register was 0x%x\n", comm);
793 #endif
794 	comm |= (PCI_COMM_ME|PCI_COMM_MAE|PCI_COMM_SERR_ENABLE|
795 	    PCI_COMM_PARITY_DETECT);
796 	pci_config_put16(conf_handle, PCI_CONF_COMM, comm),
797 #ifdef DEBUG
798 	    DBG1(D_MAP, ebus_p, "command register is now 0x%x\n",
799 		pci_config_get16(conf_handle, PCI_CONF_COMM));
800 #endif
801 	pci_config_put8(conf_handle, PCI_CONF_CACHE_LINESZ,
802 	    (uchar_t)acebus_cache_line_size);
803 	pci_config_put8(conf_handle, PCI_CONF_LATENCY_TIMER,
804 	    (uchar_t)acebus_latency_timer);
805 	pci_config_teardown(&conf_handle);
806 
807 #ifdef	ACEBUS_HOTPLUG
808 	if (acebus_update_props(ebus_p) != DDI_SUCCESS) {
809 		cmn_err(CE_WARN, "%s%d: Could not update special properties.",
810 		    ddi_driver_name(ebus_p->dip),
811 		    ddi_get_instance(ebus_p->dip));
812 		return (0);
813 	}
814 
815 	if (ddi_regs_map_setup(ebus_p->dip, CSR_IO_RINDEX,
816 	    (caddr_t *)&csr_io, 0, CSR_SIZE, &csr_attr,
817 	    &csr_handle) != DDI_SUCCESS) {
818 		cmn_err(CE_WARN, "%s%d: Could not map Ebus CSR.",
819 		    ddi_driver_name(ebus_p->dip),
820 		    ddi_get_instance(ebus_p->dip));
821 	}
822 #ifdef	DEBUG
823 	if (acebus_debug_flags) {
824 		DBG3(D_ATTACH, ebus_p, "tcr[123] = %x,%x,%x\n",
825 			ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io +
826 								TCR1_OFF)),
827 			ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io +
828 								TCR2_OFF)),
829 			ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io +
830 								TCR3_OFF)));
831 		DBG2(D_ATTACH, ebus_p, "pmd-aux=%x, freq-aux=%x\n",
832 			ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io +
833 							PMD_AUX_OFF)),
834 			ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io +
835 							FREQ_AUX_OFF)));
836 #ifdef ACEBUS_DEBUG
837 		for (comm = 0; comm < 4; comm++)
838 			prom_printf("dcsr%d=%x, dacr%d=%x, dbcr%d=%x\n", comm,
839 			ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io +
840 					0x700000+(0x2000*comm))), comm,
841 			ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io +
842 					0x700000+(0x2000*comm)+4)), comm,
843 			ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io +
844 					0x700000+(0x2000*comm)+8)));
845 #endif
846 	} /* acebus_debug_flags */
847 #endif
848 	/* If TCR registers are not initialized, initialize them here */
849 	tcr_reg = ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io +
850 								TCR1_OFF));
851 	if ((tcr_reg == 0) || (tcr_reg == -1))
852 		ddi_put32(csr_handle, (uint32_t *)((caddr_t)csr_io + TCR1_OFF),
853 								TCR1_REGVAL);
854 	tcr_reg = ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io +
855 								TCR2_OFF));
856 	if ((tcr_reg == 0) || (tcr_reg == -1))
857 		ddi_put32(csr_handle, (uint32_t *)((caddr_t)csr_io + TCR2_OFF),
858 								TCR2_REGVAL);
859 	tcr_reg = ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io +
860 								TCR3_OFF));
861 	if ((tcr_reg == 0) || (tcr_reg == -1))
862 		ddi_put32(csr_handle, (uint32_t *)((caddr_t)csr_io + TCR3_OFF),
863 								TCR3_REGVAL);
864 #ifdef	DEBUG
865 	if (acebus_debug_flags) {
866 		DBG3(D_ATTACH, ebus_p, "wrote tcr[123] = %x,%x,%x\n",
867 			ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io +
868 								TCR1_OFF)),
869 			ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io +
870 								TCR2_OFF)),
871 			ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io +
872 								TCR3_OFF)));
873 	}
874 #endif
875 
876 	ddi_regs_map_free(&csr_handle);
877 #endif	/* ACEBUS_HOTPLUG */
878 	return (1);	/* return success */
879 }
880 
881 #ifdef DEBUG
882 extern void prom_printf(const char *, ...);
883 
884 static void
885 acebus_debug(uint_t flag, ebus_devstate_t *ebus_p, char *fmt,
886 	uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5)
887 {
888 	char *s;
889 
890 	if (acebus_debug_flags & flag) {
891 		switch (flag) {
892 		case D_ATTACH:
893 			s = "attach"; break;
894 		case D_DETACH:
895 			s = "detach"; break;
896 		case D_MAP:
897 			s = "map"; break;
898 		case D_CTLOPS:
899 			s = "ctlops"; break;
900 		case D_INTR:
901 			s = "intr"; break;
902 		}
903 		if (ebus_p)
904 			cmn_err(CE_CONT, "%s%d: %s: ",
905 				ddi_get_name(ebus_p->dip),
906 				ddi_get_instance(ebus_p->dip), s);
907 		else
908 			cmn_err(CE_CONT, "ebus: ");
909 		cmn_err(CE_CONT, fmt, a1, a2, a3, a4, a5);
910 	}
911 }
912 #endif
913 
914 #ifdef	ACEBUS_HOTPLUG
915 #define	EBUS_CHILD_PHYS_LOW_RANGE	0x10
916 #define	EBUS_CHILD_PHYS_HI_RANGE	0x14
917 
918 static int
919 acebus_update_props(ebus_devstate_t *ebus_p)
920 {
921 	dev_info_t *dip = ebus_p->dip;
922 	struct ebus_pci_rangespec er[2], *erp;
923 	pci_regspec_t *pci_rp, *prp;
924 	int length, rnums, imask[3], i, found = 0;
925 
926 	/*
927 	 * If "ranges" property is found, then the device is initialized
928 	 * by OBP, hence simply return.
929 	 * Otherwise we create all the properties here.
930 	 */
931 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
932 	    "ranges", (int **)&erp, (uint_t *)&length) == DDI_PROP_SUCCESS) {
933 		ddi_prop_free(erp);
934 		return (DDI_SUCCESS);
935 	}
936 
937 	/*
938 	 * interrupt-map is the only property that comes from a .conf file.
939 	 * Since it doesn't have the nodeid field set, it must be done here.
940 	 * Other properties can come from OBP or created here.
941 	 */
942 	if (acebus_set_imap(dip) != DDI_SUCCESS) {
943 		return (DDI_FAILURE);
944 	}
945 
946 	/*
947 	 * Create the "ranges" property.
948 	 * Ebus has BAR0 and BAR1 allocated (both in memory space).
949 	 * Other BARs are 0.
950 	 * Hence there are 2 memory ranges it operates in. (one for each BAR).
951 	 * ie. there are 2 entries in its ranges property.
952 	 */
953 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip,
954 			DDI_PROP_DONTPASS, "assigned-addresses",
955 			(int **)&pci_rp, (uint_t *)&length)
956 						!= DDI_PROP_SUCCESS) {
957 		cmn_err(CE_WARN, "%s%d: Could not get assigned-addresses",
958 			ddi_driver_name(dip), ddi_get_instance(dip));
959 		return (DDI_FAILURE);
960 	}
961 	/*
962 	 * Create the 1st mem range in which it operates corresponding
963 	 * to BAR0
964 	 */
965 	er[0].ebus_phys_hi = EBUS_CHILD_PHYS_LOW_RANGE;
966 	rnums = (length * sizeof (int))/sizeof (pci_regspec_t);
967 	for (i = 0; i < rnums; i++) {
968 		prp = pci_rp + i;
969 		if (PCI_REG_REG_G(prp->pci_phys_hi) == er[0].ebus_phys_hi) {
970 			found = 1;
971 			break;
972 		}
973 	}
974 	if (!found) {
975 		cmn_err(CE_WARN, "No assigned space for memory range 0.");
976 		ddi_prop_free(pci_rp);
977 		return (DDI_FAILURE);
978 	}
979 	found = 0;
980 	er[0].ebus_phys_low = 0;
981 	er[0].pci_phys_hi = prp->pci_phys_hi;
982 	er[0].pci_phys_mid = prp->pci_phys_mid;
983 	er[0].pci_phys_low = prp->pci_phys_low;
984 	er[0].rng_size = prp->pci_size_low;
985 
986 	/*
987 	 * Create the 2nd mem range in which it operates corresponding
988 	 * to BAR1
989 	 */
990 	er[1].ebus_phys_hi = EBUS_CHILD_PHYS_HI_RANGE;
991 	for (i = 0; i < rnums; i++) {
992 		prp = pci_rp + i;
993 		if (PCI_REG_REG_G(prp->pci_phys_hi) == er[1].ebus_phys_hi) {
994 			found = 1;
995 			break;
996 		}
997 	}
998 	if (!found) {
999 		cmn_err(CE_WARN, "No assigned space for memory range 1.");
1000 		ddi_prop_free(pci_rp);
1001 		return (DDI_FAILURE);
1002 	}
1003 	er[1].ebus_phys_low = 0;
1004 	er[1].pci_phys_hi = prp->pci_phys_hi;
1005 	er[1].pci_phys_mid = prp->pci_phys_mid;
1006 	er[1].pci_phys_low = prp->pci_phys_low;
1007 	er[1].rng_size = prp->pci_size_low;
1008 
1009 	ddi_prop_free(pci_rp);
1010 	length = sizeof (er) / sizeof (int);
1011 	if (ddi_prop_update_int_array(DDI_DEV_T_NONE, dip,
1012 	    "ranges", (int *)er, length) != DDI_PROP_SUCCESS) {
1013 		cmn_err(CE_WARN, "%s%d: Could not create ranges property",
1014 			ddi_driver_name(dip), ddi_get_instance(dip));
1015 		return (DDI_FAILURE);
1016 	}
1017 	/* The following properties are as defined by PCI 1275 bindings. */
1018 	if (ddi_prop_update_int(DDI_DEV_T_NONE, dip,
1019 	    "#address-cells", 2) != DDI_PROP_SUCCESS)
1020 			return (DDI_FAILURE);
1021 	if (ddi_prop_update_int(DDI_DEV_T_NONE, dip,
1022 	    "#size-cells", 1) != DDI_PROP_SUCCESS)
1023 			return (DDI_FAILURE);
1024 	if (ddi_prop_update_int(DDI_DEV_T_NONE, dip,
1025 	    "#interrupt-cells", 1) != DDI_PROP_SUCCESS)
1026 			return (DDI_FAILURE);
1027 
1028 	imask[0] = 0x1f;
1029 	imask[1] = 0x00ffffff;
1030 	imask[2] = 0x00000003;
1031 	length = sizeof (imask) / sizeof (int);
1032 	if (ddi_prop_update_int_array(DDI_DEV_T_NONE, dip,
1033 	    "interrupt-map-mask", (int *)imask, length) != DDI_PROP_SUCCESS) {
1034 		cmn_err(CE_WARN, "%s%d: Could not update imap mask property",
1035 		    ddi_driver_name(dip), ddi_get_instance(dip));
1036 		return (DDI_FAILURE);
1037 	}
1038 
1039 	return (DDI_SUCCESS);
1040 }
1041 
1042 /*
1043  * This function takes in the ac-interrupt-map property from the .conf file,
1044  * fills in the 'nodeid' information and then creates the 'interrupt-map'
1045  * property.
1046  */
1047 static int
1048 acebus_set_imap(dev_info_t *dip)
1049 {
1050 	int *imapp, *timapp, length, num, i, default_ival = 0;
1051 	dev_info_t *tdip = dip;
1052 	int *port_id, imap_ok = 1;
1053 	int ilength;
1054 	int acebus_default_se_imap[5];
1055 
1056 	/*
1057 	 * interrupt-map is specified via .conf file in hotplug mode,
1058 	 * since the child configuration is static.
1059 	 * It could even be hardcoded in the driver.
1060 	 */
1061 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
1062 	    "ac-interrupt-map", (int **)&imapp, (uint_t *)&ilength) !=
1063 	    DDI_PROP_SUCCESS) {
1064 		/* assume default implementation */
1065 		acebus_default_se_imap[0] = 0x14;
1066 		acebus_default_se_imap[1] = 0x400000;
1067 		acebus_default_se_imap[2] = 1;
1068 		acebus_default_se_imap[3] = 0;
1069 		acebus_default_se_imap[4] = 2;
1070 		imapp = acebus_default_se_imap;
1071 		ilength = 5;
1072 		default_ival = 1;
1073 	}
1074 	num = ilength / 5;	/* there are 5 integer cells in our property */
1075 	timapp = imapp;
1076 	for (i = 0; i < num; i++) {
1077 		if (*(timapp+i*5+3) == 0)
1078 			imap_ok = 0;
1079 	}
1080 	if (imap_ok) {
1081 		if (!default_ival)
1082 			ddi_prop_free(imapp);
1083 		return (DDI_SUCCESS);
1084 	}
1085 
1086 	while (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, tdip,
1087 	    DDI_PROP_DONTPASS, "upa-portid", (int **)&port_id,
1088 	    (uint_t *)&length) != DDI_PROP_SUCCESS) {
1089 		tdip = ddi_get_parent(tdip);
1090 		if (tdip == NULL) {
1091 			cmn_err(CE_WARN, "%s%d: Could not get imap parent",
1092 				ddi_driver_name(dip), ddi_get_instance(dip));
1093 			if (!default_ival)
1094 				ddi_prop_free(imapp);
1095 			return (DDI_FAILURE);
1096 		}
1097 	}
1098 	timapp = imapp;
1099 	for (i = 0; i < num; i++) {
1100 		*(timapp+i*5+3) = ddi_get_nodeid(tdip);
1101 	}
1102 
1103 	if (ddi_prop_update_int_array(DDI_DEV_T_NONE, dip,
1104 			"interrupt-map", imapp, ilength) != DDI_PROP_SUCCESS) {
1105 		cmn_err(CE_WARN, "%s%d: Could not update AC imap property",
1106 			ddi_driver_name(dip), ddi_get_instance(dip));
1107 		if (!default_ival)
1108 			ddi_prop_free(imapp);
1109 		return (DDI_FAILURE);
1110 	}
1111 	if (!default_ival)
1112 		ddi_prop_free(imapp);
1113 	return (DDI_SUCCESS);
1114 }
1115 #endif	/* ACEBUS_HOTPLUG */
1116