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