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