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