xref: /titanic_51/usr/src/uts/i86pc/io/consplat.c (revision 01457ffd3ca5d09e8907d4263dd635e2cc8fb72b)
1ae115bc7Smrj /*
2ae115bc7Smrj  * CDDL HEADER START
3ae115bc7Smrj  *
4ae115bc7Smrj  * The contents of this file are subject to the terms of the
5ae115bc7Smrj  * Common Development and Distribution License (the "License").
6ae115bc7Smrj  * You may not use this file except in compliance with the License.
7ae115bc7Smrj  *
8ae115bc7Smrj  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9ae115bc7Smrj  * or http://www.opensolaris.org/os/licensing.
10ae115bc7Smrj  * See the License for the specific language governing permissions
11ae115bc7Smrj  * and limitations under the License.
12ae115bc7Smrj  *
13ae115bc7Smrj  * When distributing Covered Code, include this CDDL HEADER in each
14ae115bc7Smrj  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15ae115bc7Smrj  * If applicable, add the following below this CDDL HEADER, with the
16ae115bc7Smrj  * fields enclosed by brackets "[]" replaced with your own identifying
17ae115bc7Smrj  * information: Portions Copyright [yyyy] [name of copyright owner]
18ae115bc7Smrj  *
19ae115bc7Smrj  * CDDL HEADER END
20ae115bc7Smrj  */
21ae115bc7Smrj 
22ae115bc7Smrj /*
2378323854SJudy Chen  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24ae115bc7Smrj  * Use is subject to license terms.
25ae115bc7Smrj  */
26ae115bc7Smrj 
27ae115bc7Smrj /*
28ae115bc7Smrj  * isa-specific console configuration routines
29ae115bc7Smrj  */
30ae115bc7Smrj 
31ae115bc7Smrj #include <sys/types.h>
32ae115bc7Smrj #include <sys/param.h>
33ae115bc7Smrj #include <sys/cmn_err.h>
34ae115bc7Smrj #include <sys/systm.h>
35ae115bc7Smrj #include <sys/conf.h>
36ae115bc7Smrj #include <sys/debug.h>
37ae115bc7Smrj #include <sys/ddi.h>
38ae115bc7Smrj #include <sys/sunddi.h>
39ae115bc7Smrj #include <sys/sunndi.h>
40ae115bc7Smrj #include <sys/esunddi.h>
41ae115bc7Smrj #include <sys/ddi_impldefs.h>
42ae115bc7Smrj #include <sys/promif.h>
43ae115bc7Smrj #include <sys/modctl.h>
44ae115bc7Smrj #include <sys/termios.h>
45843e1988Sjohnlev #if defined(__xpv)
46843e1988Sjohnlev #include <sys/hypervisor.h>
47843e1988Sjohnlev #include <sys/boot_console.h>
48843e1988Sjohnlev #endif
49ae115bc7Smrj 
5078323854SJudy Chen extern int pseudo_isa;
5178323854SJudy Chen 
52ae115bc7Smrj /* The names of currently supported graphics drivers on x86 */
53ae115bc7Smrj static char *
54ae115bc7Smrj gfxdrv_name[] = {
55e57b9183Scg149915 	"radeon",
56ae115bc7Smrj 	"vgatext",
57ae115bc7Smrj 	"i915",
582df1fe9cSrandyf 	"atiatom",
592df1fe9cSrandyf 	"nvidia",
60ae115bc7Smrj };
61ae115bc7Smrj 
62ae115bc7Smrj int
63ae115bc7Smrj plat_use_polled_debug() {
64ae115bc7Smrj 	return (0);
65ae115bc7Smrj }
66ae115bc7Smrj 
67ae115bc7Smrj int
68ae115bc7Smrj plat_support_serial_kbd_and_ms() {
69ae115bc7Smrj 	return (0);
70ae115bc7Smrj }
71ae115bc7Smrj 
72843e1988Sjohnlev #define	A_CNT(arr)	(sizeof (arr) / sizeof (arr[0]))
73843e1988Sjohnlev 
74ae115bc7Smrj #define	CONS_INVALID	-1
75ae115bc7Smrj #define	CONS_SCREEN	0
76ae115bc7Smrj #define	CONS_TTYA	1
77ae115bc7Smrj #define	CONS_TTYB	2
78ae115bc7Smrj #define	CONS_USBSER	3
79843e1988Sjohnlev #define	CONS_HYPERVISOR	4
80ae115bc7Smrj 
81583da248Srz201010 char *plat_fbpath(void);
82583da248Srz201010 
83ae115bc7Smrj static int
84ae115bc7Smrj console_type()
85ae115bc7Smrj {
86ae115bc7Smrj 	static int boot_console = CONS_INVALID;
87ae115bc7Smrj 
88ae115bc7Smrj 	char *cons;
89ae115bc7Smrj 	dev_info_t *root;
90ae115bc7Smrj 
91ae115bc7Smrj 	if (boot_console != CONS_INVALID)
92ae115bc7Smrj 		return (boot_console);
93ae115bc7Smrj 
94843e1988Sjohnlev #if defined(__xpv)
95843e1988Sjohnlev 	if (!DOMAIN_IS_INITDOMAIN(xen_info) || bcons_hypervisor_redirect()) {
96843e1988Sjohnlev 		boot_console = CONS_HYPERVISOR;
97843e1988Sjohnlev 		return (boot_console);
98843e1988Sjohnlev 	}
99843e1988Sjohnlev #endif /* __xpv */
100843e1988Sjohnlev 
101ae115bc7Smrj 	/*
102ae115bc7Smrj 	 * console is defined by "console" property, with
103ae115bc7Smrj 	 * fallback on the old "input-device" property.
104583da248Srz201010 	 * If "input-device" is not defined either, also check "output-device".
105ae115bc7Smrj 	 */
106ae115bc7Smrj 	boot_console = CONS_SCREEN;	/* default is screen/kb */
107ae115bc7Smrj 	root = ddi_root_node();
108ae115bc7Smrj 	if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, root,
109ae115bc7Smrj 	    DDI_PROP_DONTPASS, "console", &cons) == DDI_SUCCESS) ||
110ae115bc7Smrj 	    (ddi_prop_lookup_string(DDI_DEV_T_ANY, root,
111583da248Srz201010 	    DDI_PROP_DONTPASS, "input-device", &cons) == DDI_SUCCESS) ||
112583da248Srz201010 	    (ddi_prop_lookup_string(DDI_DEV_T_ANY, root,
113583da248Srz201010 	    DDI_PROP_DONTPASS, "output-device", &cons) == DDI_SUCCESS)) {
114843e1988Sjohnlev 		if (strcmp(cons, "ttya") == 0) {
115ae115bc7Smrj 			boot_console = CONS_TTYA;
116843e1988Sjohnlev 		} else if (strcmp(cons, "ttyb") == 0) {
117ae115bc7Smrj 			boot_console = CONS_TTYB;
118843e1988Sjohnlev 		} else if (strcmp(cons, "usb-serial") == 0) {
119ae115bc7Smrj 			(void) i_ddi_attach_hw_nodes("ehci");
120ae115bc7Smrj 			(void) i_ddi_attach_hw_nodes("uhci");
121ae115bc7Smrj 			(void) i_ddi_attach_hw_nodes("ohci");
122ae115bc7Smrj 			/*
123ae115bc7Smrj 			 * USB device enumerate asynchronously.
124ae115bc7Smrj 			 * Wait 2 seconds for USB serial devices to attach.
125ae115bc7Smrj 			 */
126ae115bc7Smrj 			delay(drv_usectohz(2000000));
127ae115bc7Smrj 			boot_console = CONS_USBSER;
128843e1988Sjohnlev #if defined(__xpv)
129843e1988Sjohnlev 		} else if (strcmp(cons, "hypervisor") == 0) {
130843e1988Sjohnlev 			boot_console = CONS_HYPERVISOR;
131843e1988Sjohnlev #endif /* __xpv */
132ae115bc7Smrj 		}
133ae115bc7Smrj 		ddi_prop_free(cons);
134ae115bc7Smrj 	}
135583da248Srz201010 
136583da248Srz201010 	/*
137583da248Srz201010 	 * If the console is configured to use a framebuffer but none
138583da248Srz201010 	 * could be found, fallback to "ttya" since it's likely to exist
139583da248Srz201010 	 * and it matches longstanding behavior on SPARC.
140583da248Srz201010 	 */
141583da248Srz201010 	if (boot_console == CONS_SCREEN && plat_fbpath() == NULL)
142583da248Srz201010 		boot_console = CONS_TTYA;
143583da248Srz201010 
144ae115bc7Smrj 	return (boot_console);
145ae115bc7Smrj }
146ae115bc7Smrj 
147ae115bc7Smrj int
148ae115bc7Smrj plat_stdin_is_keyboard(void)
149ae115bc7Smrj {
150ae115bc7Smrj 	return (console_type() == CONS_SCREEN);
151ae115bc7Smrj }
152ae115bc7Smrj 
153ae115bc7Smrj int
154ae115bc7Smrj plat_stdout_is_framebuffer(void)
155ae115bc7Smrj {
156ae115bc7Smrj 	return (console_type() == CONS_SCREEN);
157ae115bc7Smrj }
158ae115bc7Smrj 
15978323854SJudy Chen static char *
16078323854SJudy Chen plat_devpath(char *name, char *path)
16178323854SJudy Chen {
16278323854SJudy Chen 	major_t major;
16378323854SJudy Chen 	dev_info_t *dip, *pdip;
16478323854SJudy Chen 
16578323854SJudy Chen 	if ((major = ddi_name_to_major(name)) == (major_t)-1)
16678323854SJudy Chen 		return (NULL);
16778323854SJudy Chen 
16878323854SJudy Chen 	if ((dip = devnamesp[major].dn_head) == NULL)
16978323854SJudy Chen 		return (NULL);
17078323854SJudy Chen 
17178323854SJudy Chen 	pdip = ddi_get_parent(dip);
17278323854SJudy Chen 	if (i_ddi_attach_node_hierarchy(pdip) != DDI_SUCCESS)
17378323854SJudy Chen 		return (NULL);
17478323854SJudy Chen 	if (ddi_initchild(pdip, dip) != DDI_SUCCESS)
17578323854SJudy Chen 		return (NULL);
17678323854SJudy Chen 
17778323854SJudy Chen 	(void) ddi_pathname(dip, path);
17878323854SJudy Chen 
17978323854SJudy Chen 	return (path);
18078323854SJudy Chen }
18178323854SJudy Chen 
182ae115bc7Smrj /*
183ae115bc7Smrj  * Return generic path to keyboard device from the alias.
184ae115bc7Smrj  */
185ae115bc7Smrj char *
186ae115bc7Smrj plat_kbdpath(void)
187ae115bc7Smrj {
18878323854SJudy Chen 	static char kbpath[MAXPATHLEN];
18978323854SJudy Chen 
190ae115bc7Smrj 	/*
191ae115bc7Smrj 	 * Hardcode to isa keyboard path
192ae115bc7Smrj 	 * XXX make it settable via bootprop?
193ae115bc7Smrj 	 */
19478323854SJudy Chen 	if (pseudo_isa)
195ae115bc7Smrj 		return ("/isa/i8042@1,60/keyboard@0");
19678323854SJudy Chen 
19778323854SJudy Chen 	if (plat_devpath("kb8042", kbpath) == NULL)
19878323854SJudy Chen 		return (NULL);
19978323854SJudy Chen 
20078323854SJudy Chen 	return (kbpath);
201ae115bc7Smrj }
202ae115bc7Smrj 
203ae115bc7Smrj /*
204ae115bc7Smrj  * Return generic path to display device from the alias.
205ae115bc7Smrj  */
206ae115bc7Smrj char *
207ae115bc7Smrj plat_fbpath(void)
208ae115bc7Smrj {
209ae115bc7Smrj 	static char *fbpath = NULL;
210ae115bc7Smrj 	static char fbpath_buf[MAXPATHLEN];
211ae115bc7Smrj 	major_t major;
212843e1988Sjohnlev 	dev_info_t *dip, *dip_pseudo = NULL;
213ae115bc7Smrj 	int i;
214ae115bc7Smrj 
215843e1988Sjohnlev 	/* lookup the dip for the pseudo device */
216843e1988Sjohnlev 	(void) resolve_pathname("/pseudo", &dip_pseudo, NULL, NULL);
217843e1988Sjohnlev 
218843e1988Sjohnlev 	for (i = 0; i < A_CNT(gfxdrv_name); i++) {
219ae115bc7Smrj 		/*
220ae115bc7Smrj 		 * look for first instance of each driver
221ae115bc7Smrj 		 */
222843e1988Sjohnlev 		if ((major = ddi_name_to_major(gfxdrv_name[i])) == (major_t)-1)
223843e1988Sjohnlev 			continue;
224843e1988Sjohnlev 
225843e1988Sjohnlev 		if ((dip = devnamesp[major].dn_head) == NULL)
226843e1988Sjohnlev 			continue;
227843e1988Sjohnlev 
228843e1988Sjohnlev 		/*
229843e1988Sjohnlev 		 * We're looking for a real hardware device here so skip
230843e1988Sjohnlev 		 * any pseudo devices.  When could a framebuffer hardware
231843e1988Sjohnlev 		 * driver also have a pseudo node?  Well, some framebuffer
232843e1988Sjohnlev 		 * hardware drivers (nvidia) also create pseudo nodes for
233843e1988Sjohnlev 		 * administration purposes, and these nodes will exist
234843e1988Sjohnlev 		 * regardless of if the actual associated hardware
235843e1988Sjohnlev 		 * is present or not.
236843e1988Sjohnlev 		 */
237843e1988Sjohnlev 		if (ddi_get_parent(dip) == dip_pseudo)
238843e1988Sjohnlev 			continue;
239843e1988Sjohnlev 
240843e1988Sjohnlev 		if (i_ddi_attach_node_hierarchy(dip) == DDI_SUCCESS) {
241ae115bc7Smrj 			(void) ddi_pathname(dip, fbpath_buf);
242ae115bc7Smrj 			fbpath = fbpath_buf;
243ae115bc7Smrj 		}
244ae115bc7Smrj 
245ae115bc7Smrj 		if (fbpath)
246843e1988Sjohnlev 			break;
247ae115bc7Smrj 	}
248ae115bc7Smrj 
249843e1988Sjohnlev 	if (dip_pseudo != NULL)
250843e1988Sjohnlev 		ddi_release_devi(dip_pseudo);
251843e1988Sjohnlev 
252ae115bc7Smrj 	/* No screen found */
253843e1988Sjohnlev 	return (fbpath);
254ae115bc7Smrj }
255ae115bc7Smrj 
256ae115bc7Smrj char *
257ae115bc7Smrj plat_mousepath(void)
258ae115bc7Smrj {
25978323854SJudy Chen 	static char mpath[MAXPATHLEN];
26078323854SJudy Chen 
261ae115bc7Smrj 	/*
262ae115bc7Smrj 	 * Hardcode to isa mouse path
263ae115bc7Smrj 	 * XXX make it settable via bootprop?
264ae115bc7Smrj 	 */
26578323854SJudy Chen 	if (pseudo_isa)
266ae115bc7Smrj 		return ("/isa/i8042@1,60/mouse@1");
26778323854SJudy Chen 
26878323854SJudy Chen 	if (plat_devpath("mouse8042", mpath) == NULL)
26978323854SJudy Chen 		return (NULL);
27078323854SJudy Chen 
27178323854SJudy Chen 	return (mpath);
272ae115bc7Smrj }
273ae115bc7Smrj 
274ae115bc7Smrj /* return path of first usb serial device */
275ae115bc7Smrj static char *
276ae115bc7Smrj plat_usbser_path(void)
277ae115bc7Smrj {
278ae115bc7Smrj 	extern dev_info_t *usbser_first_device(void);
279ae115bc7Smrj 
280ae115bc7Smrj 	dev_info_t *us_dip;
281ae115bc7Smrj 	static char *us_path = NULL;
282ae115bc7Smrj 
283ae115bc7Smrj 	if (us_path)
284ae115bc7Smrj 		return (us_path);
285ae115bc7Smrj 
286ae115bc7Smrj 	us_dip = usbser_first_device();
287ae115bc7Smrj 	if (us_dip == NULL)
288ae115bc7Smrj 		return (NULL);
289ae115bc7Smrj 
290ae115bc7Smrj 	us_path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
291ae115bc7Smrj 	(void) ddi_pathname(us_dip, us_path);
292ae115bc7Smrj 	ndi_rele_devi(us_dip);	/* held from usbser_first_device */
293ae115bc7Smrj 	return (us_path);
294ae115bc7Smrj }
295ae115bc7Smrj 
29678323854SJudy Chen static char *
29778323854SJudy Chen plat_ttypath(int inum)
29878323854SJudy Chen {
29978323854SJudy Chen 	static char *defaultpath[] = {
30078323854SJudy Chen 	    "/isa/asy@1,3f8:a",
30178323854SJudy Chen 	    "/isa/asy@1,2f8:b"
30278323854SJudy Chen 	};
30378323854SJudy Chen 	static char path[MAXPATHLEN];
30478323854SJudy Chen 	char *bp;
30578323854SJudy Chen 	major_t major;
30678323854SJudy Chen 	dev_info_t *dip;
30778323854SJudy Chen 
30878323854SJudy Chen 	if (pseudo_isa)
30978323854SJudy Chen 		return (defaultpath[inum]);
31078323854SJudy Chen 
31178323854SJudy Chen 	if ((major = ddi_name_to_major("asy")) == (major_t)-1)
31278323854SJudy Chen 		return (NULL);
31378323854SJudy Chen 
31478323854SJudy Chen 	if ((dip = devnamesp[major].dn_head) == NULL)
31578323854SJudy Chen 		return (NULL);
31678323854SJudy Chen 
317*01457ffdSJudy Chen 	for (; dip != NULL; dip = ddi_get_next(dip)) {
31878323854SJudy Chen 		if (i_ddi_attach_node_hierarchy(dip) != DDI_SUCCESS)
31978323854SJudy Chen 			return (NULL);
32078323854SJudy Chen 
321*01457ffdSJudy Chen 		if (DEVI(dip)->devi_minor->ddm_name[0] == ('a' + (char)inum))
322*01457ffdSJudy Chen 			break;
323*01457ffdSJudy Chen 	}
324*01457ffdSJudy Chen 	if (dip == NULL)
325*01457ffdSJudy Chen 		return (NULL);
326*01457ffdSJudy Chen 
32778323854SJudy Chen 	(void) ddi_pathname(dip, path);
32878323854SJudy Chen 	bp = path + strlen(path);
32978323854SJudy Chen 	(void) snprintf(bp, 3, ":%s", DEVI(dip)->devi_minor->ddm_name);
33078323854SJudy Chen 
33178323854SJudy Chen 	return (path);
33278323854SJudy Chen }
33378323854SJudy Chen 
334ae115bc7Smrj /*
335ae115bc7Smrj  * Lacking support for com2 and com3, if that matters.
336ae115bc7Smrj  * Another possible enhancement could be to use properties
337ae115bc7Smrj  * for the port mapping rather than simply hard-code them.
338ae115bc7Smrj  */
339ae115bc7Smrj char *
340ae115bc7Smrj plat_stdinpath(void)
341ae115bc7Smrj {
342ae115bc7Smrj 	switch (console_type()) {
343843e1988Sjohnlev #if defined(__xpv)
344843e1988Sjohnlev 	case CONS_HYPERVISOR:
345843e1988Sjohnlev 		return ("/xpvd/xencons@0");
346843e1988Sjohnlev #endif /* __xpv */
347ae115bc7Smrj 	case CONS_TTYA:
34878323854SJudy Chen 		return (plat_ttypath(0));
349ae115bc7Smrj 	case CONS_TTYB:
35078323854SJudy Chen 		return (plat_ttypath(1));
351ae115bc7Smrj 	case CONS_USBSER:
352ae115bc7Smrj 		return (plat_usbser_path());
353ae115bc7Smrj 	case CONS_SCREEN:
354ae115bc7Smrj 	default:
355ae115bc7Smrj 		break;
356ae115bc7Smrj 	};
357ae115bc7Smrj 	return (plat_kbdpath());
358ae115bc7Smrj }
359ae115bc7Smrj 
360ae115bc7Smrj char *
361ae115bc7Smrj plat_stdoutpath(void)
362ae115bc7Smrj {
363ae115bc7Smrj 	switch (console_type()) {
364843e1988Sjohnlev #if defined(__xpv)
365843e1988Sjohnlev 	case CONS_HYPERVISOR:
366843e1988Sjohnlev 		return ("/xpvd/xencons@0");
367843e1988Sjohnlev #endif /* __xpv */
368ae115bc7Smrj 	case CONS_TTYA:
36978323854SJudy Chen 		return (plat_ttypath(0));
370ae115bc7Smrj 	case CONS_TTYB:
37178323854SJudy Chen 		return (plat_ttypath(1));
372ae115bc7Smrj 	case CONS_USBSER:
373ae115bc7Smrj 		return (plat_usbser_path());
374ae115bc7Smrj 	case CONS_SCREEN:
375ae115bc7Smrj 	default:
376ae115bc7Smrj 		break;
377ae115bc7Smrj 	};
378ae115bc7Smrj 	return (plat_fbpath());
379ae115bc7Smrj }
380ae115bc7Smrj 
381ae115bc7Smrj /*
382ae115bc7Smrj  * If VIS_PIXEL mode will be implemented on x86, these following
383ae115bc7Smrj  * functions should be re-considered. Now these functions are
384ae115bc7Smrj  * unused on x86.
385ae115bc7Smrj  */
386ae115bc7Smrj void
387c9503a49Slq150181 plat_tem_get_inverses(int *inverse, int *inverse_screen)
388c9503a49Slq150181 {
389c9503a49Slq150181 	*inverse = 0;
390c9503a49Slq150181 	*inverse_screen = 0;
391c9503a49Slq150181 }
392c9503a49Slq150181 
393c9503a49Slq150181 void
394ae115bc7Smrj plat_tem_get_prom_font_size(int *charheight, int *windowtop)
395ae115bc7Smrj {
396ae115bc7Smrj 	*charheight = 0;
397ae115bc7Smrj 	*windowtop = 0;
398ae115bc7Smrj }
399ae115bc7Smrj 
400843e1988Sjohnlev /*ARGSUSED*/
401ae115bc7Smrj void
402ae115bc7Smrj plat_tem_get_prom_size(size_t *height, size_t *width)
403ae115bc7Smrj {
404843e1988Sjohnlev 	panic("unimplemented at line %d of %s", __LINE__, __FILE__);
405ae115bc7Smrj }
406ae115bc7Smrj 
407ae115bc7Smrj void
408ae115bc7Smrj plat_tem_hide_prom_cursor(void)
409ae115bc7Smrj {
410843e1988Sjohnlev 	panic("unimplemented at line %d of %s", __LINE__, __FILE__);
411ae115bc7Smrj }
412ae115bc7Smrj 
413843e1988Sjohnlev /*ARGSUSED*/
414ae115bc7Smrj void
415ae115bc7Smrj plat_tem_get_prom_pos(uint32_t *row, uint32_t *col)
416ae115bc7Smrj {
417843e1988Sjohnlev 	panic("unimplemented at line %d of %s", __LINE__, __FILE__);
418ae115bc7Smrj }
419