xref: /illumos-gate/usr/src/uts/i86pc/io/consplat.c (revision 843e19887f64dde75055cf8842fc4db2171eff45)
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 /*
30  * isa-specific console configuration routines
31  */
32 
33 #include <sys/types.h>
34 #include <sys/param.h>
35 #include <sys/cmn_err.h>
36 #include <sys/systm.h>
37 #include <sys/conf.h>
38 #include <sys/debug.h>
39 #include <sys/ddi.h>
40 #include <sys/sunddi.h>
41 #include <sys/sunndi.h>
42 #include <sys/esunddi.h>
43 #include <sys/ddi_impldefs.h>
44 #include <sys/promif.h>
45 #include <sys/modctl.h>
46 #include <sys/termios.h>
47 #if defined(__xpv)
48 #include <sys/hypervisor.h>
49 #include <sys/boot_console.h>
50 #endif
51 
52 /* The names of currently supported graphics drivers on x86 */
53 static char *
54 gfxdrv_name[] = {
55 	"vgatext",
56 	"i915",
57 	"nvidia"
58 };
59 
60 int
61 plat_use_polled_debug() {
62 	return (0);
63 }
64 
65 int
66 plat_support_serial_kbd_and_ms() {
67 	return (0);
68 }
69 
70 #define	A_CNT(arr)	(sizeof (arr) / sizeof (arr[0]))
71 
72 #define	CONS_INVALID	-1
73 #define	CONS_SCREEN	0
74 #define	CONS_TTYA	1
75 #define	CONS_TTYB	2
76 #define	CONS_USBSER	3
77 #define	CONS_HYPERVISOR	4
78 
79 static int
80 console_type()
81 {
82 	static int boot_console = CONS_INVALID;
83 
84 	char *cons;
85 	dev_info_t *root;
86 
87 	if (boot_console != CONS_INVALID)
88 		return (boot_console);
89 
90 #if defined(__xpv)
91 	if (!DOMAIN_IS_INITDOMAIN(xen_info) || bcons_hypervisor_redirect()) {
92 		boot_console = CONS_HYPERVISOR;
93 		return (boot_console);
94 	}
95 #endif /* __xpv */
96 
97 	/*
98 	 * console is defined by "console" property, with
99 	 * fallback on the old "input-device" property.
100 	 */
101 	boot_console = CONS_SCREEN;	/* default is screen/kb */
102 	root = ddi_root_node();
103 	if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, root,
104 	    DDI_PROP_DONTPASS, "console", &cons) == DDI_SUCCESS) ||
105 	    (ddi_prop_lookup_string(DDI_DEV_T_ANY, root,
106 	    DDI_PROP_DONTPASS, "input-device", &cons) == DDI_SUCCESS)) {
107 		if (strcmp(cons, "ttya") == 0) {
108 			boot_console = CONS_TTYA;
109 		} else if (strcmp(cons, "ttyb") == 0) {
110 			boot_console = CONS_TTYB;
111 		} else if (strcmp(cons, "usb-serial") == 0) {
112 			(void) i_ddi_attach_hw_nodes("ehci");
113 			(void) i_ddi_attach_hw_nodes("uhci");
114 			(void) i_ddi_attach_hw_nodes("ohci");
115 			/*
116 			 * USB device enumerate asynchronously.
117 			 * Wait 2 seconds for USB serial devices to attach.
118 			 */
119 			delay(drv_usectohz(2000000));
120 			boot_console = CONS_USBSER;
121 #if defined(__xpv)
122 		} else if (strcmp(cons, "hypervisor") == 0) {
123 			boot_console = CONS_HYPERVISOR;
124 #endif /* __xpv */
125 		}
126 		ddi_prop_free(cons);
127 	}
128 	return (boot_console);
129 }
130 
131 int
132 plat_stdin_is_keyboard(void)
133 {
134 	return (console_type() == CONS_SCREEN);
135 }
136 
137 int
138 plat_stdout_is_framebuffer(void)
139 {
140 	return (console_type() == CONS_SCREEN);
141 }
142 
143 /*
144  * Return generic path to keyboard device from the alias.
145  */
146 char *
147 plat_kbdpath(void)
148 {
149 	/*
150 	 * Hardcode to isa keyboard path
151 	 * XXX make it settable via bootprop?
152 	 */
153 	return ("/isa/i8042@1,60/keyboard@0");
154 }
155 
156 /*
157  * Return generic path to display device from the alias.
158  */
159 char *
160 plat_fbpath(void)
161 {
162 	static char *fbpath = NULL;
163 	static char fbpath_buf[MAXPATHLEN];
164 	major_t major;
165 	dev_info_t *dip, *dip_pseudo = NULL;
166 	int i;
167 
168 	/* lookup the dip for the pseudo device */
169 	(void) resolve_pathname("/pseudo", &dip_pseudo, NULL, NULL);
170 
171 	for (i = 0; i < A_CNT(gfxdrv_name); i++) {
172 		/*
173 		 * look for first instance of each driver
174 		 */
175 		if ((major = ddi_name_to_major(gfxdrv_name[i])) == (major_t)-1)
176 			continue;
177 
178 		if ((dip = devnamesp[major].dn_head) == NULL)
179 			continue;
180 
181 		/*
182 		 * We're looking for a real hardware device here so skip
183 		 * any pseudo devices.  When could a framebuffer hardware
184 		 * driver also have a pseudo node?  Well, some framebuffer
185 		 * hardware drivers (nvidia) also create pseudo nodes for
186 		 * administration purposes, and these nodes will exist
187 		 * regardless of if the actual associated hardware
188 		 * is present or not.
189 		 */
190 		if (ddi_get_parent(dip) == dip_pseudo)
191 			continue;
192 
193 		if (i_ddi_attach_node_hierarchy(dip) == DDI_SUCCESS) {
194 			(void) ddi_pathname(dip, fbpath_buf);
195 			fbpath = fbpath_buf;
196 		}
197 
198 		if (fbpath)
199 			break;
200 	}
201 
202 	if (dip_pseudo != NULL)
203 		ddi_release_devi(dip_pseudo);
204 
205 	/* No screen found */
206 	return (fbpath);
207 }
208 
209 char *
210 plat_mousepath(void)
211 {
212 	/*
213 	 * Hardcode to isa mouse path
214 	 * XXX make it settable via bootprop?
215 	 */
216 	return ("/isa/i8042@1,60/mouse@1");
217 }
218 
219 /* return path of first usb serial device */
220 static char *
221 plat_usbser_path(void)
222 {
223 	extern dev_info_t *usbser_first_device(void);
224 
225 	dev_info_t *us_dip;
226 	static char *us_path = NULL;
227 
228 	if (us_path)
229 		return (us_path);
230 
231 	us_dip = usbser_first_device();
232 	if (us_dip == NULL)
233 		return (NULL);
234 
235 	us_path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
236 	(void) ddi_pathname(us_dip, us_path);
237 	ndi_rele_devi(us_dip);	/* held from usbser_first_device */
238 	return (us_path);
239 }
240 
241 /*
242  * Lacking support for com2 and com3, if that matters.
243  * Another possible enhancement could be to use properties
244  * for the port mapping rather than simply hard-code them.
245  */
246 char *
247 plat_stdinpath(void)
248 {
249 	switch (console_type()) {
250 #if defined(__xpv)
251 	case CONS_HYPERVISOR:
252 		return ("/xpvd/xencons@0");
253 #endif /* __xpv */
254 	case CONS_TTYA:
255 		return ("/isa/asy@1,3f8:a");
256 	case CONS_TTYB:
257 		return ("/isa/asy@1,2f8:b");
258 	case CONS_USBSER:
259 		return (plat_usbser_path());
260 	case CONS_SCREEN:
261 	default:
262 		break;
263 	};
264 	return (plat_kbdpath());
265 }
266 
267 char *
268 plat_stdoutpath(void)
269 {
270 	switch (console_type()) {
271 #if defined(__xpv)
272 	case CONS_HYPERVISOR:
273 		return ("/xpvd/xencons@0");
274 #endif /* __xpv */
275 	case CONS_TTYA:
276 		return ("/isa/asy@1,3f8:a");
277 	case CONS_TTYB:
278 		return ("/isa/asy@1,2f8:b");
279 	case CONS_USBSER:
280 		return (plat_usbser_path());
281 	case CONS_SCREEN:
282 	default:
283 		break;
284 	};
285 	return (plat_fbpath());
286 }
287 
288 /*
289  * If VIS_PIXEL mode will be implemented on x86, these following
290  * functions should be re-considered. Now these functions are
291  * unused on x86.
292  */
293 void
294 plat_tem_get_inverses(int *inverse, int *inverse_screen)
295 {
296 	*inverse = 0;
297 	*inverse_screen = 0;
298 }
299 
300 void
301 plat_tem_get_prom_font_size(int *charheight, int *windowtop)
302 {
303 	*charheight = 0;
304 	*windowtop = 0;
305 }
306 
307 /*ARGSUSED*/
308 void
309 plat_tem_get_prom_size(size_t *height, size_t *width)
310 {
311 	panic("unimplemented at line %d of %s", __LINE__, __FILE__);
312 }
313 
314 void
315 plat_tem_hide_prom_cursor(void)
316 {
317 	panic("unimplemented at line %d of %s", __LINE__, __FILE__);
318 }
319 
320 /*ARGSUSED*/
321 void
322 plat_tem_get_prom_pos(uint32_t *row, uint32_t *col)
323 {
324 	panic("unimplemented at line %d of %s", __LINE__, __FILE__);
325 }
326