summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/uts/i86pc/io/consplat.c156
1 files changed, 106 insertions, 50 deletions
diff --git a/usr/src/uts/i86pc/io/consplat.c b/usr/src/uts/i86pc/io/consplat.c
index 9d142c7dd8..bbb63c4923 100644
--- a/usr/src/uts/i86pc/io/consplat.c
+++ b/usr/src/uts/i86pc/io/consplat.c
@@ -42,6 +42,7 @@
#include <sys/promif.h>
#include <sys/modctl.h>
#include <sys/termios.h>
+#include <sys/pci.h>
#if defined(__xpv)
#include <sys/hypervisor.h>
#include <sys/boot_console.h>
@@ -49,16 +50,6 @@
extern int pseudo_isa;
-/* The names of currently supported graphics drivers on x86 */
-static char *
-gfxdrv_name[] = {
- "radeon",
- "vgatext",
- "i915",
- "atiatom",
- "nvidia",
-};
-
int
plat_use_polled_debug() {
return (0);
@@ -200,56 +191,121 @@ plat_kbdpath(void)
return (kbpath);
}
+static int
+find_fb_dev(dev_info_t *dip, void *found_dip)
+{
+ char *dev_type;
+ dev_info_t *pdip;
+ char *parent_type;
+
+ if (dip == ddi_root_node())
+ return (DDI_WALK_CONTINUE);
+
+ if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
+ "device_type", &dev_type) != DDI_SUCCESS)
+ return (DDI_WALK_PRUNECHILD);
+
+ if ((strcmp(dev_type, "isa") == 0) || (strcmp(dev_type, "eisa") == 0)) {
+ ddi_prop_free(dev_type);
+ return (DDI_WALK_CONTINUE);
+ }
+
+ if ((strcmp(dev_type, "pci") == 0) ||
+ (strcmp(dev_type, "pciex") == 0)) {
+ ddi_acc_handle_t pci_conf;
+ uint16_t data16;
+
+ ddi_prop_free(dev_type);
+
+ if (i_ddi_attach_node_hierarchy(dip) != DDI_SUCCESS)
+ return (DDI_WALK_CONTINUE);
+
+ if (pci_config_setup(dip, &pci_conf) != DDI_SUCCESS) {
+ /* This happends when it's the host bridge */
+ return (DDI_WALK_CONTINUE);
+ }
+
+ data16 = pci_config_get16(pci_conf, PCI_BCNF_BCNTRL);
+ pci_config_teardown(&pci_conf);
+
+ if (data16 & PCI_BCNF_BCNTRL_VGA_ENABLE)
+ return (DDI_WALK_CONTINUE);
+
+ return (DDI_WALK_PRUNECHILD);
+ }
+
+ if (strcmp(dev_type, "display") != 0) {
+ ddi_prop_free(dev_type);
+ return (DDI_WALK_CONTINUE);
+ }
+
+ ddi_prop_free(dev_type);
+
+ if ((pdip = ddi_get_parent(dip)) == NULL)
+ return (DDI_WALK_CONTINUE);
+
+ if (ddi_prop_lookup_string(DDI_DEV_T_ANY, pdip, DDI_PROP_DONTPASS,
+ "device_type", &parent_type) != DDI_SUCCESS)
+ return (DDI_WALK_CONTINUE);
+
+ if ((strcmp(parent_type, "isa") == 0) ||
+ (strcmp(parent_type, "eisa") == 0)) {
+ *(dev_info_t **)found_dip = dip;
+ ddi_prop_free(parent_type);
+ return (DDI_WALK_TERMINATE);
+ }
+
+ if ((strcmp(parent_type, "pci") == 0) ||
+ (strcmp(parent_type, "pciex") == 0)) {
+ ddi_acc_handle_t pci_conf;
+ uint16_t data16;
+
+ ddi_prop_free(parent_type);
+
+ if (i_ddi_attach_node_hierarchy(dip) != DDI_SUCCESS)
+ return (DDI_WALK_CONTINUE);
+
+ if (pci_config_setup(dip, &pci_conf) != DDI_SUCCESS)
+ return (DDI_WALK_CONTINUE);
+
+ data16 = pci_config_get16(pci_conf, PCI_CONF_COMM);
+ pci_config_teardown(&pci_conf);
+
+ if (!(data16 & PCI_COMM_IO))
+ return (DDI_WALK_CONTINUE);
+
+ *(dev_info_t **)found_dip = dip;
+ return (DDI_WALK_TERMINATE);
+ }
+
+ ddi_prop_free(parent_type);
+ return (DDI_WALK_CONTINUE);
+}
+
/*
- * Return generic path to display device from the alias.
+ * Conduct a width-first traverse searching for a display device which
+ * has either:
+ * 1) a VGA device.
+ * 2) a PCI VGA compatible device whose IO space is enabled
+ * and the VGA Enable bit of any PCI-PCI bridge above it is set.
+ *
+ * Return the device path as the console fb path.
*/
char *
plat_fbpath(void)
{
+ dev_info_t *fb_dip = NULL;
static char *fbpath = NULL;
static char fbpath_buf[MAXPATHLEN];
- major_t major;
- dev_info_t *dip, *dip_pseudo = NULL;
- int i;
-
- /* lookup the dip for the pseudo device */
- (void) resolve_pathname("/pseudo", &dip_pseudo, NULL, NULL);
-
- for (i = 0; i < A_CNT(gfxdrv_name); i++) {
- /*
- * look for first instance of each driver
- */
- if ((major = ddi_name_to_major(gfxdrv_name[i])) == (major_t)-1)
- continue;
-
- if ((dip = devnamesp[major].dn_head) == NULL)
- continue;
-
- /*
- * We're looking for a real hardware device here so skip
- * any pseudo devices. When could a framebuffer hardware
- * driver also have a pseudo node? Well, some framebuffer
- * hardware drivers (nvidia) also create pseudo nodes for
- * administration purposes, and these nodes will exist
- * regardless of if the actual associated hardware
- * is present or not.
- */
- if (ddi_get_parent(dip) == dip_pseudo)
- continue;
-
- if (i_ddi_attach_node_hierarchy(dip) == DDI_SUCCESS) {
- (void) ddi_pathname(dip, fbpath_buf);
- fbpath = fbpath_buf;
- }
- if (fbpath)
- break;
- }
+ ddi_walk_devs(ddi_root_node(), find_fb_dev, &fb_dip);
+
+ if (fb_dip == NULL)
+ return (NULL);
- if (dip_pseudo != NULL)
- ddi_release_devi(dip_pseudo);
+ (void) ddi_pathname(fb_dip, fbpath_buf);
+ fbpath = fbpath_buf;
- /* No screen found */
return (fbpath);
}