$Id: 080_pci_isolate_device_feature.diff 1218 2004-04-02 06:28:00Z branden $

Implement IsolateDevice and SingleCard layout options for XF86Config, and
-isolateDevice command-line flag for XFree86 X server.  Useful for
multi-card setups where different X servers run on each card.

This patch by Aivils Stoss <Aivils.Stoss@unibanka.lv>, licensed under the
GNU GPL.  Minor modifications by Andreas Schuldei and Branden Robinson;
documentation added by Branden Robinson.

--- xc/programs/Xserver/hw/xfree86/XF86Config.man~	2004-03-26 18:10:22.000000000 -0500
+++ xc/programs/Xserver/hw/xfree86/XF86Config.man	2004-03-26 18:53:20.000000000 -0500
@@ -1592,7 +1592,7 @@
 section provides information specific to the whole session, including
 session-specific
 .BR Options .
-The
+In addition to options specific to this section (described below), the
 .B ServerFlags
 options (described above) may be specified here, and ones given here
 override those given in the
@@ -1678,12 +1678,30 @@
 .RE
 .TP 7
 .B Options
-Any option permitted in the
+In addition to the following, any option permitted in the
 .B ServerFlags
 section may also be specified here.  When the same option appears in both
 places, the value given here overrides the one given in the
 .B ServerFlags
 section.
+.TP 7
+.BI "Option \*qIsolateDevice\*q  \*q" bus\-id \*q
+Restrict device resets to the specified
+.IR bus\-id .
+See the
+.B BusID
+option (described in
+.BR "DEVICE SECTION" ,
+above) for the format of the
+.I bus\-id
+parameter.  This option overrides
+.BR SingleCard ,
+if specified.  At present, only PCI devices can be isolated in this manner.
+.TP 7
+.BI "Option \*qSingleCard\*q  \*q" boolean \*q
+As
+.BR IsolateDevice ,
+except that the bus ID of the first device in the layout is used.
 .PP
 Here is an example of a
 .B ServerLayout
--- xc/programs/Xserver/hw/xfree86/XFree86.man~	2004-03-26 19:04:30.000000000 -0500
+++ xc/programs/Xserver/hw/xfree86/XFree86.man	2004-03-26 19:10:42.000000000 -0500
@@ -192,6 +192,19 @@
 this are downgraded from fatal errors to warnings.  This option should
 be used with care.
 .TP 8
