preprocessor cleanup: __xpv
[unleashed.git] / usr / src / uts / i86pc / io / consplat.c
blobae8c580be4830e16ae1b6fd13a8abac704f3ca3b
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
23 * Copyright (c) 2012 Gary Mills
25 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
26 * Use is subject to license terms.
30 * isa-specific console configuration routines
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 #include <sys/pci.h>
49 extern int pseudo_isa;
51 int
52 plat_use_polled_debug()
54 return (0);
57 int
58 plat_support_serial_kbd_and_ms()
60 return (0);
63 #define A_CNT(arr) (sizeof (arr) / sizeof (arr[0]))
65 #ifndef CONS_INVALID
66 #define CONS_INVALID -1
67 #define CONS_SCREEN_TEXT 0
68 #define CONS_TTY 1
69 #define CONS_XXX 2 /* Unused */
70 #define CONS_USBSER 3
71 #define CONS_HYPERVISOR 4
72 #define CONS_SCREEN_GRAPHICS 5
73 #endif /* CONS_INVALID */
75 char *plat_fbpath(void);
77 static int
78 console_type(int *tnum)
80 static int boot_console = CONS_INVALID;
81 static int tty_num = 0;
83 char *cons;
84 dev_info_t *root;
86 /* If we already have determined the console, just return it. */
87 if (boot_console != CONS_INVALID) {
88 if (tnum != NULL)
89 *tnum = tty_num;
90 return (boot_console);
95 * console is defined by "console" property, with
96 * fallback on the old "input-device" property.
97 * If "input-device" is not defined either, also check "output-device".
99 boot_console = CONS_SCREEN_TEXT; /* default is screen/kb */
100 root = ddi_root_node();
101 if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, root,
102 DDI_PROP_DONTPASS, "console", &cons) == DDI_SUCCESS) ||
103 (ddi_prop_lookup_string(DDI_DEV_T_ANY, root,
104 DDI_PROP_DONTPASS, "input-device", &cons) == DDI_SUCCESS) ||
105 (ddi_prop_lookup_string(DDI_DEV_T_ANY, root,
106 DDI_PROP_DONTPASS, "output-device", &cons) == DDI_SUCCESS)) {
107 if (strlen(cons) == 4 && strncmp(cons, "tty", 3) == 0 &&
108 cons[3] >= 'a' && cons[3] <= 'd') {
109 boot_console = CONS_TTY;
110 tty_num = cons[3] - 'a';
111 } else if (strcmp(cons, "usb-serial") == 0) {
112 (void) i_ddi_attach_hw_nodes("xhci");
113 (void) i_ddi_attach_hw_nodes("ehci");
114 (void) i_ddi_attach_hw_nodes("uhci");
115 (void) i_ddi_attach_hw_nodes("ohci");
117 * USB device enumerate asynchronously.
118 * Wait 2 seconds for USB serial devices to attach.
120 delay(drv_usectohz(2000000));
121 boot_console = CONS_USBSER;
123 ddi_prop_free(cons);
127 * If the console is configured to use a framebuffer but none
128 * could be found, fallback to "ttya" since it's likely to exist
129 * and it matches longstanding behavior on SPARC.
131 if (boot_console == CONS_SCREEN_TEXT && plat_fbpath() == NULL) {
132 boot_console = CONS_TTY;
133 tty_num = 0;
136 if (tnum != NULL)
137 *tnum = tty_num;
138 return (boot_console);
142 plat_stdin_is_keyboard(void)
144 return (console_type(NULL) == CONS_SCREEN_TEXT);
148 plat_stdout_is_framebuffer(void)
150 return (console_type(NULL) == CONS_SCREEN_TEXT);
153 static char *
154 plat_devpath(char *name, char *path)
156 major_t major;
157 dev_info_t *dip, *pdip;
159 if ((major = ddi_name_to_major(name)) == (major_t)-1)
160 return (NULL);
162 if ((dip = devnamesp[major].dn_head) == NULL)
163 return (NULL);
165 pdip = ddi_get_parent(dip);
166 if (i_ddi_attach_node_hierarchy(pdip) != DDI_SUCCESS)
167 return (NULL);
168 if (ddi_initchild(pdip, dip) != DDI_SUCCESS)
169 return (NULL);
171 (void) ddi_pathname(dip, path);
173 return (path);
177 * Return generic path to keyboard device from the alias.
179 char *
180 plat_kbdpath(void)
182 static char kbpath[MAXPATHLEN];
185 * Hardcode to isa keyboard path
186 * XXX make it settable via bootprop?
188 if (pseudo_isa)
189 return ("/isa/i8042@1,60/keyboard@0");
191 if (plat_devpath("kb8042", kbpath) == NULL)
192 return (NULL);
194 return (kbpath);
198 * NOTE: this function is duplicated here and in gfx_private/vgatext while
199 * we work on a set of commitable interfaces to sunpci.c.
201 * Use the class code to determine if the device is a PCI-to-PCI bridge.
202 * Returns: B_TRUE if the device is a bridge.
203 * B_FALSE if the device is not a bridge or the property cannot be
204 * retrieved.
206 static boolean_t
207 is_pci_bridge(dev_info_t *dip)
209 uint32_t class_code;
211 class_code = (uint32_t)ddi_prop_get_int(DDI_DEV_T_ANY, dip,
212 DDI_PROP_DONTPASS, "class-code", 0xffffffff);
214 if (class_code == 0xffffffff || class_code == DDI_PROP_NOT_FOUND)
215 return (B_FALSE);
217 class_code &= 0x00ffff00;
218 if (class_code == ((PCI_CLASS_BRIDGE << 16) | (PCI_BRIDGE_PCI << 8)))
219 return (B_TRUE);
221 return (B_FALSE);
225 * Type for the parameter of find_fb_dev()
227 struct find_fb_dev_param
229 dev_info_t *found_dip; /* dip found for VGA console */
230 int vga_enable; /* check PCI_BCNF_BCNTRL_VGA_ENABLE or not */
234 * The VGA device could be under a subtractive PCI bridge on some systems.
235 * Though the PCI_BCNF_BCNTRL_VGA_ENABLE bit is not set on such subtractive
236 * PCI bridge, the subtractive PCI bridge can forward VGA access if no other
237 * agent claims the access.
238 * The vga_enable element in param acts as a flag, if not set, ignore the
239 * checking for the PCI_BCNF_BCNTRL_VGA_ENABLE bit of the PCI bridge during
240 * the search.
242 static int
243 find_fb_dev(dev_info_t *dip, void *param)
245 struct find_fb_dev_param *p = param;
246 char *dev_type;
247 dev_info_t *pdip;
248 char *parent_type;
250 if (dip == ddi_root_node())
251 return (DDI_WALK_CONTINUE);
253 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
254 "device_type", &dev_type) != DDI_SUCCESS)
255 return (DDI_WALK_PRUNECHILD);
257 if ((strcmp(dev_type, "isa") == 0) || (strcmp(dev_type, "eisa") == 0)) {
258 ddi_prop_free(dev_type);
259 return (DDI_WALK_CONTINUE);
262 if ((strcmp(dev_type, "pci") == 0) ||
263 (strcmp(dev_type, "pciex") == 0)) {
264 ddi_acc_handle_t pci_conf;
265 uint16_t data16;
266 char *nodename;
268 ddi_prop_free(dev_type);
270 if (!p->vga_enable)
271 return (DDI_WALK_CONTINUE);
273 nodename = ddi_node_name(dip);
276 * If the node is not a PCI-to-PCI bridge, continue traversing
277 * (it could be the root node), otherwise, check for the
278 * VGAEnable bit to be set in the Bridge Control Register.
280 if (strcmp(nodename, "pci") == 0) {
281 if (is_pci_bridge(dip) == B_FALSE)
282 return (DDI_WALK_CONTINUE);
285 if (i_ddi_attach_node_hierarchy(dip) != DDI_SUCCESS)
286 return (DDI_WALK_PRUNECHILD);
288 if (pci_config_setup(dip, &pci_conf) != DDI_SUCCESS)
289 return (DDI_WALK_PRUNECHILD);
291 data16 = pci_config_get16(pci_conf, PCI_BCNF_BCNTRL);
292 pci_config_teardown(&pci_conf);
294 if (data16 & PCI_BCNF_BCNTRL_VGA_ENABLE)
295 return (DDI_WALK_CONTINUE);
297 return (DDI_WALK_PRUNECHILD);
300 if (strcmp(dev_type, "display") != 0) {
301 ddi_prop_free(dev_type);
302 return (DDI_WALK_CONTINUE);
305 ddi_prop_free(dev_type);
307 if ((pdip = ddi_get_parent(dip)) == NULL)
308 return (DDI_WALK_PRUNECHILD);
310 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, pdip, DDI_PROP_DONTPASS,
311 "device_type", &parent_type) != DDI_SUCCESS)
312 return (DDI_WALK_PRUNECHILD);
314 if ((strcmp(parent_type, "isa") == 0) ||
315 (strcmp(parent_type, "eisa") == 0)) {
316 p->found_dip = dip;
317 ddi_prop_free(parent_type);
318 return (DDI_WALK_TERMINATE);
321 if ((strcmp(parent_type, "pci") == 0) ||
322 (strcmp(parent_type, "pciex") == 0)) {
323 ddi_acc_handle_t pci_conf;
324 uint16_t data16;
326 ddi_prop_free(parent_type);
328 if (i_ddi_attach_node_hierarchy(dip) != DDI_SUCCESS)
329 return (DDI_WALK_PRUNECHILD);
331 if (pci_config_setup(dip, &pci_conf) != DDI_SUCCESS)
332 return (DDI_WALK_PRUNECHILD);
334 data16 = pci_config_get16(pci_conf, PCI_CONF_COMM);
335 pci_config_teardown(&pci_conf);
337 if (!(data16 & PCI_COMM_IO))
338 return (DDI_WALK_PRUNECHILD);
340 p->found_dip = dip;
341 return (DDI_WALK_TERMINATE);
344 ddi_prop_free(parent_type);
345 return (DDI_WALK_PRUNECHILD);
349 * The first round search is to find:
350 * 1) a VGA device.
351 * 2) a PCI VGA compatible device whose IO space is enabled
352 * and the VGA Enable bit of any PCI-PCI bridge above it is set.
353 * If the first round search succeeds, prune the second round search.
355 * The second round seach does not check the VGA Enable bit.
357 * Return the device path as the console fb path.
359 char *
360 plat_fbpath(void)
362 struct find_fb_dev_param param;
363 static char *fbpath = NULL;
364 static char fbpath_buf[MAXPATHLEN];
366 /* first round search */
367 param.found_dip = NULL;
368 param.vga_enable = 1;
369 ddi_walk_devs(ddi_root_node(), find_fb_dev, &param);
371 if (param.found_dip != NULL) {
372 (void) ddi_pathname(param.found_dip, fbpath_buf);
373 fbpath = fbpath_buf;
374 return (fbpath);
378 * second round search, do not check the
379 * PCI_BCNF_BCNTRL_VGA_ENABLE bit
381 param.found_dip = NULL;
382 param.vga_enable = 0;
383 ddi_walk_devs(ddi_root_node(), find_fb_dev, &param);
385 if (param.found_dip == NULL)
386 return (NULL);
388 (void) ddi_pathname(param.found_dip, fbpath_buf);
389 fbpath = fbpath_buf;
390 return (fbpath);
393 char *
394 plat_mousepath(void)
396 static char mpath[MAXPATHLEN];
399 * Hardcode to isa mouse path
400 * XXX make it settable via bootprop?
402 if (pseudo_isa)
403 return ("/isa/i8042@1,60/mouse@1");
405 if (plat_devpath("mouse8042", mpath) == NULL)
406 return (NULL);
408 return (mpath);
411 /* return path of first usb serial device */
412 static char *
413 plat_usbser_path(void)
415 extern dev_info_t *usbser_first_device(void);
417 dev_info_t *us_dip;
418 static char *us_path = NULL;
420 if (us_path)
421 return (us_path);
423 us_dip = usbser_first_device();
424 if (us_dip == NULL)
425 return (NULL);
427 us_path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
428 (void) ddi_pathname(us_dip, us_path);
429 ndi_rele_devi(us_dip); /* held from usbser_first_device */
430 return (us_path);
433 static char *
434 plat_ttypath(int inum)
436 static char *defaultpath[] = {
437 "/isa/asy@1,3f8:a",
438 "/isa/asy@1,2f8:b",
439 "/isa/asy@1,3e8:c",
440 "/isa/asy@1,2e8:d"
442 static char path[MAXPATHLEN];
443 char *bp;
444 major_t major;
445 dev_info_t *dip;
447 if (pseudo_isa)
448 return (defaultpath[inum]);
450 if ((major = ddi_name_to_major("asy")) == (major_t)-1)
451 return (NULL);
453 if ((dip = devnamesp[major].dn_head) == NULL)
454 return (NULL);
456 for (; dip != NULL; dip = ddi_get_next(dip)) {
457 if (i_ddi_attach_node_hierarchy(dip) != DDI_SUCCESS)
458 return (NULL);
460 if (DEVI(dip)->devi_minor->ddm_name[0] == ('a' + (char)inum))
461 break;
463 if (dip == NULL)
464 return (NULL);
466 (void) ddi_pathname(dip, path);
467 bp = path + strlen(path);
468 (void) snprintf(bp, 3, ":%s", DEVI(dip)->devi_minor->ddm_name);
470 return (path);
474 * Another possible enhancement could be to use properties
475 * for the port mapping rather than simply hard-code them.
477 char *
478 plat_stdinpath(void)
480 int tty_num = 0;
482 switch (console_type(&tty_num)) {
483 case CONS_TTY:
484 return (plat_ttypath(tty_num));
485 case CONS_USBSER:
486 return (plat_usbser_path());
487 case CONS_SCREEN_TEXT:
488 default:
489 break;
491 return (plat_kbdpath());
494 char *
495 plat_stdoutpath(void)
497 int tty_num = 0;
499 switch (console_type(&tty_num)) {
500 case CONS_TTY:
501 return (plat_ttypath(tty_num));
502 case CONS_USBSER:
503 return (plat_usbser_path());
504 case CONS_SCREEN_TEXT:
505 default:
506 break;
508 return (plat_fbpath());
512 * If VIS_PIXEL mode will be implemented on x86, these following
513 * functions should be re-considered. Now these functions are
514 * unused on x86.
516 void
517 plat_tem_get_inverses(int *inverse, int *inverse_screen)
519 *inverse = 0;
520 *inverse_screen = 0;
523 void
524 plat_tem_get_prom_font_size(int *charheight, int *windowtop)
526 *charheight = 0;
527 *windowtop = 0;
530 /*ARGSUSED*/
531 void
532 plat_tem_get_prom_size(size_t *height, size_t *width)
534 panic("unimplemented at line %d of %s", __LINE__, __FILE__);
537 void
538 plat_tem_hide_prom_cursor(void)
540 panic("unimplemented at line %d of %s", __LINE__, __FILE__);
543 /*ARGSUSED*/
544 void
545 plat_tem_get_prom_pos(uint32_t *row, uint32_t *col)
547 panic("unimplemented at line %d of %s", __LINE__, __FILE__);