diff --git a/hw/xfree86/common/xf86AutoConfig.c b/hw/xfree86/common/xf86AutoConfig.c
index cc8976f..7a43694 100644
--- a/hw/xfree86/common/xf86AutoConfig.c
+++ b/hw/xfree86/common/xf86AutoConfig.c
@@ -1,8 +1,8 @@
/*
* Copyright 2003 by David H. Dawes.
* Copyright 2003 by X-Oz Technologies.
+ * Copyright (c) 2013 Oracle and/or its affiliates.
* All rights reserved.
- * Copyright (c) 2013 Oracle and/or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -49,6 +49,9 @@
#ifdef sun
#include <sys/visual_io.h>
#include <ctype.h>
+#if (defined(__sparc__) || defined(__sparc))
+static Bool MultiSessionConfig (void);
+#endif
#endif
/* Sections for the default built-in configuration. */
@@ -169,6 +172,10 @@ xf86AutoConfig(void)
char buf[1024];
ConfigStatus ret;
+#if ((defined(__sparc__) || defined(__sparc)) && defined (sun))
+ if (!MultiSessionConfig()) {
+#endif
+
listPossibleVideoDrivers(deviceList, 20);
for (p = deviceList; *p; p++) {
@@ -196,6 +203,9 @@ xf86AutoConfig(void)
for (p = deviceList; *p; p++) {
free(*p);
}
+#if ((defined(__sparc__) || defined(__sparc)) && defined (sun))
+ }
+#endif
xf86MsgVerb(X_DEFAULT, 0,
"Using default built-in configuration (%d lines)\n",
@@ -442,3 +452,173 @@ autoConfigDevice(GDevPtr preconf_device)
return ptr;
}
+
+#if ((defined(__sparc__) || defined(__sparc)) && defined (sun))
+#include <libdevinfo.h>
+#include <xorg/xf86Pci.h>
+#include "pciaccess.h"
+#include <sys/utsname.h>
+
+#define MAX_DEV 16
+
+#define IS_VGA(c) \
+ (((c) & 0x00ffff00) \
+ == ((PCI_CLASS_DISPLAY << 16) | (PCI_SUBCLASS_DISPLAY_VGA << 8)))
+
+#define BUILTIN_MULTI_SERVERFLAGS_OPT1 \
+ "\tOption\t\"DefaultServerLayout\"\t\"Xsession0\"\n"
+
+#define BUILTIN_MULTI_SECTION_POST \
+ "EndSection\n\n"
+
+#define BUILTIN_MULTI_SERVERFLAGS_OPT2 \
+ "\tOption\t\"AutoAddDevices\"\t\"true\"\n"
+
+#define BUILTIN_MULTI_SERVERFLAGS_SECTION \
+ "Section \"ServerFlags\"\n" \
+ BUILTIN_MULTI_SERVERFLAGS_OPT1 \
+ BUILTIN_MULTI_SERVERFLAGS_OPT2 \
+ BUILTIN_MULTI_SECTION_POST
+
+#define BUILTIN_MULTI_LAYOUT_SECTION_PRE \
+ "Section \"ServerLayout\"\n" \
+ "\tIdentifier\t\"Xsession%d\"\n"
+
+#define BUILTIN_MULTI_LAYOUT_SECTION_LINE \
+ "\tScreen\t\t\"Screen%d\"\n"
+
+#define BUILTIN_MULTI_SCREEN_SECTION_PRE \
+ "Section \"Screen\"\n" \
+ "\tIdentifier\t\"Screen%d\"\n"
+
+#define BUILTIN_MULTI_SCREEN_SECTION_LINE \
+ "\tDevice\t\t\"Card%d\"\n"
+
+#define BUILTIN_MULTI_DEVICE_SECTION_PRE \
+ "Section \"Device\"\n" \
+ "\tIdentifier\t\"Card%d\"\n"
+
+#define BUILTIN_MULTI_DEVICE_SECTION_LINE \
+ "\tBusID\t\t\"%s\"\n\tDriver\t\t\"%s\"\n"
+
+static Bool
+MultiSessionConfig (void)
+{
+ di_node_t node;
+ struct pci_device_iterator * iter;
+ struct pci_device * dev;
+ typedef struct {
+ char busid[64];
+ char dev_path[PATH_MAX];
+ } disp_dev_type;
+ disp_dev_type disp_dev[MAX_DEV];
+ int num = 0;
+ char buf[1024];
+ int i;
+ struct utsname sys;
+ struct sol_device_private {
+ struct pci_device base;
+ const char * device_string;
+ };
+#define DEV_PATH(dev) (((struct sol_device_private *) dev)->device_string)
+
+ if (uname(&sys) < 0) {
+ xf86Msg(X_ERROR, "Error in uname call\n");
+ return FALSE;
+ }
+
+ if (strcmp(sys.machine, "sun4v"))
+ return FALSE;
+
+ iter = pci_slot_match_iterator_create( NULL );
+
+ while ( (dev = pci_device_next( iter )) != NULL ) {
+ if (IS_VGA(dev->device_class)) {
+ if (num > MAX_DEV) {
+ xf86Msg(X_ERROR, "Too many display devices: %d\n", num);
+ return FALSE;
+ }
+
+ memset(&disp_dev[num], 0, sizeof (disp_dev_type));
+
+ snprintf(disp_dev[num].busid, sizeof(disp_dev[num].busid),
+ "PCI:%d@%d:%d:%d", dev->bus, dev->domain,
+ dev->dev, dev->func);
+
+ strcpy(disp_dev[num].dev_path, "/devices");
+ strncat(disp_dev[num].dev_path, DEV_PATH(dev),
+ sizeof(disp_dev_type) - strlen("/devices"));
+
+ num++;
+ }
+ }
+
+ pci_iterator_destroy(iter);
+
+ /* Do not do multi-session configuration if dev number is 0 or 1 */
+ if (num <= 1)
+ return FALSE;
+
+ snprintf(buf, sizeof(buf), BUILTIN_MULTI_SERVERFLAGS_SECTION);
+ AppendToConfig(buf);
+
+ for (i = 0; i < num; i++) {
+ char drv[32];
+
+ snprintf(buf, sizeof(buf), BUILTIN_MULTI_LAYOUT_SECTION_PRE, i);
+ AppendToConfig(buf);
+ snprintf(buf, sizeof(buf), BUILTIN_MULTI_LAYOUT_SECTION_LINE, i);
+ AppendToConfig(buf);
+ snprintf(buf, sizeof(buf), BUILTIN_MULTI_SECTION_POST);
+ AppendToConfig(buf);
+
+ snprintf(buf, sizeof(buf), BUILTIN_MULTI_SCREEN_SECTION_PRE, i);
+ AppendToConfig(buf);
+ snprintf(buf, sizeof(buf), BUILTIN_MULTI_SCREEN_SECTION_LINE, i);
+ AppendToConfig(buf);
+ snprintf(buf, sizeof(buf), BUILTIN_MULTI_SECTION_POST);
+ AppendToConfig(buf);
+
+ snprintf(buf, sizeof(buf), BUILTIN_MULTI_DEVICE_SECTION_PRE, i);
+ AppendToConfig(buf);
+
+ drv[0] = 0;
+ if (disp_dev[i].dev_path) {
+ int iret;
+ int fd;
+
+ fd = open(disp_dev[i].dev_path, O_RDONLY);
+ if (fd >= 0) {
+ struct vis_identifier visid;
+ const char *cp;
+
+ SYSCALL(iret = ioctl(fd, VIS_GETIDENTIFIER, &visid));
+ close (fd);
+
+ if (iret >= 0) {
+ if (strcmp(visid.name, "SUNWtext") != 0) {
+ for (cp = visid.name; (*cp != '\0') && isupper((uchar_t)*cp); cp++);
+ /* find end of all uppercase vendor section */
+ if ((cp != visid.name) && (*cp != '\0'))
+ strncpy (drv, cp, sizeof(drv));
+ }
+ }
+ }
+ }
+
+ if (drv[0] == 0) {
+ xf86Msg(X_ERROR, "Can't find driver for session %d\n", i);
+ FreeConfig();
+ return FALSE;
+ }
+
+ snprintf(buf, sizeof(buf), BUILTIN_MULTI_DEVICE_SECTION_LINE,
+ disp_dev[i].busid, drv);
+ AppendToConfig(buf);
+ snprintf(buf, sizeof(buf), BUILTIN_MULTI_SECTION_POST);
+ AppendToConfig(buf);
+ }
+
+ return TRUE;
+}
+#endif