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