1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <sys/types.h>
30 #include <sys/hypervisor.h>
31 #include <sys/sunndi.h>
32 #include <sys/sunddi.h>
33 #include <sys/ddi_subrdefs.h>
34 #include <sys/bootconf.h>
35 #include <sys/psw.h>
36 #include <sys/modctl.h>
37 #include <sys/errno.h>
38 #include <sys/reboot.h>
39 #include <sys/hypervisor.h>
40 #include <xen/sys/xenbus_comms.h>
41 #include <xen/sys/xenbus_impl.h>
42 #include <xen/sys/xendev.h>
43 
44 extern int xen_boot_debug;
45 
46 /*
47  * Internal structures and functions
48  */
49 int xendev_nounload = 0;
50 void xendev_enumerate(int);
51 
52 /*
53  * Interface routines
54  */
55 
56 static struct modlmisc modlmisc = {
57 	&mod_miscops, "virtual device probe %I%"
58 };
59 
60 static struct modlinkage modlinkage = {
61 	MODREV_1, (void *)&modlmisc, NULL
62 };
63 
64 int
65 _init(void)
66 {
67 	int	err;
68 
69 	if ((err = mod_install(&modlinkage)) != 0)
70 		return (err);
71 
72 	impl_bus_add_probe(xendev_enumerate);
73 	return (0);
74 }
75 
76 int
77 _fini(void)
78 {
79 	int	err;
80 
81 	if (xendev_nounload)
82 		return (EBUSY);
83 
84 	if ((err = mod_remove(&modlinkage)) != 0)
85 		return (err);
86 
87 	impl_bus_delete_probe(xendev_enumerate);
88 	return (0);
89 }
90 
91 int
92 _info(struct modinfo *modinfop)
93 {
94 	return (mod_info(&modlinkage, modinfop));
95 }
96 
97 
98 /*
99  * This functions is invoked twice, first time with reprogram=0 to
100  * set up the xpvd portion of the device tree. The second time is
101  * ignored.
102  */
103 void
104 xendev_enumerate(int reprogram)
105 {
106 	dev_info_t *dip;
107 
108 	if (reprogram != 0)
109 		return;
110 
111 	ndi_devi_alloc_sleep(ddi_root_node(), "xpvd",
112 	    (pnode_t)DEVI_SID_NODEID, &dip);
113 
114 	(void) ndi_devi_bind_driver(dip, 0);
115 
116 	/*
117 	 * Too early to enumerate split device drivers in domU
118 	 * since we need to create taskq thread during enumeration.
119 	 * So, we only enumerate softdevs and console here.
120 	 */
121 	xendev_enum_all(dip, B_TRUE);
122 }
123