+.B \-isolateDevice \fIbus\-id\fP
+Restrict device resets to the device at
+.IR bus\-id .
+The
+.I bus\-id
+string has the form
+.IB bustype : bus : device : function
+(e.g., \(oqPCI:1:0:0\(cq).
+At present, only isolation of PCI devices is supported; i.e., this option
+is ignored if
+.I bustype
+is anything other than \(oqPCI\(cq.
+.TP 8
 .B \-keeptty
 Prevent the server from detaching its initial controlling terminal.
 This option is only useful when debugging the server.  Not all platforms
diff -urN xc/programs/Xserver/hw/xfree86/common~/xf86Config.c xc/programs/Xserver/hw/xfree86/common/xf86Config.c
--- xc/programs/Xserver/hw/xfree86/common~/xf86Config.c	2004-03-26 18:29:19.000000000 -0500
+++ xc/programs/Xserver/hw/xfree86/common/xf86Config.c	2004-03-26 19:02:42.000000000 -0500
@@ -1416,6 +1416,20 @@
     return TRUE;
 }
 
+typedef enum {
+    LAYOUT_ISOLATEDEVICE,
+    LAYOUT_SINGLECARD
+} LayoutValues;
+
+static OptionInfoRec LayoutOptions[] = {
+  { LAYOUT_ISOLATEDEVICE,	"IsolateDevice",	OPTV_STRING,
+	{0}, FALSE },
+  { LAYOUT_SINGLECARD,		"SingleCard",		OPTV_BOOLEAN,
+	{0}, FALSE },
+  { -1,				NULL,			OPTV_NONE,
+	{0}, FALSE },
+};
+
 /*
  * figure out which layout is active, which screens are used in that layout,
  * which drivers and monitors are used in these screens
@@ -2213,6 +2227,8 @@
     const char *filename;
     char *searchpath;
     MessageType from = X_DEFAULT;
+    char *scanptr;
+    Bool singlecard = 0;
 
     if (getuid() == 0)
 	searchpath = ROOT_CONFIGPATH;
@@ -2283,6 +2299,29 @@
 	}
     }
 
+    xf86ProcessOptions(-1, xf86ConfigLayout.options, LayoutOptions);
+
+    if ((scanptr = xf86GetOptValString(LayoutOptions, LAYOUT_ISOLATEDEVICE))) {
+	; /* IsolateDevice specified; overrides SingleCard */
+    } else {
+	xf86GetOptValBool(LayoutOptions, LAYOUT_SINGLECARD, &singlecard);
+	if (singlecard)
+	    scanptr = xf86ConfigLayout.screens->screen->device->busID;
+    }
+    if (scanptr) {
+	int bus, device, func, stroffset = 0;
+	if (strncmp(scanptr, "PCI:", 4) != 0) {
+	    xf86Msg(X_WARNING, "Bus types other than PCI not yet isolable.\n"
+			       "\tIgnoring IsolateDevice option.\n");
+	} else if (sscanf(scanptr, "PCI:%d:%d:%d", &bus, &device, &func) == 3) {
+	    xf86IsolateDevice.bus = bus;
+	    xf86IsolateDevice.device = device;
+	    xf86IsolateDevice.func = func;
+	    xf86Msg(X_INFO,
+		    "Isolating PCI bus \"%d:%d:%d\"\n", bus, device, func);
+	}
+    }
+
     /* Now process everything else */
 
     if (!configFiles(xf86configptr->conf_files) ||
diff -urN xc/programs/Xserver/hw/xfree86/common~/xf86Globals.c xc/programs/Xserver/hw/xfree86/common/xf86Globals.c
--- xc/programs/Xserver/hw/xfree86/common~/xf86Globals.c	2004-03-26 18:29:19.000000000 -0500
+++ xc/programs/Xserver/hw/xfree86/common/xf86Globals.c	2004-03-26 18:29:40.000000000 -0500
@@ -215,6 +215,7 @@
 #endif
 PropertyPtr *xf86RegisteredPropertiesTable = NULL;
 Bool xf86inSuspend = FALSE;
+PciBusId xf86IsolateDevice;
 
 #ifdef DLOPEN_HACK
 /*
diff -urN xc/programs/Xserver/hw/xfree86/common~/xf86Init.c xc/programs/Xserver/hw/xfree86/common/xf86Init.c
--- xc/programs/Xserver/hw/xfree86/common~/xf86Init.c	2004-03-26 18:29:19.000000000 -0500
+++ xc/programs/Xserver/hw/xfree86/common/xf86Init.c	2004-03-26 19:17:21.000000000 -0500
@@ -1590,6 +1590,25 @@
     xf86AllowMouseOpenFail = TRUE;
     return 1;
   }
+  if (!strcmp(argv[i], "-isolateDevice"))
+  {
+    int bus, device, func;
+    if (++i >= argc)
+	return 0;
+    if (strncmp(argv[i], "PCI:", 4)) {
+	ErrorF("Bus types other than PCI not yet isolable\n");
+	return 0;
+    }
+    if (sscanf(argv[i], "PCI:%d:%d:%d", &bus, &device, &func) == 3) {
+	xf86IsolateDevice.bus = bus;
+	xf86IsolateDevice.device = device;
+	xf86IsolateDevice.func = func;
+	return 2;
+    } else {
+	ErrorF("Invalid isolated device specifiation\n");
+	return 0;
+    }
+  }
   /* OS-specific processing */
   return xf86ProcessArgument(argc, argv, i);
 }
@@ -1650,6 +1669,7 @@
 #endif
   ErrorF("-bestRefresh           choose modes with the best refresh rate\n");
   ErrorF("-ignoreABI             make module ABI mismatches non-fatal\n");
+  ErrorF("-isolateDevice bus_id  restrict device resets to bus_id (PCI only)\n");
   ErrorF("-version               show the server version\n");
   /* OS-specific usage */
   xf86UseMsg();
diff -urN xc/programs/Xserver/hw/xfree86/common~/xf86Priv.h xc/programs/Xserver/hw/xfree86/common/xf86Priv.h
--- xc/programs/Xserver/hw/xfree86/common~/xf86Priv.h	2004-03-26 18:29:19.000000000 -0500
+++ xc/programs/Xserver/hw/xfree86/common/xf86Priv.h	2004-03-26 18:29:40.000000000 -0500
@@ -53,6 +53,7 @@
 extern Gamma xf86Gamma;
 extern char *xf86ServerName;
 extern Bool xf86ShowUnresolved;
+extern PciBusId xf86IsolateDevice;
 
 /* Other parameters */
 
diff -urN xc/programs/Xserver/hw/xfree86/common~/xf86pciBus.c xc/programs/Xserver/hw/xfree86/common/xf86pciBus.c
--- xc/programs/Xserver/hw/xfree86/common~/xf86pciBus.c	2004-03-26 18:29:19.000000000 -0500
+++ xc/programs/Xserver/hw/xfree86/common/xf86pciBus.c	2004-03-26 19:04:03.000000000 -0500
@@ -160,7 +160,10 @@
     int num = 0;
     pciVideoPtr info;
     Bool mem64 = FALSE;
+    int DoIsolateDeviceCheck = 0;
 
+    if (xf86IsolateDevice.bus || xf86IsolateDevice.device || xf86IsolateDevice.func)
+	DoIsolateDeviceCheck = 1;
     pcrpp = xf86PciInfo = xf86scanpci(0);
     getPciClassFlags(pcrpp);
     
@@ -182,7 +185,11 @@
 	    subclass = pcrp->pci_sub_class;
 	}
 	
-	if (PCIINFOCLASSES(baseclass, subclass)) {
+	if (PCIINFOCLASSES(baseclass, subclass) &&
+	    (DoIsolateDeviceCheck ?
+	    (xf86IsolateDevice.bus == pcrp->busnum &&
+	     xf86IsolateDevice.device == pcrp->devnum &&
+	     xf86IsolateDevice.func == pcrp->funcnum) : 1)) {
 	    num++;
 	    xf86PciVideoInfo = xnfrealloc(xf86PciVideoInfo,
 					  sizeof(pciVideoPtr) * (num + 1));

