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