summaryrefslogtreecommitdiff
path: root/hw/xfree86/common
diff options
context:
space:
mode:
Diffstat (limited to 'hw/xfree86/common')
-rw-r--r--hw/xfree86/common/extramodes33
-rw-r--r--hw/xfree86/common/fourcc.h130
-rw-r--r--hw/xfree86/common/modeline2c.pl79
-rw-r--r--hw/xfree86/common/vesamodes111
-rw-r--r--hw/xfree86/common/xf86Bus.c3205
-rw-r--r--hw/xfree86/common/xf86Bus.h135
-rw-r--r--hw/xfree86/common/xf86Config.h27
-rw-r--r--hw/xfree86/common/xf86Configure.c997
-rw-r--r--hw/xfree86/common/xf86DGA.c1181
-rw-r--r--hw/xfree86/common/xf86DPMS.c175
-rw-r--r--hw/xfree86/common/xf86Date.h7
-rw-r--r--hw/xfree86/common/xf86Debug.c162
-rw-r--r--hw/xfree86/common/xf86DefModes.c153
-rw-r--r--hw/xfree86/common/xf86DoProbe.c83
-rw-r--r--hw/xfree86/common/xf86DoScanPci.c97
-rw-r--r--hw/xfree86/common/xf86Globals.c224
-rw-r--r--hw/xfree86/common/xf86Helper.c2994
-rw-r--r--hw/xfree86/common/xf86InPriv.h17
-rw-r--r--hw/xfree86/common/xf86MiscExt.c612
-rw-r--r--hw/xfree86/common/xf86Mode.c1999
-rw-r--r--hw/xfree86/common/xf86Module.h203
-rw-r--r--hw/xfree86/common/xf86Opt.h82
-rw-r--r--hw/xfree86/common/xf86Option.c777
-rw-r--r--hw/xfree86/common/xf86PM.c188
-rw-r--r--hw/xfree86/common/xf86PciInfo.h573
-rw-r--r--hw/xfree86/common/xf86Privstr.h234
-rw-r--r--hw/xfree86/common/xf86RandR.c280
-rw-r--r--hw/xfree86/common/xf86Resources.h113
-rw-r--r--hw/xfree86/common/xf86VidMode.c683
-rw-r--r--hw/xfree86/common/xf86cmap.c1081
-rw-r--r--hw/xfree86/common/xf86cmap.h62
-rw-r--r--hw/xfree86/common/xf86fbBus.c70
-rw-r--r--hw/xfree86/common/xf86fbman.c1236
-rw-r--r--hw/xfree86/common/xf86fbman.h193
-rw-r--r--hw/xfree86/common/xf86isaBus.c115
-rw-r--r--hw/xfree86/common/xf86noBus.c48
-rw-r--r--hw/xfree86/common/xf86pciBus.c3493
-rw-r--r--hw/xfree86/common/xf86pciBus.h72
-rw-r--r--hw/xfree86/common/xf86sbusBus.c705
-rw-r--r--hw/xfree86/common/xf86sbusBus.h98
-rw-r--r--hw/xfree86/common/xf86str.h1029
-rw-r--r--hw/xfree86/common/xf86xv.c1935
-rw-r--r--hw/xfree86/common/xf86xv.h272
-rw-r--r--hw/xfree86/common/xf86xvmc.c201
-rw-r--r--hw/xfree86/common/xf86xvmc.h134
-rw-r--r--hw/xfree86/common/xisb.c172
-rw-r--r--hw/xfree86/common/xisb.h64
47 files changed, 26534 insertions, 0 deletions
diff --git a/hw/xfree86/common/extramodes b/hw/xfree86/common/extramodes
new file mode 100644
index 000000000..f7dc01216
--- /dev/null
+++ b/hw/xfree86/common/extramodes
@@ -0,0 +1,33 @@
+//
+// Extra modes to include as default modes in the X server.
+//
+// $XFree86: xc/programs/Xserver/hw/xfree86/etc/extramodes,v 1.6 2002/11/11 04:21:46 dawes Exp $
+//
+
+# 832x624 @ 75Hz (74.55Hz) (fix if the official/Apple spec is different) hsync: 49.725kHz
+ModeLine "832x624" 57.284 832 864 928 1152 624 625 628 667 -Hsync -Vsync
+
+# 1152x768 @ 54.8Hz (Titanium PowerBook) hsync: 44.2kHz
+ModeLine "1152x768" 64.995 1152 1178 1314 1472 768 771 777 806 +hsync +vsync
+
+# 1400x1050 @ 60Hz (VESA GTF) hsync: 65.5kHz
+ModeLine "1400x1050" 122.0 1400 1488 1640 1880 1050 1052 1064 1082 +hsync +vsync
+
+# 1400x1050 @ 75Hz (VESA GTF) hsync: 82.2kHz
+ModeLine "1400x1050" 155.8 1400 1464 1784 1912 1050 1052 1064 1090 +hsync +vsync
+
+# 1600x1024 @ 60Hz (SGI 1600SW) hsync: 64.0kHz
+Modeline "1600x1024" 106.910 1600 1620 1640 1670 1024 1027 1030 1067 -hsync -vsync
+
+# 1920x1440 @ 85Hz (VESA GTF) hsync: 128.5kHz
+Modeline "1920x1440" 341.35 1920 2072 2288 2656 1440 1441 1444 1512 -hsync +vsync
+
+# 2048x1536 @ 60Hz (VESA GTF) hsync: 95.3kHz
+Modeline "2048x1536" 266.95 2048 2200 2424 2800 1536 1537 1540 1589 -hsync +vsync
+
+# 2048x1536 @ 75Hz (VESA GTF) hsync: 120.2kHz
+Modeline "2048x1536" 340.48 2048 2216 2440 2832 1536 1537 1540 1603 -hsync +vsync
+
+# 2048x1536 @ 85Hz (VESA GTF) hsync: 137.0kHz
+Modeline "2048x1536" 388.04 2048 2216 2440 2832 1536 1537 1540 1612 -hsync +vsync
+
diff --git a/hw/xfree86/common/fourcc.h b/hw/xfree86/common/fourcc.h
new file mode 100644
index 000000000..61f403679
--- /dev/null
+++ b/hw/xfree86/common/fourcc.h
@@ -0,0 +1,130 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/common/fourcc.h,v 1.3 2001/12/03 22:13:24 mvojkovi Exp $ */
+
+/*
+ This header file contains listings of STANDARD guids for video formats.
+ Please do not place non-registered, or incomplete entries in this file.
+ A list of some popular fourcc's are at: http://www.webartz.com/fourcc/
+ For an explanation of fourcc <-> guid mappings see RFC2361.
+*/
+
+#define FOURCC_YUY2 0x32595559
+#define XVIMAGE_YUY2 \
+ { \
+ FOURCC_YUY2, \
+ XvYUV, \
+ LSBFirst, \
+ {'Y','U','Y','2', \
+ 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \
+ 16, \
+ XvPacked, \
+ 1, \
+ 0, 0, 0, 0, \
+ 8, 8, 8, \
+ 1, 2, 2, \
+ 1, 1, 1, \
+ {'Y','U','Y','V', \
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, \
+ XvTopToBottom \
+ }
+
+#define FOURCC_YV12 0x32315659
+#define XVIMAGE_YV12 \
+ { \
+ FOURCC_YV12, \
+ XvYUV, \
+ LSBFirst, \
+ {'Y','V','1','2', \
+ 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \
+ 12, \
+ XvPlanar, \
+ 3, \
+ 0, 0, 0, 0, \
+ 8, 8, 8, \
+ 1, 2, 2, \
+ 1, 2, 2, \
+ {'Y','V','U', \
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, \
+ XvTopToBottom \
+ }
+
+#define FOURCC_I420 0x30323449
+#define XVIMAGE_I420 \
+ { \
+ FOURCC_I420, \
+ XvYUV, \
+ LSBFirst, \
+ {'I','4','2','0', \
+ 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \
+ 12, \
+ XvPlanar, \
+ 3, \
+ 0, 0, 0, 0, \
+ 8, 8, 8, \
+ 1, 2, 2, \
+ 1, 2, 2, \
+ {'Y','U','V', \
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, \
+ XvTopToBottom \
+ }
+
+
+#define FOURCC_UYVY 0x59565955
+#define XVIMAGE_UYVY \
+ { \
+ FOURCC_UYVY, \
+ XvYUV, \
+ LSBFirst, \
+ {'U','Y','V','Y', \
+ 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \
+ 16, \
+ XvPacked, \
+ 1, \
+ 0, 0, 0, 0, \
+ 8, 8, 8, \
+ 1, 2, 2, \
+ 1, 1, 1, \
+ {'U','Y','V','Y', \
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, \
+ XvTopToBottom \
+ }
+
+#define FOURCC_IA44 0x34344149
+#define XVIMAGE_IA44 \
+ { \
+ FOURCC_IA44, \
+ XvYUV, \
+ LSBFirst, \
+ {'I','A','4','4', \
+ 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \
+ 8, \
+ XvPacked, \
+ 1, \
+ 0, 0, 0, 0, \
+ 8, 8, 8, \
+ 1, 1, 1, \
+ 1, 1, 1, \
+ {'A','I', \
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, \
+ XvTopToBottom \
+ }
+
+#define FOURCC_AI44 0x34344941
+#define XVIMAGE_AI44 \
+ { \
+ FOURCC_AI44, \
+ XvYUV, \
+ LSBFirst, \
+ {'A','I','4','4', \
+ 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \
+ 8, \
+ XvPacked, \
+ 1, \
+ 0, 0, 0, 0, \
+ 8, 8, 8, \
+ 1, 1, 1, \
+ 1, 1, 1, \
+ {'I','A', \
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, \
+ XvTopToBottom \
+ }
+
diff --git a/hw/xfree86/common/modeline2c.pl b/hw/xfree86/common/modeline2c.pl
new file mode 100644
index 000000000..fb76789d6
--- /dev/null
+++ b/hw/xfree86/common/modeline2c.pl
@@ -0,0 +1,79 @@
+#!/usr/bin/perl
+
+# automatically generate the xf86DefModeSet.c file from a normal
+# XF86Config style file of Modelines
+#
+# run as
+#
+# perl /modeline2c.pl < [modesfile] > xf86DefModes.c
+#
+# hackish perl - author Dirk Hohndel
+# Copyright 1999-2001 by The XFree86 Project, Inc.
+#
+# $XFree86: xc/programs/Xserver/hw/xfree86/common/modeline2c.pl,v 1.8 2001/10/28 03:33:17 tsi Exp $
+
+#my %flagshash;
+$flagshash{""} = "0";
+# $flagshash{"Interlace"} = "V_INTERLACE";
+# $flagshash{"+hsync"} = "V_PHSYNC";
+# $flagshash{"-hsync"} = "V_NHSYNC";
+# $flagshash{"+vsync"} = "V_PVSYNC";
+# $flagshash{"-vsync"} = "V_NVSYNC";
+# XXX I'm definitely not a perl guru... -- tsi
+$flagshash{"+hsync +vsync"} = "V_PHSYNC | V_PVSYNC";
+$flagshash{"+hsync -vsync"} = "V_PHSYNC | V_NVSYNC";
+$flagshash{"-hsync +vsync"} = "V_NHSYNC | V_PVSYNC";
+$flagshash{"-hsync -vsync"} = "V_NHSYNC | V_NVSYNC";
+$flagshash{"+hsync +vsync interlace"} = "V_PHSYNC | V_PVSYNC | V_INTERLACE";
+$flagshash{"+hsync -vsync interlace"} = "V_PHSYNC | V_NVSYNC | V_INTERLACE";
+$flagshash{"-hsync +vsync interlace"} = "V_NHSYNC | V_PVSYNC | V_INTERLACE";
+$flagshash{"-hsync -vsync interlace"} = "V_NHSYNC | V_NVSYNC | V_INTERLACE";
+
+# stop CVS from expanding the XFree86 Id here...
+
+$proj = "XFree86";
+printf("/* \$$proj: \$ */
+
+/* THIS FILE IS AUTOMATICALLY GENERATED -- DO NOT EDIT -- LOOK at
+ * modeline2c.pl */
+
+/*
+ * Copyright 1999 by The XFree86 Project, Inc.
+ *
+ * Author: Dirk Hohndel <hohndel\@XFree86.Org>
+ */
+
+#include \"xf86.h\"
+#include \"xf86Config.h\"
+#include \"xf86Priv.h\"
+#include \"xf86_OSlib.h\"
+
+#include \"globals.h\"
+
+#define MODEPREFIX(name) NULL, NULL, name, 0,M_T_DEFAULT
+#define MODESUFFIX 0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0,FALSE,FALSE,0,NULL,0,0.0,0.0
+
+DisplayModeRec xf86DefaultModes [] = {
+");
+while (<>) {
+ if (/^\#/) {
+ s/^\#//;
+ chop;
+ print "/*" . $_ . " */\n";
+ }
+ if (/^ModeLine\s+(\S+)\s+([\d.\s]+)(.*)/i) {
+ $name = $1;
+ $values = $2;
+ $flags = $3;
+ $flags =~ y/A-Z/a-z/;
+ $values =~ /([\d.]+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)/;
+ printf("\t{MODEPREFIX(%s),%d, %d,%d,%d,%d,0, %d,%d,%d,%d,0, %s, MODESUFFIX},\n",
+ $name,$1*1000,$2,$3,$4,$5,$6,$7,$8,$9,$flagshash{$flags});
+# Also generate half-width doublescanned modes
+ printf("\t{MODEPREFIX(\"%dx%d\"),%d, %d,%d,%d,%d,0, %d,%d,%d,%d,0, %s | V_DBLSCAN, MODESUFFIX},\n",
+ $2/2,$6/2,$1*500,$2/2,$3/2,$4/2,$5/2,$6/2,$7/2,$8/2,$9/2,$flagshash{$flags});
+ }
+
+
+}
+printf("\t{MODEPREFIX(NULL),0,0,0,0,0,0,0,0,0,0,0,0,MODESUFFIX}\n};\n");
diff --git a/hw/xfree86/common/vesamodes b/hw/xfree86/common/vesamodes
new file mode 100644
index 000000000..d2df5931a
--- /dev/null
+++ b/hw/xfree86/common/vesamodes
@@ -0,0 +1,111 @@
+//
+// Default modes distilled from
+// "VESA and Industry Standards and Guide for Computer Display Monitor
+// Timing", version 1.0, revision 0.8, adopted September 17, 1998.
+//
+// $XFree86: xc/programs/Xserver/hw/xfree86/etc/vesamodes,v 1.4 1999/11/18 16:52:17 tsi Exp $
+
+
+# 640x350 @ 85Hz (VESA) hsync: 37.9kHz
+ModeLine "640x350" 31.5 640 672 736 832 350 382 385 445 +hsync -vsync
+
+# 640x400 @ 85Hz (VESA) hsync: 37.9kHz
+ModeLine "640x400" 31.5 640 672 736 832 400 401 404 445 -hsync +vsync
+
+# 720x400 @ 85Hz (VESA) hsync: 37.9kHz
+ModeLine "720x400" 35.5 720 756 828 936 400 401 404 446 -hsync +vsync
+
+# 640x480 @ 60Hz (Industry standard) hsync: 31.5kHz
+ModeLine "640x480" 25.2 640 656 752 800 480 490 492 525 -hsync -vsync
+
+# 640x480 @ 72Hz (VESA) hsync: 37.9kHz
+ModeLine "640x480" 31.5 640 664 704 832 480 489 491 520 -hsync -vsync
+
+# 640x480 @ 75Hz (VESA) hsync: 37.5kHz
+ModeLine "640x480" 31.5 640 656 720 840 480 481 484 500 -hsync -vsync
+
+# 640x480 @ 85Hz (VESA) hsync: 43.3kHz
+ModeLine "640x480" 36.0 640 696 752 832 480 481 484 509 -hsync -vsync
+
+# 800x600 @ 56Hz (VESA) hsync: 35.2kHz
+ModeLine "800x600" 36.0 800 824 896 1024 600 601 603 625 +hsync +vsync
+
+# 800x600 @ 60Hz (VESA) hsync: 37.9kHz
+ModeLine "800x600" 40.0 800 840 968 1056 600 601 605 628 +hsync +vsync
+
+# 800x600 @ 72Hz (VESA) hsync: 48.1kHz
+ModeLine "800x600" 50.0 800 856 976 1040 600 637 643 666 +hsync +vsync
+
+# 800x600 @ 75Hz (VESA) hsync: 46.9kHz
+ModeLine "800x600" 49.5 800 816 896 1056 600 601 604 625 +hsync +vsync
+
+# 800x600 @ 85Hz (VESA) hsync: 53.7kHz
+ModeLine "800x600" 56.3 800 832 896 1048 600 601 604 631 +hsync +vsync
+
+# 1024x768i @ 43Hz (industry standard) hsync: 35.5kHz
+ModeLine "1024x768" 44.9 1024 1032 1208 1264 768 768 776 817 +hsync +vsync Interlace
+
+# 1024x768 @ 60Hz (VESA) hsync: 48.4kHz
+ModeLine "1024x768" 65.0 1024 1048 1184 1344 768 771 777 806 -hsync -vsync
+
+# 1024x768 @ 70Hz (VESA) hsync: 56.5kHz
+ModeLine "1024x768" 75.0 1024 1048 1184 1328 768 771 777 806 -hsync -vsync
+
+# 1024x768 @ 75Hz (VESA) hsync: 60.0kHz
+ModeLine "1024x768" 78.8 1024 1040 1136 1312 768 769 772 800 +hsync +vsync
+
+# 1024x768 @ 85Hz (VESA) hsync: 68.7kHz
+ModeLine "1024x768" 94.5 1024 1072 1168 1376 768 769 772 808 +hsync +vsync
+
+# 1152x864 @ 75Hz (VESA) hsync: 67.5kHz
+ModeLine "1152x864" 108.0 1152 1216 1344 1600 864 865 868 900 +hsync +vsync
+
+# 1280x960 @ 60Hz (VESA) hsync: 60.0kHz
+ModeLine "1280x960" 108.0 1280 1376 1488 1800 960 961 964 1000 +hsync +vsync
+
+# 1280x960 @ 85Hz (VESA) hsync: 85.9kHz
+ModeLine "1280x960" 148.5 1280 1344 1504 1728 960 961 964 1011 +hsync +vsync
+
+# 1280x1024 @ 60Hz (VESA) hsync: 64.0kHz
+ModeLine "1280x1024" 108.0 1280 1328 1440 1688 1024 1025 1028 1066 +hsync +vsync
+
+# 1280x1024 @ 75Hz (VESA) hsync: 80.0kHz
+ModeLine "1280x1024" 135.0 1280 1296 1440 1688 1024 1025 1028 1066 +hsync +vsync
+
+# 1280x1024 @ 85Hz (VESA) hsync: 91.1kHz
+ModeLine "1280x1024" 157.5 1280 1344 1504 1728 1024 1025 1028 1072 +hsync +vsync
+
+# 1600x1200 @ 60Hz (VESA) hsync: 75.0kHz
+ModeLine "1600x1200" 162.0 1600 1664 1856 2160 1200 1201 1204 1250 +hsync +vsync
+
+# 1600x1200 @ 65Hz (VESA) hsync: 81.3kHz
+ModeLine "1600x1200" 175.5 1600 1664 1856 2160 1200 1201 1204 1250 +hsync +vsync
+
+# 1600x1200 @ 70Hz (VESA) hsync: 87.5kHz
+ModeLine "1600x1200" 189.0 1600 1664 1856 2160 1200 1201 1204 1250 +hsync +vsync
+
+# 1600x1200 @ 75Hz (VESA) hsync: 93.8kHz
+ModeLine "1600x1200" 202.5 1600 1664 1856 2160 1200 1201 1204 1250 +hsync +vsync
+
+# 1600x1200 @ 85Hz (VESA) hsync: 106.3kHz
+ModeLine "1600x1200" 229.5 1600 1664 1856 2160 1200 1201 1204 1250 +hsync +vsync
+
+# 1792x1344 @ 60Hz (VESA) hsync: 83.6kHz
+ModeLine "1792x1344" 204.8 1792 1920 2120 2448 1344 1345 1348 1394 -hsync +vsync
+
+# 1792x1344 @ 75Hz (VESA) hsync: 106.3kHz
+ModeLine "1792x1344" 261.0 1792 1888 2104 2456 1344 1345 1348 1417 -hsync +vsync
+
+# 1856x1392 @ 60Hz (VESA) hsync: 86.3kHz
+ModeLine "1856x1392" 218.3 1856 1952 2176 2528 1392 1393 1396 1439 -hsync +vsync
+
+# 1856x1392 @ 75Hz (VESA) hsync: 112.5kHz
+ModeLine "1856x1392" 288.0 1856 1984 2208 2560 1392 1393 1396 1500 -hsync +vsync
+
+# 1920x1440 @ 60Hz (VESA) hsync: 90.0kHz
+ModeLine "1920x1440" 234.0 1920 2048 2256 2600 1440 1441 1444 1500 -hsync +vsync
+
+# 1920x1440 @ 75Hz (VESA) hsync: 112.5kHz
+ModeLine "1920x1440" 297.0 1920 2064 2288 2640 1440 1441 1444 1500 -hsync +vsync
+
+
diff --git a/hw/xfree86/common/xf86Bus.c b/hw/xfree86/common/xf86Bus.c
new file mode 100644
index 000000000..fd9e3c3d1
--- /dev/null
+++ b/hw/xfree86/common/xf86Bus.c
@@ -0,0 +1,3205 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86Bus.c,v 1.76 2003/02/21 17:19:34 tsi Exp $ */
+/*
+ * Copyright (c) 1997-1999 by The XFree86 Project, Inc.
+ */
+#define REDUCER
+/*
+ * This file contains the interfaces to the bus-specific code
+ */
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "X.h"
+#include "os.h"
+#include "xf86.h"
+#include "xf86Priv.h"
+#include "xf86Resources.h"
+
+/* Bus-specific headers */
+
+#include "xf86Bus.h"
+
+#define XF86_OS_PRIVS
+#define NEED_OS_RAC_PROTOS
+#include "xf86_OSproc.h"
+
+#include "xf86RAC.h"
+
+/* Entity data */
+EntityPtr *xf86Entities = NULL; /* Bus slots claimed by drivers */
+int xf86NumEntities = 0;
+static int xf86EntityPrivateCount = 0;
+BusAccPtr xf86BusAccInfo = NULL;
+
+xf86AccessRec AccessNULL = {NULL,NULL,NULL};
+
+xf86CurrentAccessRec xf86CurrentAccess = {NULL,NULL};
+
+BusRec primaryBus = { BUS_NONE, {{0}}};
+
+Bool xf86ResAccessEnter = FALSE;
+
+#ifdef REDUCER
+/* Resources that temporarily conflict with estimated resources */
+static resPtr AccReducers = NULL;
+#endif
+
+/* resource lists */
+resPtr Acc = NULL;
+resPtr osRes = NULL;
+
+/* allocatable ranges */
+resPtr ResRange = NULL;
+
+/* predefined special resources */
+resRange resVgaExclusive[] = {_VGA_EXCLUSIVE, _END};
+resRange resVgaShared[] = {_VGA_SHARED, _END};
+resRange resVgaMemShared[] = {_VGA_SHARED_MEM,_END};
+resRange resVgaIoShared[] = {_VGA_SHARED_IO,_END};
+resRange resVgaUnusedExclusive[] = {_VGA_EXCLUSIVE_UNUSED, _END};
+resRange resVgaUnusedShared[] = {_VGA_SHARED_UNUSED, _END};
+resRange resVgaSparseExclusive[] = {_VGA_EXCLUSIVE_SPARSE, _END};
+resRange resVgaSparseShared[] = {_VGA_SHARED_SPARSE, _END};
+resRange res8514Exclusive[] = {_8514_EXCLUSIVE, _END};
+resRange res8514Shared[] = {_8514_SHARED, _END};
+
+/* Flag: do we need RAC ? */
+static Bool needRAC = FALSE;
+static Bool doFramebufferMode = FALSE;
+
+/* state change notification callback list */
+static StateChangeNotificationPtr StateChangeNotificationList;
+static void notifyStateChange(xf86NotifyState state);
+
+#undef MIN
+#define MIN(x,y) ((x<y)?x:y)
+
+
+/*
+ * Call the bus probes relevant to the architecture.
+ *
+ * The only one available so far is for PCI and SBUS.
+ */
+
+void
+xf86BusProbe(void)
+{
+ xf86PciProbe();
+#if defined(__sparc__) && !defined(__OpenBSD__)
+ xf86SbusProbe();
+#endif
+}
+
+/*
+ * Determine what bus type the busID string represents. The start of the
+ * bus-dependent part of the string is returned as retID.
+ */
+
+BusType
+StringToBusType(const char* busID, const char **retID)
+{
+ char *p, *s;
+ BusType ret = BUS_NONE;
+
+ /* If no type field, Default to PCI */
+ if (isdigit(busID[0])) {
+ if (retID)
+ *retID = busID;
+ return BUS_PCI;
+ }
+
+ s = xstrdup(busID);
+ p = strtok(s, ":");
+ if (p == NULL || *p == 0) {
+ xfree(s);
+ return BUS_NONE;
+ }
+ if (!xf86NameCmp(p, "pci") || !xf86NameCmp(p, "agp"))
+ ret = BUS_PCI;
+ if (!xf86NameCmp(p, "isa"))
+ ret = BUS_ISA;
+ if (!xf86NameCmp(p, "sbus"))
+ ret = BUS_SBUS;
+ if (ret != BUS_NONE)
+ if (retID)
+ *retID = busID + strlen(p) + 1;
+ xfree(s);
+ return ret;
+}
+
+/*
+ * Entity related code.
+ */
+
+void
+xf86EntityInit(void)
+{
+ int i;
+ resPtr *pprev_next;
+ resPtr res;
+ xf86AccessPtr pacc;
+
+ for (i = 0; i < xf86NumEntities; i++)
+ if (xf86Entities[i]->entityInit) {
+ if (xf86Entities[i]->access->busAcc)
+ ((BusAccPtr)xf86Entities[i]->access->busAcc)->set_f
+ (xf86Entities[i]->access->busAcc);
+ pacc = xf86Entities[i]->access->fallback;
+ if (pacc->AccessEnable)
+ pacc->AccessEnable(pacc->arg);
+ xf86Entities[i]->entityInit(i,xf86Entities[i]->private);
+ if (pacc->AccessDisable)
+ pacc->AccessDisable(pacc->arg);
+ /* remove init resources after init is processed */
+ pprev_next = &Acc;
+ res = Acc;
+ while (res) {
+ if (res->res_type & ResInit && (res->entityIndex == i)) {
+ (*pprev_next) = res->next;
+ xfree(res);
+ } else
+ pprev_next = &(res->next);
+ res = (*pprev_next);
+ }
+ }
+}
+
+int
+xf86AllocateEntity(void)
+{
+ xf86NumEntities++;
+ xf86Entities = xnfrealloc(xf86Entities,
+ sizeof(EntityPtr) * xf86NumEntities);
+ xf86Entities[xf86NumEntities - 1] = xnfcalloc(1,sizeof(EntityRec));
+ xf86Entities[xf86NumEntities - 1]->entityPrivates =
+ xnfcalloc(sizeof(DevUnion) * xf86EntityPrivateCount, 1);
+ return (xf86NumEntities - 1);
+}
+
+static void
+EntityEnter(void)
+{
+ int i;
+ xf86AccessPtr pacc;
+
+ for (i = 0; i < xf86NumEntities; i++)
+ if (xf86Entities[i]->entityEnter) {
+ if (xf86Entities[i]->access->busAcc)
+ ((BusAccPtr)xf86Entities[i]->access->busAcc)->set_f
+ (xf86Entities[i]->access->busAcc);
+ pacc = xf86Entities[i]->access->fallback;
+ if (pacc->AccessEnable)
+ pacc->AccessEnable(pacc->arg);
+ xf86Entities[i]->entityEnter(i,xf86Entities[i]->private);
+ if (pacc->AccessDisable)
+ pacc->AccessDisable(pacc->arg);
+ }
+}
+
+static void
+EntityLeave(void)
+{
+ int i;
+ xf86AccessPtr pacc;
+
+ for (i = 0; i < xf86NumEntities; i++)
+ if (xf86Entities[i]->entityLeave) {
+ if (xf86Entities[i]->access->busAcc)
+ ((BusAccPtr)xf86Entities[i]->access->busAcc)->set_f
+ (xf86Entities[i]->access->busAcc);
+ pacc = xf86Entities[i]->access->fallback;
+ if (pacc->AccessEnable)
+ pacc->AccessEnable(pacc->arg);
+ xf86Entities[i]->entityLeave(i,xf86Entities[i]->private);
+ if (pacc->AccessDisable)
+ pacc->AccessDisable(pacc->arg);
+ }
+}
+
+Bool
+xf86IsEntityPrimary(int entityIndex)
+{
+ EntityPtr pEnt = xf86Entities[entityIndex];
+
+ if (primaryBus.type != pEnt->busType) return FALSE;
+
+ switch (pEnt->busType) {
+ case BUS_PCI:
+ return (pEnt->pciBusId.bus == primaryBus.id.pci.bus &&
+ pEnt->pciBusId.device == primaryBus.id.pci.device &&
+ pEnt->pciBusId.func == primaryBus.id.pci.func);
+ case BUS_ISA:
+ return TRUE;
+ case BUS_SBUS:
+ return (pEnt->sbusBusId.fbNum == primaryBus.id.sbus.fbNum);
+ default:
+ return FALSE;
+ }
+}
+
+Bool
+xf86SetEntityFuncs(int entityIndex, EntityProc init, EntityProc enter,
+ EntityProc leave, pointer private)
+{
+ if (entityIndex >= xf86NumEntities)
+ return FALSE;
+ xf86Entities[entityIndex]->entityInit = init;
+ xf86Entities[entityIndex]->entityEnter = enter;
+ xf86Entities[entityIndex]->entityLeave = leave;
+ xf86Entities[entityIndex]->private = private;
+ return TRUE;
+}
+
+Bool
+xf86DriverHasEntities(DriverPtr drvp)
+{
+ int i;
+ for (i = 0; i < xf86NumEntities; i++) {
+ if (xf86Entities[i]->driver == drvp)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void
+xf86AddEntityToScreen(ScrnInfoPtr pScrn, int entityIndex)
+{
+ if (entityIndex == -1)
+ return;
+ if (xf86Entities[entityIndex]->inUse &&
+ !(xf86Entities[entityIndex]->entityProp & IS_SHARED_ACCEL))
+ FatalError("Requested Entity already in use!\n");
+
+ pScrn->numEntities++;
+ pScrn->entityList = xnfrealloc(pScrn->entityList,
+ pScrn->numEntities * sizeof(int));
+ pScrn->entityList[pScrn->numEntities - 1] = entityIndex;
+ xf86Entities[entityIndex]->access->next = pScrn->access;
+ pScrn->access = xf86Entities[entityIndex]->access;
+ xf86Entities[entityIndex]->inUse = TRUE;
+ pScrn->entityInstanceList = xnfrealloc(pScrn->entityInstanceList,
+ pScrn->numEntities * sizeof(int));
+ pScrn->entityInstanceList[pScrn->numEntities - 1] = 0;
+ pScrn->domainIOBase = xf86Entities[entityIndex]->domainIO;
+}
+
+void
+xf86SetEntityInstanceForScreen(ScrnInfoPtr pScrn, int entityIndex, int instance)
+{
+ int i;
+
+ if (entityIndex == -1 || entityIndex >= xf86NumEntities)
+ return;
+
+ for (i = 0; i < pScrn->numEntities; i++) {
+ if (pScrn->entityList[i] == entityIndex) {
+ pScrn->entityInstanceList[i] = instance;
+ break;
+ }
+ }
+}
+
+/*
+ * XXX This needs to be updated for the case where a single entity may have
+ * instances associated with more than one screen.
+ */
+ScrnInfoPtr
+xf86FindScreenForEntity(int entityIndex)
+{
+ int i,j;
+
+ if (entityIndex == -1) return NULL;
+
+ if (xf86Screens) {
+ for (i = 0; i < xf86NumScreens; i++) {
+ for (j = 0; j < xf86Screens[i]->numEntities; j++) {
+ if ( xf86Screens[i]->entityList[j] == entityIndex )
+ return (xf86Screens[i]);
+ }
+ }
+ }
+ return NULL;
+}
+
+void
+xf86RemoveEntityFromScreen(ScrnInfoPtr pScrn, int entityIndex)
+{
+ int i;
+ EntityAccessPtr *ptr = (EntityAccessPtr *)&pScrn->access;
+ EntityAccessPtr peacc;
+
+ for (i = 0; i < pScrn->numEntities; i++) {
+ if (pScrn->entityList[i] == entityIndex) {
+ peacc = xf86Entities[pScrn->entityList[i]]->access;
+ (*ptr) = peacc->next;
+ /* disable entity: call disable func */
+ if (peacc->pAccess && peacc->pAccess->AccessDisable)
+ peacc->pAccess->AccessDisable(peacc->pAccess->arg);
+ /* also disable fallback - just in case */
+ if (peacc->fallback && peacc->fallback->AccessDisable)
+ peacc->fallback->AccessDisable(peacc->fallback->arg);
+ for (i++; i < pScrn->numEntities; i++)
+ pScrn->entityList[i-1] = pScrn->entityList[i];
+ pScrn->numEntities--;
+ xf86Entities[entityIndex]->inUse = FALSE;
+ break;
+ }
+ ptr = &(xf86Entities[pScrn->entityList[i]]->access->next);
+ }
+}
+
+/*
+ * xf86ClearEntitiesForScreen() - called when a screen is deleted
+ * to mark it's entities unused. Called by xf86DeleteScreen().
+ */
+void
+xf86ClearEntityListForScreen(int scrnIndex)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ EntityAccessPtr peacc;
+ int i, entityIndex;
+
+ if (pScrn->entityList == NULL || pScrn->numEntities == 0) return;
+
+ for (i = 0; i < pScrn->numEntities; i++) {
+ entityIndex = pScrn->entityList[i];
+ xf86Entities[entityIndex]->inUse = FALSE;
+ /* disable resource: call the disable function */
+ peacc = xf86Entities[entityIndex]->access;
+ if (peacc->pAccess && peacc->pAccess->AccessDisable)
+ peacc->pAccess->AccessDisable(peacc->pAccess->arg);
+ /* and the fallback function */
+ if (peacc->fallback && peacc->fallback->AccessDisable)
+ peacc->fallback->AccessDisable(peacc->fallback->arg);
+ /* shared resources are only needed when entity is active: remove */
+ xf86DeallocateResourcesForEntity(entityIndex, ResShared);
+ }
+ xfree(pScrn->entityList);
+ xfree(pScrn->entityInstanceList);
+ if (pScrn->CurrentAccess->pIoAccess == (EntityAccessPtr)pScrn->access)
+ pScrn->CurrentAccess->pIoAccess = NULL;
+ if (pScrn->CurrentAccess->pMemAccess == (EntityAccessPtr)pScrn->access)
+ pScrn->CurrentAccess->pMemAccess = NULL;
+ pScrn->entityList = NULL;
+ pScrn->entityInstanceList = NULL;
+}
+
+void
+xf86DeallocateResourcesForEntity(int entityIndex, unsigned long type)
+{
+ resPtr *pprev_next = &Acc;
+ resPtr res = Acc;
+
+ while (res) {
+ if (res->entityIndex == entityIndex &&
+ (type & ResAccMask & res->res_type))
+ {
+ (*pprev_next) = res->next;
+ xfree(res);
+ } else
+ pprev_next = &(res->next);
+ res = (*pprev_next);
+ }
+}
+
+/*
+ * Add an extra device section (GDevPtr) to an entity.
+ */
+
+void
+xf86AddDevToEntity(int entityIndex, GDevPtr dev)
+{
+ EntityPtr pEnt;
+
+ if (entityIndex >= xf86NumEntities)
+ return;
+
+ pEnt = xf86Entities[entityIndex];
+ pEnt->numInstances++;
+ pEnt->devices = xnfrealloc(pEnt->devices,
+ pEnt->numInstances * sizeof(GDevPtr));
+ pEnt->devices[pEnt->numInstances - 1] = dev;
+ dev->claimed = TRUE;
+}
+
+/*
+ * xf86GetEntityInfo() -- This function hands information from the
+ * EntityRec struct to the drivers. The EntityRec structure itself
+ * remains invisible to the driver.
+ */
+EntityInfoPtr
+xf86GetEntityInfo(int entityIndex)
+{
+ EntityInfoPtr pEnt;
+ int i;
+
+ if (entityIndex >= xf86NumEntities)
+ return NULL;
+
+ pEnt = xnfcalloc(1,sizeof(EntityInfoRec));
+ pEnt->index = entityIndex;
+ pEnt->location = xf86Entities[entityIndex]->bus;
+ pEnt->active = xf86Entities[entityIndex]->active;
+ pEnt->chipset = xf86Entities[entityIndex]->chipset;
+ pEnt->resources = xf86Entities[entityIndex]->resources;
+ pEnt->driver = xf86Entities[entityIndex]->driver;
+ if ( (xf86Entities[entityIndex]->devices) &&
+ (xf86Entities[entityIndex]->devices[0]) ) {
+ for (i = 0; i < xf86Entities[entityIndex]->numInstances; i++)
+ if (xf86Entities[entityIndex]->devices[i]->screen == 0)
+ break;
+ pEnt->device = xf86Entities[entityIndex]->devices[i];
+ } else
+ pEnt->device = NULL;
+
+ return pEnt;
+}
+
+int
+xf86GetNumEntityInstances(int entityIndex)
+{
+ if (entityIndex >= xf86NumEntities)
+ return -1;
+
+ return xf86Entities[entityIndex]->numInstances;
+}
+
+GDevPtr
+xf86GetDevFromEntity(int entityIndex, int instance)
+{
+ int i;
+
+ /* We might not use AddDevtoEntity */
+ if ( (!xf86Entities[entityIndex]->devices) ||
+ (!xf86Entities[entityIndex]->devices[0]) )
+ return NULL;
+
+ if (entityIndex >= xf86NumEntities ||
+ instance >= xf86Entities[entityIndex]->numInstances)
+ return NULL;
+
+ for (i = 0; i < xf86Entities[entityIndex]->numInstances; i++)
+ if (xf86Entities[entityIndex]->devices[i]->screen == instance)
+ break;
+ return xf86Entities[entityIndex]->devices[i];
+}
+
+/*
+ * general generic disable function.
+ */
+static void
+disableAccess(void)
+{
+ int i;
+ xf86AccessPtr pacc;
+ EntityAccessPtr peacc;
+
+ /* call disable funcs and reset current access pointer */
+ /* the entity specific access funcs are in an enabled */
+ /* state - driver must restore their state explicitely */
+ for (i = 0; i < xf86NumScreens; i++) {
+ peacc = xf86Screens[i]->CurrentAccess->pIoAccess;
+ while (peacc) {
+ if (peacc->pAccess->AccessDisable)
+ peacc->pAccess->AccessDisable(peacc->pAccess->arg);
+ peacc = peacc->next;
+ }
+ xf86Screens[i]->CurrentAccess->pIoAccess = NULL;
+ peacc = xf86Screens[i]->CurrentAccess->pMemAccess;
+ while (peacc) {
+ if (peacc->pAccess->AccessDisable)
+ peacc->pAccess->AccessDisable(peacc->pAccess->arg);
+ peacc = peacc->next;
+ }
+ xf86Screens[i]->CurrentAccess->pMemAccess = NULL;
+ }
+ /* then call the generic entity disable funcs */
+ for (i = 0; i < xf86NumEntities; i++) {
+ pacc = xf86Entities[i]->access->fallback;
+ if (pacc->AccessDisable)
+ pacc->AccessDisable(pacc->arg);
+ }
+}
+
+static void
+clearAccess(void)
+{
+ int i;
+
+ /* call disable funcs and reset current access pointer */
+ /* the entity specific access funcs are in an enabled */
+ /* state - driver must restore their state explicitely */
+ for (i = 0; i < xf86NumScreens; i++) {
+ xf86Screens[i]->CurrentAccess->pIoAccess = NULL;
+ xf86Screens[i]->CurrentAccess->pMemAccess = NULL;
+ }
+
+}
+
+/*
+ * Generic interface to bus specific code - add other buses here
+ */
+
+/*
+ * xf86AccessInit() - set up everything needed for access control
+ * called only once on first server generation.
+ */
+void
+xf86AccessInit(void)
+{
+ initPciState();
+ initPciBusState();
+ DisablePciBusAccess();
+ DisablePciAccess();
+
+ xf86ResAccessEnter = TRUE;
+}
+
+/*
+ * xf86AccessEnter() -- gets called to save the text mode VGA IO
+ * resources when reentering the server after a VT switch.
+ */
+void
+xf86AccessEnter(void)
+{
+ if (xf86ResAccessEnter)
+ return;
+
+ /*
+ * on enter we simply disable routing of special resources
+ * to any bus and let the RAC code to "open" the right bridges.
+ */
+ PciBusStateEnter();
+ DisablePciBusAccess();
+ PciStateEnter();
+ disableAccess();
+ EntityEnter();
+ notifyStateChange(NOTIFY_ENTER);
+ xf86EnterServerState(SETUP);
+ xf86ResAccessEnter = TRUE;
+}
+
+/*
+ * xf86AccessLeave() -- prepares access for and calls the
+ * entityLeave() functions.
+ * xf86AccessLeaveState() --- gets called to restore the
+ * access to the VGA IO resources when switching VT or on
+ * server exit.
+ * This was split to call xf86AccessLeaveState() from
+ * ddxGiveUp().
+ */
+void
+xf86AccessLeave(void)
+{
+ if (!xf86ResAccessEnter)
+ return;
+ notifyStateChange(NOTIFY_LEAVE);
+ disableAccess();
+ DisablePciBusAccess();
+ EntityLeave();
+}
+
+void
+xf86AccessLeaveState(void)
+{
+ if (!xf86ResAccessEnter)
+ return;
+ xf86ResAccessEnter = FALSE;
+ PciStateLeave();
+ PciBusStateLeave();
+}
+
+/*
+ * xf86AccessRestoreState() - Restore the access registers to the
+ * state before X was started. This is handy for framebuffers.
+ */
+static void
+xf86AccessRestoreState(void)
+{
+ if (!xf86ResAccessEnter)
+ return;
+ PciStateLeave();
+ PciBusStateLeave();
+}
+
+/*
+ * xf86EnableAccess() -- enable access to controlled resources.
+ * To reduce latency when switching access the ScrnInfoRec has
+ * a linked list of the EntityAccPtr of all screen entities.
+ */
+/*
+ * switching access needs to be done in te following oder:
+ * disable
+ * 1. disable old entity
+ * 2. reroute bus
+ * 3. enable new entity
+ * Otherwise resources needed for access control might be shadowed
+ * by other resources!
+ */
+#ifdef async
+
+static AsyncQPtr *AsyncQ = NULL;
+ScrnInfoPtr xf86CurrentScreen = NULL;
+
+#define SETUP_Q org = AsyncQ; \
+ AsyncQ = &new;
+
+#define PROCESS_Q xf86CurrentScreen = pScrn;
+ if (!new) AsyncQ = org; \
+ else { \
+ AsyncQPtr tmp_Q; \
+ while (1) {\
+ new->func(new->arg);\
+ if (!(new->next)) {\
+ AsyncQ = org; xfree(new); break; \
+ } \
+ tmp_Q = new->next; \
+ xfree(new); \
+ new = tmp_Q; \
+ } \
+ }
+#else
+#define SETUP_Q
+#define PROCESS_Q
+#endif
+
+void
+xf86EnableAccess(ScrnInfoPtr pScrn)
+{
+ register EntityAccessPtr peAcc = (EntityAccessPtr) pScrn->access;
+ register EntityAccessPtr pceAcc;
+ register xf86AccessPtr pAcc;
+ EntityAccessPtr tmp;
+#ifdef async
+ AsyncQPtr *org, new = NULL;
+#endif
+
+#ifdef DEBUG
+ ErrorF("Enable access %i\n",pScrn->scrnIndex);
+#endif
+
+ /* Entity is not under access control or currently enabled */
+ if (!pScrn->access) {
+ if (pScrn->busAccess) {
+ SETUP_Q;
+ ((BusAccPtr)pScrn->busAccess)->set_f(pScrn->busAccess);
+ PROCESS_Q;
+ }
+ return;
+ }
+
+ switch (pScrn->resourceType) {
+ case IO:
+ pceAcc = pScrn->CurrentAccess->pIoAccess;
+ if (peAcc == pceAcc) {
+ return;
+ }
+ SETUP_Q;
+ if (pScrn->CurrentAccess->pMemAccess == pceAcc)
+ pScrn->CurrentAccess->pMemAccess = NULL;
+ while (pceAcc) {
+ pAcc = pceAcc->pAccess;
+ if ( pAcc && pAcc->AccessDisable)
+ (*pAcc->AccessDisable)(pAcc->arg);
+ pceAcc = pceAcc->next;
+ }
+ if (pScrn->busAccess)
+ ((BusAccPtr)pScrn->busAccess)->set_f(pScrn->busAccess);
+ while (peAcc) {
+ pAcc = peAcc->pAccess;
+ if (pAcc && pAcc->AccessEnable)
+ (*pAcc->AccessEnable)(pAcc->arg);
+ peAcc = peAcc->next;
+ }
+ pScrn->CurrentAccess->pIoAccess = (EntityAccessPtr) pScrn->access;
+ PROCESS_Q;
+ return;
+
+ case MEM_IO:
+ pceAcc = pScrn->CurrentAccess->pIoAccess;
+ if (peAcc != pceAcc) { /* current Io != pAccess */
+ SETUP_Q;
+ tmp = pceAcc;
+ while (pceAcc) {
+ pAcc = pceAcc->pAccess;
+ if (pAcc && pAcc->AccessDisable)
+ (*pAcc->AccessDisable)(pAcc->arg);
+ pceAcc = pceAcc->next;
+ }
+ pceAcc = pScrn->CurrentAccess->pMemAccess;
+ if (peAcc != pceAcc /* current Mem != pAccess */
+ && tmp !=pceAcc) {
+ while (pceAcc) {
+ pAcc = pceAcc->pAccess;
+ if (pAcc && pAcc->AccessDisable)
+ (*pAcc->AccessDisable)(pAcc->arg);
+ pceAcc = pceAcc->next;
+ }
+ }
+ } else { /* current Io == pAccess */
+ pceAcc = pScrn->CurrentAccess->pMemAccess;
+ if (pceAcc == peAcc) { /* current Mem == pAccess */
+ return;
+ }
+ SETUP_Q;
+ while (pceAcc) { /* current Mem != pAccess */
+ pAcc = pceAcc->pAccess;
+ if (pAcc && pAcc->AccessDisable)
+ (*pAcc->AccessDisable)(pAcc->arg);
+ pceAcc = pceAcc->next;
+ }
+ }
+ if (pScrn->busAccess)
+ ((BusAccPtr)pScrn->busAccess)->set_f(pScrn->busAccess);
+ while (peAcc) {
+ pAcc = peAcc->pAccess;
+ if (pAcc && pAcc->AccessEnable)
+ (*pAcc->AccessEnable)(pAcc->arg);
+ peAcc = peAcc->next;
+ }
+ pScrn->CurrentAccess->pMemAccess =
+ pScrn->CurrentAccess->pIoAccess = (EntityAccessPtr) pScrn->access;
+ PROCESS_Q;
+ return;
+
+ case MEM:
+ pceAcc = pScrn->CurrentAccess->pMemAccess;
+ if (peAcc == pceAcc) {
+ return;
+ }
+ SETUP_Q;
+ if (pScrn->CurrentAccess->pIoAccess == pceAcc)
+ pScrn->CurrentAccess->pIoAccess = NULL;
+ while (pceAcc) {
+ pAcc = pceAcc->pAccess;
+ if ( pAcc && pAcc->AccessDisable)
+ (*pAcc->AccessDisable)(pAcc->arg);
+ pceAcc = pceAcc->next;
+ }
+ if (pScrn->busAccess)
+ ((BusAccPtr)pScrn->busAccess)->set_f(pScrn->busAccess);
+ while (peAcc) {
+ pAcc = peAcc->pAccess;
+ if (pAcc && pAcc->AccessEnable)
+ (*pAcc->AccessEnable)(pAcc->arg);
+ peAcc = peAcc->next;
+ }
+ pScrn->CurrentAccess->pMemAccess = (EntityAccessPtr) pScrn->access;
+ PROCESS_Q;
+ return;
+
+ case NONE:
+ if (pScrn->busAccess) {
+ SETUP_Q;
+ ((BusAccPtr)pScrn->busAccess)->set_f(pScrn->busAccess);
+ PROCESS_Q;
+ }
+ return;
+ }
+}
+
+void
+xf86SetCurrentAccess(Bool Enable, ScrnInfoPtr pScrn)
+{
+ EntityAccessPtr pceAcc2 = NULL;
+ register EntityAccessPtr pceAcc = NULL;
+ register xf86AccessPtr pAcc;
+
+
+ switch(pScrn->resourceType) {
+ case IO:
+ pceAcc = pScrn->CurrentAccess->pIoAccess;
+ break;
+ case MEM:
+ pceAcc = pScrn->CurrentAccess->pMemAccess;
+ break;
+ case MEM_IO:
+ pceAcc = pScrn->CurrentAccess->pMemAccess;
+ pceAcc2 = pScrn->CurrentAccess->pIoAccess;
+ break;
+ default:
+ break;
+ }
+
+ while (pceAcc) {
+ pAcc = pceAcc->pAccess;
+ if ( pAcc) {
+ if (!Enable) {
+ if (pAcc->AccessDisable)
+ (*pAcc->AccessDisable)(pAcc->arg);
+ } else {
+ if (pAcc->AccessEnable)
+ (*pAcc->AccessEnable)(pAcc->arg);
+ }
+ }
+ pceAcc = pceAcc->next;
+ if (!pceAcc) {
+ pceAcc = pceAcc2;
+ pceAcc2 = NULL;
+ }
+ }
+}
+
+void
+xf86SetAccessFuncs(EntityInfoPtr pEnt, xf86SetAccessFuncPtr funcs,
+ xf86SetAccessFuncPtr oldFuncs)
+{
+ AccessFuncPtr rac;
+
+ if (!xf86Entities[pEnt->index]->rac)
+ xf86Entities[pEnt->index]->rac = xnfcalloc(1,sizeof(AccessFuncRec));
+
+ rac = xf86Entities[pEnt->index]->rac;
+
+ if (funcs->mem == funcs->io_mem && funcs->mem && funcs->io)
+ xf86Entities[pEnt->index]->entityProp |= NO_SEPARATE_MEM_FROM_IO;
+ if (funcs->io == funcs->io_mem && funcs->mem && funcs->io)
+ xf86Entities[pEnt->index]->entityProp |= NO_SEPARATE_IO_FROM_MEM;
+
+ rac->mem_new = funcs->mem;
+ rac->io_new = funcs->io;
+ rac->io_mem_new = funcs->io_mem;
+
+ rac->old = oldFuncs;
+}
+
+/*
+ * Conflict checking
+ */
+
+static memType
+getMask(memType val)
+{
+ memType mask = 0;
+ memType tmp = 0;
+
+ mask=~mask;
+ tmp = ~((~tmp) >> 1);
+
+ while (!(val & tmp)) {
+ mask = mask >> 1;
+ val = val << 1;
+ }
+ return mask;
+}
+
+/*
+ * checkConflictBlock() -- check for conflicts of a block resource range.
+ * If conflict is found return end of conflicting range. Else return 0.
+ */
+static memType
+checkConflictBlock(resRange *range, resPtr pRes)
+{
+ memType val,tmp,prev;
+ int i;
+
+ switch (pRes->res_type & ResExtMask) {
+ case ResBlock:
+ if (range->rBegin < pRes->block_end &&
+ range->rEnd > pRes->block_begin) {
+#ifdef DEBUG
+ ErrorF("b-b conflict w: %lx %lx\n",
+ pRes->block_begin,pRes->block_end);
+#endif
+ return pRes->block_end < range->rEnd ?
+ pRes->block_end : range->rEnd;
+ }
+ return 0;
+ case ResSparse:
+ if (pRes->sparse_base > range->rEnd) return 0;
+
+ val = (~pRes->sparse_mask | pRes->sparse_base) & getMask(range->rEnd);
+#ifdef DEBUG
+ ErrorF("base = 0x%lx, mask = 0x%lx, begin = 0x%lx, end = 0x%lx ,"
+ "val = 0x%lx\n",
+ pRes->sparse_base, pRes->sparse_mask, range->rBegin,
+ range->rEnd, val);
+#endif
+ i = sizeof(memType) * 8;
+ tmp = prev = pRes->sparse_base;
+
+ while (i) {
+ tmp |= 1<< (--i) & val;
+ if (tmp > range->rEnd)
+ tmp = prev;
+ else
+ prev = tmp;
+ }
+ if (tmp >= range->rBegin) {
+#ifdef DEBUG
+ ErrorF("conflict found at: 0x%lx\n",tmp);
+ ErrorF("b-d conflict w: %lx %lx\n",
+ pRes->sparse_base,pRes->sparse_mask);
+#endif
+ return tmp;
+ }
+ else
+ return 0;
+ }
+ return 0;
+}
+
+/*
+ * checkConflictSparse() -- check for conflicts of a sparse resource range.
+ * If conflict is found return base of conflicting region. Else return 0.
+ */
+#define mt_max ~(memType)0
+#define length sizeof(memType) * 8
+static memType
+checkConflictSparse(resRange *range, resPtr pRes)
+{
+ memType val, tmp, prev;
+ int i;
+
+ switch (pRes->res_type & ResExtMask) {
+ case ResSparse:
+ tmp = pRes->sparse_mask & range->rMask;
+ if ((tmp & pRes->sparse_base) == (tmp & range->rBase)) {
+#ifdef DEBUG
+ ErrorF("s-b conflict w: %lx %lx\n",
+ pRes->sparse_base,pRes->sparse_mask);
+#endif
+ return pRes->sparse_mask;
+ }
+ return 0;
+
+ case ResBlock:
+ if (pRes->block_end < range->rBase) return 0;
+
+ val = (~range->rMask | range->rBase) & getMask(pRes->block_end);
+ i = length;
+ tmp = prev = range->rBase;
+
+ while (i) {
+#ifdef DEBUG
+ ErrorF("tmp = 0x%lx\n",tmp);
+#endif
+ tmp |= 1<< (--i) & val;
+ if (tmp > pRes->block_end)
+ tmp = prev;
+ else
+ prev = tmp;
+ }
+ if (tmp < pRes->block_begin)
+ return 0;
+ else {
+ /*
+ * now we subdivide the block region in sparse regions
+ * with base values = 2^n and find the smallest mask.
+ * This might be done in a simpler way....
+ */
+ memType mask, m_mask = 0, base = pRes->block_begin;
+ int i;
+ while (base < pRes->block_end) {
+ for (i = 1; i < length; i++)
+ if ( base != (base & (mt_max << i))) break;
+ mask = mt_max >> (length - i);
+ do mask >>= 1;
+ while ((mask + base + 1) > pRes->block_end);
+ /* m_mask and are _inverted_ sparse masks */
+ m_mask = mask > m_mask ? mask : m_mask;
+ base = base + mask + 1;
+ }
+#ifdef DEBUG
+ ErrorF("conflict found at: 0x%lx\n",tmp);
+ ErrorF("b-b conflict w: %lx %lx\n",
+ pRes->block_begin,pRes->block_end);
+#endif
+ return ~m_mask;
+ }
+ }
+ return 0;
+}
+#undef mt_max
+#undef length
+
+/*
+ * needCheck() -- this function decides whether to check for conflicts
+ * depending on the types of the resource ranges and their locations
+ */
+static Bool
+needCheck(resPtr pRes, unsigned long type, int entityIndex, xf86State state)
+{
+ /* the same entity shouldn't conflict with itself */
+ ScrnInfoPtr pScrn;
+ int i;
+ BusType loc = BUS_NONE;
+ BusType r_loc = BUS_NONE;
+
+ /* Ignore overlapped ranges that have been nullified */
+ if ((pRes->res_type & ResOverlap) && (pRes->block_begin > pRes->block_end))
+ return FALSE;
+
+ if ((pRes->res_type & ResTypeMask) != (type & ResTypeMask))
+ return FALSE;
+
+ /*
+ * Resources set by BIOS (ResBios) are allowed to conflict
+ * with resources marked (ResBios).
+ */
+ if (pRes->res_type & type & ResBios)
+ return FALSE;
+
+ /*If requested, skip over estimated resources */
+ if (pRes->res_type & type & ResEstimated)
+ return FALSE;
+
+ if (type & pRes->res_type & ResUnused)
+ return FALSE;
+
+ if (state == OPERATING) {
+ if (type & ResDisableOpr || pRes->res_type & ResDisableOpr)
+ return FALSE;
+ if (type & pRes->res_type & ResUnusedOpr) return FALSE;
+ /*
+ * Maybe we should have ResUnused set The resUnusedOpr
+ * bit, too. This way we could avoid this confusion
+ */
+ if ((type & ResUnusedOpr && pRes->res_type & ResUnused) ||
+ (type & ResUnused && pRes->res_type & ResUnusedOpr))
+ return FALSE;
+ }
+
+ if (entityIndex > -1)
+ loc = xf86Entities[entityIndex]->busType;
+ if (pRes->entityIndex > -1)
+ r_loc = xf86Entities[pRes->entityIndex]->busType;
+
+ switch (type & ResAccMask) {
+ case ResExclusive:
+ switch (pRes->res_type & ResAccMask) {
+ case ResExclusive:
+ break;
+ case ResShared:
+ /* ISA buses are only locally exclusive on a PCI system */
+ if (loc == BUS_ISA && r_loc == BUS_PCI)
+ return FALSE;
+ break;
+ }
+ break;
+ case ResShared:
+ switch (pRes->res_type & ResAccMask) {
+ case ResExclusive:
+ /* ISA buses are only locally exclusive on a PCI system */
+ if (loc == BUS_PCI && r_loc == BUS_ISA)
+ return FALSE;
+ break;
+ case ResShared:
+ return FALSE;
+ }
+ break;
+ case ResAny:
+ break;
+ }
+
+ if (pRes->entityIndex == entityIndex) return FALSE;
+
+ if (pRes->entityIndex > -1 &&
+ (pScrn = xf86FindScreenForEntity(entityIndex))) {
+ for (i = 0; i < pScrn->numEntities; i++)
+ if (pScrn->entityList[i] == pRes->entityIndex) return FALSE;
+ }
+ return TRUE;
+}
+
+/*
+ * checkConflict() - main conflict checking function which all other
+ * function call.
+ */
+static memType
+checkConflict(resRange *rgp, resPtr pRes, int entityIndex,
+ xf86State state, Bool ignoreIdentical)
+{
+ memType ret;
+
+ while(pRes) {
+ if (!needCheck(pRes,rgp->type, entityIndex ,state)) {
+ pRes = pRes->next;
+ continue;
+ }
+ switch (rgp->type & ResExtMask) {
+ case ResBlock:
+ if (rgp->rEnd < rgp->rBegin) {
+ xf86Msg(X_ERROR,"end of block range 0x%lx < begin 0x%lx\n",
+ rgp->rEnd,rgp->rBegin);
+ return 0;
+ }
+ if ((ret = checkConflictBlock(rgp, pRes))) {
+ if (!ignoreIdentical || (rgp->rBegin != pRes->block_begin)
+ || (rgp->rEnd != pRes->block_end))
+ return ret;
+ }
+ break;
+ case ResSparse:
+ if ((rgp->rBase & rgp->rMask) != rgp->rBase) {
+ xf86Msg(X_ERROR,"sparse io range (base: 0x%lx mask: 0x%lx)"
+ "doesn't satisfy (base & mask = mask)\n",
+ rgp->rBase, rgp->rMask);
+ return 0;
+ }
+ if ((ret = checkConflictSparse(rgp, pRes))) {
+ if (!ignoreIdentical || (rgp->rBase != pRes->sparse_base)
+ || (rgp->rMask != pRes->sparse_mask))
+ return ret;
+ }
+ break;
+ }
+ pRes = pRes->next;
+ }
+ return 0;
+}
+
+/*
+ * ChkConflict() -- used within xxxBus ; find conflict with any location.
+ */
+memType
+ChkConflict(resRange *rgp, resPtr res, xf86State state)
+{
+ return checkConflict(rgp, res, -2, state,FALSE);
+}
+
+/*
+ * xf86ChkConflict() - This function is the low level interface to
+ * the resource broker that gets exported. Tests all resources ie.
+ * performs test with SETUP flag.
+ */
+memType
+xf86ChkConflict(resRange *rgp, int entityIndex)
+{
+ return checkConflict(rgp, Acc, entityIndex, SETUP,FALSE);
+}
+
+/*
+ * Resources List handling
+ */
+
+resPtr
+xf86JoinResLists(resPtr rlist1, resPtr rlist2)
+{
+ resPtr pRes;
+
+ if (!rlist1)
+ return rlist2;
+
+ if (!rlist2)
+ return rlist1;
+
+ for (pRes = rlist1; pRes->next; pRes = pRes->next)
+ ;
+ pRes->next = rlist2;
+ return rlist1;
+}
+
+resPtr
+xf86AddResToList(resPtr rlist, resRange *range, int entityIndex)
+{
+ resPtr new;
+
+ switch (range->type & ResExtMask) {
+ case ResBlock:
+ if (range->rEnd < range->rBegin) {
+ xf86Msg(X_ERROR,"end of block range 0x%lx < begin 0x%lx\n",
+ range->rEnd,range->rBegin);
+ return rlist;
+ }
+ break;
+ case ResSparse:
+ if ((range->rBase & range->rMask) != range->rBase) {
+ xf86Msg(X_ERROR,"sparse io range (base: 0x%lx mask: 0x%lx)"
+ "doesn't satisfy (base & mask = mask)\n",
+ range->rBase, range->rMask);
+ return rlist;
+ }
+ break;
+ }
+
+ new = xnfalloc(sizeof(resRec));
+ /*
+ * Only background resources may be registered with ResBios
+ * and ResEstimated set. Other resources only set it for
+ * testing.
+ */
+ if (entityIndex != (-1))
+ range->type &= ~(ResBios | ResEstimated);
+ new->val = *range;
+ new->entityIndex = entityIndex;
+ new->next = rlist;
+ return new;
+}
+
+void
+xf86FreeResList(resPtr rlist)
+{
+ resPtr pRes;
+
+ if (!rlist)
+ return;
+
+ for (pRes = rlist->next; pRes; rlist = pRes, pRes = pRes->next)
+ xfree(rlist);
+ xfree(rlist);
+}
+
+resPtr
+xf86DupResList(const resPtr rlist)
+{
+ resPtr pRes, ret, prev, new;
+
+ if (!rlist)
+ return NULL;
+
+ ret = xnfalloc(sizeof(resRec));
+ *ret = *rlist;
+ prev = ret;
+ for (pRes = rlist->next; pRes; pRes = pRes->next) {
+ new = xnfalloc(sizeof(resRec));
+ *new = *pRes;
+ prev->next = new;
+ prev = new;
+ }
+ return ret;
+}
+
+void
+xf86PrintResList(int verb, resPtr list)
+{
+ int i = 0;
+ const char *s, *r;
+ resPtr tmp = list;
+ unsigned long type;
+
+ if (!list)
+ return;
+
+ type = ResMem;
+ r = "M";
+ while (1) {
+ while (list) {
+ if ((list->res_type & ResPhysMask) == type) {
+ switch (list->res_type & ResExtMask) {
+ case ResBlock:
+ xf86ErrorFVerb(verb,
+ "\t[%d] %d\t%d\t0x%08lx - 0x%08lx (0x%lx)",
+ i, list->entityIndex,
+ (list->res_type & ResDomain) >> 24,
+ list->block_begin, list->block_end,
+ list->block_end - list->block_begin + 1);
+ break;
+ case ResSparse:
+ xf86ErrorFVerb(verb, "\t[%d] %d\t%d\t0x%08lx - 0x%08lx ",
+ i, list->entityIndex,
+ (list->res_type & ResDomain) >> 24,
+ list->sparse_base,list->sparse_mask);
+ break;
+ default:
+ list = list->next;
+ continue;
+ }
+ xf86ErrorFVerb(verb, " %s", r);
+ switch (list->res_type & ResAccMask) {
+ case ResExclusive:
+ if (list->res_type & ResUnused)
+ s = "x";
+ else
+ s = "X";
+ break;
+ case ResShared:
+ if (list->res_type & ResUnused)
+ s = "s";
+ else
+ s = "S";
+ break;
+ default:
+ s = "?";
+ }
+ xf86ErrorFVerb(verb, "%s", s);
+ switch (list->res_type & ResExtMask) {
+ case ResBlock:
+ s = "[B]";
+ break;
+ case ResSparse:
+ s = "[S]";
+ break;
+ default:
+ s = "[?]";
+ }
+ xf86ErrorFVerb(verb, "%s", s);
+ if (list->res_type & ResEstimated)
+ xf86ErrorFVerb(verb, "E");
+ if (list->res_type & ResOverlap)
+ xf86ErrorFVerb(verb, "O");
+ if (list->res_type & ResInit)
+ xf86ErrorFVerb(verb, "t");
+ if (list->res_type & ResBios)
+ xf86ErrorFVerb(verb, "(B)");
+ if (list->res_type & ResBus)
+ xf86ErrorFVerb(verb, "(b)");
+ if (list->res_type & ResOprMask) {
+ switch (list->res_type & ResOprMask) {
+ case ResUnusedOpr:
+ s = "(OprU)";
+ break;
+ case ResDisableOpr:
+ s = "(OprD)";
+ break;
+ default:
+ s = "(Opr?)";
+ break;
+ }
+ xf86ErrorFVerb(verb, "%s", s);
+ }
+ xf86ErrorFVerb(verb, "\n");
+ i++;
+ }
+ list = list->next;
+ }
+ if (type == ResIo) break;
+ type = ResIo;
+ r = "I";
+ list = tmp;
+ }
+}
+
+resPtr
+xf86AddRangesToList(resPtr list, resRange *pRange, int entityIndex)
+{
+ while(pRange && pRange->type != ResEnd) {
+ list = xf86AddResToList(list,pRange,entityIndex);
+ pRange++;
+ }
+ return list;
+}
+
+void
+xf86ResourceBrokerInit(void)
+{
+ resPtr resPci;
+
+ osRes = NULL;
+
+ /* Get the addressable ranges */
+ ResRange = xf86BusAccWindowsFromOS();
+ xf86MsgVerb(X_INFO, 3, "Addressable bus resource ranges are\n");
+ xf86PrintResList(3, ResRange);
+
+ /* Get the ranges used exclusively by the system */
+ osRes = xf86AccResFromOS(osRes);
+ xf86MsgVerb(X_INFO, 3, "OS-reported resource ranges:\n");
+ xf86PrintResList(3, osRes);
+
+ /* Bus dep initialization */
+ resPci = ResourceBrokerInitPci(&osRes);
+ Acc = xf86JoinResLists(xf86DupResList(osRes), resPci);
+
+ xf86MsgVerb(X_INFO, 3, "All system resource ranges:\n");
+ xf86PrintResList(3, Acc);
+
+}
+
+#define MEM_ALIGN (1024 * 1024)
+
+/*
+ * RemoveOverlaps() -- remove overlaps between resources of the
+ * same kind.
+ * Beware: This function doesn't check for access attributes.
+ * At resource broker initialization this is no problem as this
+ * only deals with exclusive resources.
+ */
+void
+RemoveOverlaps(resPtr target, resPtr list, Bool pow2Alignment, Bool useEstimated)
+{
+ resPtr pRes;
+ memType size, newsize, adjust;
+
+ for (pRes = list; pRes; pRes = pRes->next) {
+ if (pRes != target
+ && ((pRes->res_type & ResTypeMask) ==
+ (target->res_type & ResTypeMask))
+ && pRes->block_begin <= target->block_end
+ && pRes->block_end >= target->block_begin) {
+ /* Possibly ignore estimated resources */
+ if (!useEstimated && (pRes->res_type & ResEstimated)) continue;
+ /*
+ * Target should be a larger region than pRes. If pRes fully
+ * contains target, don't do anything unless target can overlap.
+ */
+ if (pRes->block_begin <= target->block_begin &&
+ pRes->block_end >= target->block_end) {
+ if (target->res_type & ResOverlap) {
+ /* Nullify range but keep its ResOverlap bit on */
+ target->block_end = target->block_begin - 1;
+ return;
+ }
+ continue;
+ }
+ /*
+ * In cases where the target and pRes have the same starting
+ * address, reduce the size of the target (given it's an estimate).
+ */
+ if (pRes->block_begin == target->block_begin) {
+ if (target->res_type & ResOverlap)
+ target->block_end = target->block_begin - 1;
+ else
+ target->block_end = pRes->block_end;
+ }
+ /* Otherwise, trim target to remove the overlap */
+ else if (pRes->block_begin <= target->block_end) {
+ target->block_end = pRes->block_begin - 1;
+ } else if (!pow2Alignment &&
+ pRes->block_end >= target->block_begin) {
+ target->block_begin = pRes->block_end + 1;
+ }
+ if (pow2Alignment) {
+ /*
+ * Align to a power of two. This requires finding the
+ * largest power of two that is smaller than the adjusted
+ * size.
+ */
+ size = target->block_end - target->block_begin + 1;
+ newsize = 1UL << (sizeof(memType) * 8 - 1);
+ while (!(newsize & size))
+ newsize >>= 1;
+ target->block_end = target->block_begin + newsize - 1;
+ } else if (target->block_end > MEM_ALIGN) {
+ /* Align the end to MEM_ALIGN */
+ if ((adjust = (target->block_end + 1) % MEM_ALIGN))
+ target->block_end -= adjust;
+ }
+ }
+ }
+}
+
+/*
+ * Resource request code
+ */
+
+#define ALIGN(x,a) ((x) + a) &~(a)
+
+resRange
+xf86GetBlock(unsigned long type, memType size,
+ memType window_start, memType window_end,
+ memType align_mask, resPtr avoid)
+{
+ memType min, max, tmp;
+ resRange r = {ResEnd,0,0};
+ resPtr res_range = ResRange;
+
+ if (!size) return r;
+ if (window_end < window_start || (window_end - window_start) < (size - 1)) {
+ ErrorF("Requesting insufficient memory window!:"
+ " start: 0x%lx end: 0x%lx size 0x%lx\n",
+ window_start,window_end,size);
+ return r;
+ }
+ type = (type & ~(ResExtMask | ResBios | ResEstimated)) | ResBlock;
+
+ while (res_range) {
+ if ((type & ResTypeMask) == (res_range->res_type & ResTypeMask)) {
+ if (res_range->block_begin > window_start)
+ min = res_range->block_begin;
+ else
+ min = window_start;
+ if (res_range->block_end < window_end)
+ max = res_range->block_end;
+ else
+ max = window_end;
+ min = ALIGN(min,align_mask);
+ /* do not produce an overflow! */
+ while (min < max && (max - min) >= (size - 1)) {
+ RANGE(r,min,min + size - 1,type);
+ tmp = ChkConflict(&r,Acc,SETUP);
+ if (!tmp) {
+ tmp = ChkConflict(&r,avoid,SETUP);
+ if (!tmp) {
+ return r;
+ }
+ }
+ min = ALIGN(tmp,align_mask);
+ }
+ }
+ res_range = res_range->next;
+ }
+ RANGE(r,0,0,ResEnd);
+ return r;
+}
+
+#define mt_max ~(memType)0
+#define length sizeof(memType) * 8
+/*
+ * make_base() -- assign the lowest bits to the bits set in mask.
+ * example: mask 011010 val 0000110 -> 011000
+ */
+static memType
+make_base(memType val, memType mask)
+{
+ int i,j = 0;
+ memType ret = 0
+ ;
+ for (i = 0;i<length;i++) {
+ if ((1 << i) & mask) {
+ ret |= (((val >> j) & 1) << i);
+ j++;
+ }
+ }
+ return ret;
+}
+
+/*
+ * make_base() -- assign the bits set in mask to the lowest bits.
+ * example: mask 011010 , val 010010 -> 000011
+ */
+static memType
+unmake_base(memType val, memType mask)
+{
+ int i,j = 0;
+ memType ret = 0;
+
+ for (i = 0;i<length;i++) {
+ if ((1 << i) & mask) {
+ ret |= (((val >> i) & 1) << j);
+ j++;
+ }
+ }
+ return ret;
+}
+
+static memType
+fix_counter(memType val, memType old_mask, memType mask)
+{
+ mask = old_mask & mask;
+
+ val = make_base(val,old_mask);
+ return unmake_base(val,mask);
+}
+
+resRange
+xf86GetSparse(unsigned long type, memType fixed_bits,
+ memType decode_mask, memType address_mask, resPtr avoid)
+{
+ resRange r = {ResEnd,0,0};
+ memType new_mask;
+ memType mask1;
+ memType base;
+ memType bits;
+ memType counter = 0;
+ memType counter1;
+ memType max_counter = ~(memType)0;
+ memType max_counter1;
+ memType conflict = 0;
+
+ /* for sanity */
+ type = (type & ~(ResExtMask | ResBios | ResEstimated)) | ResSparse;
+
+ /*
+ * a sparse address consists of 3 parts:
+ * fixed_bits: F bits which hard decoded by the hardware
+ * decode_bits: D bits which are used to decode address
+ * but which may be set by software
+ * address_bits: A bits which are used to address the
+ * sparse range.
+ * the decode_mask marks all decode bits while the address_mask
+ * masks out all address_bits:
+ * F D A
+ * decode_mask: 0 1 0
+ * address_mask: 1 1 0
+ */
+ decode_mask &= address_mask;
+ new_mask = decode_mask;
+
+ /*
+ * We start by setting the decode_mask bits to different values
+ * when a conflict is found the address_mask of the conflicting
+ * resource is returned. We remove those bits from decode_mask
+ * that are also set in the returned address_mask as they always
+ * conflict with resources which use them as address masks.
+ * The resoulting mask is stored in new_mask.
+ * We continue until no conflict is found or until we have
+ * tried all possible settings of new_mask.
+ */
+ while (1) {
+ base = make_base(counter,new_mask) | fixed_bits;
+ RANGE(r,base,address_mask,type);
+ conflict = ChkConflict(&r,Acc,SETUP);
+ if (!conflict) {
+ conflict = ChkConflict(&r,avoid,SETUP);
+ if (!conflict) {
+ return r;
+ }
+ }
+ counter = fix_counter(counter,new_mask,conflict);
+ max_counter = fix_counter(max_counter,new_mask,conflict);
+ new_mask &= conflict;
+ counter ++;
+ if (counter > max_counter) break;
+ }
+ if (!new_mask && (new_mask == decode_mask)) {
+ RANGE(r,0,0,ResEnd);
+ return r;
+ }
+ /*
+ * if we haven't been successful we also try to modify those
+ * bits in decode_mask that are not at the same time set in
+ * new mask. These bits overlap with address_bits of some
+ * resources. If a conflict with a resource of this kind is
+ * found (ie. returned_mask & mask1 != mask1) with
+ * mask1 = decode_mask & ~new_mask we cannot
+ * use our choice of bits in the new_mask part. We try
+ * another choice.
+ */
+ max_counter = fix_counter(mt_max,mt_max,new_mask);
+ mask1 = decode_mask & ~new_mask;
+ max_counter1 = fix_counter(mt_max,mt_max,mask1);
+ counter = 0;
+
+ while (1) {
+ bits = make_base(counter,new_mask) | fixed_bits;
+ counter1 = 0;
+ while (1) {
+ base = make_base(counter1,mask1);
+ RANGE(r,base,address_mask,type);
+ conflict = ChkConflict(&r,Acc,SETUP);
+ if (!conflict) {
+ conflict = ChkConflict(&r,avoid,SETUP);
+ if (!conflict) {
+ return r;
+ }
+ }
+ counter1 ++;
+ if ((mask1 & conflict) != mask1 || counter1 > max_counter1)
+ break;
+ }
+ counter ++;
+ if (counter > max_counter) break;
+ }
+ RANGE(r,0,0,ResEnd);
+ return r;
+}
+
+#undef length
+#undef mt_max
+
+/*
+ * Resource registrarion
+ */
+
+static resList
+xf86GetResourcesImplicitly(int entityIndex)
+{
+ if (entityIndex >= xf86NumEntities) return NULL;
+
+ switch (xf86Entities[entityIndex]->bus.type) {
+ case BUS_ISA:
+ case BUS_NONE:
+ case BUS_SBUS:
+ return NULL;
+ case BUS_PCI:
+ return GetImplicitPciResources(entityIndex);
+ case BUS_last:
+ return NULL;
+ }
+ return NULL;
+}
+
+static void
+convertRange2Host(int entityIndex, resRange *pRange)
+{
+ if (pRange->type & ResBus) {
+ switch (xf86Entities[entityIndex]->busType) {
+ case BUS_PCI:
+ pciConvertRange2Host(entityIndex,pRange);
+ break;
+ case BUS_ISA:
+ isaConvertRange2Host(pRange);
+ break;
+ default:
+ break;
+ }
+
+ pRange->type &= ~ResBus;
+ }
+}
+
+/*
+ * xf86RegisterResources() -- attempts to register listed resources.
+ * If list is NULL it tries to obtain resources implicitly. Function
+ * returns a resPtr listing all resources not successfully registered.
+ */
+
+resPtr
+xf86RegisterResources(int entityIndex, resList list, unsigned long access)
+{
+ resPtr res = NULL;
+ resRange range;
+ resList list_f = NULL;
+
+ if (!list) {
+ list = xf86GetResourcesImplicitly(entityIndex);
+ /* these resources have to be in host address space already */
+ if (!list) return NULL;
+ list_f = list;
+ }
+
+ while(list->type != ResEnd) {
+ range = *list;
+
+ convertRange2Host(entityIndex,&range);
+
+ if ((access != ResNone) && (access & ResAccMask)) {
+ range.type = (range.type & ~ResAccMask) | (access & ResAccMask);
+ }
+ range.type &= ~ResEstimated; /* Not allowed for drivers */
+#if !(defined(__alpha__) && defined(linux))
+ /* On Alpha Linux, do not check for conflicts, trust the kernel. */
+ if (checkConflict(&range, Acc, entityIndex, SETUP,TRUE))
+ res = xf86AddResToList(res,&range,entityIndex);
+ else
+#endif
+ {
+ Acc = xf86AddResToList(Acc,&range,entityIndex);
+ }
+ list++;
+ }
+ if (list_f)
+ xfree(list_f);
+
+#ifdef DEBUG
+ xf86MsgVerb(X_INFO, 3,"Resources after driver initialization\n");
+ xf86PrintResList(3, Acc);
+ if (res) xf86MsgVerb(X_INFO, 3,
+ "Failed Resources after driver initialization "
+ "for Entity: %i\n",entityIndex);
+ xf86PrintResList(3, res);
+#endif
+ return res;
+
+}
+
+static void
+busTypeSpecific(EntityPtr pEnt, xf86State state, xf86AccessPtr *acc_mem,
+ xf86AccessPtr *acc_io, xf86AccessPtr *acc_mem_io)
+{
+ pciAccPtr *ppaccp;
+
+ switch (pEnt->bus.type) {
+ case BUS_ISA:
+ case BUS_SBUS:
+ *acc_mem = *acc_io = *acc_mem_io = &AccessNULL;
+ break;
+ break;
+ case BUS_PCI:
+ ppaccp = xf86PciAccInfo;
+ while (*ppaccp) {
+ if ((*ppaccp)->busnum == pEnt->pciBusId.bus
+ && (*ppaccp)->devnum == pEnt->pciBusId.device
+ && (*ppaccp)->funcnum == pEnt->pciBusId.func) {
+ *acc_io = &(*ppaccp)->ioAccess;
+ *acc_mem = &(*ppaccp)->memAccess;
+ *acc_mem_io = &(*ppaccp)->io_memAccess;
+ break;
+ }
+ ppaccp++;
+ }
+ break;
+ default:
+ *acc_mem = *acc_io = *acc_mem_io = NULL;
+ break;
+ }
+ return;
+}
+
+static void
+setAccess(EntityPtr pEnt, xf86State state)
+{
+
+ xf86AccessPtr acc_mem, acc_io, acc_mem_io;
+ xf86AccessPtr org_mem = NULL, org_io = NULL, org_mem_io = NULL;
+ int prop;
+
+ busTypeSpecific(pEnt,state,&acc_mem,&acc_io,&acc_mem_io);
+
+ /* The replacement function needs to handle _all_ shared resources */
+ /* unless they are handeled locally and disabled otherwise */
+ if (pEnt->rac) {
+ if (pEnt->rac->io_new) {
+ org_io = acc_io;
+ acc_io = pEnt->rac->io_new;
+ }
+ if (pEnt->rac->mem_new) {
+ org_mem = acc_mem;
+ acc_mem = pEnt->rac->mem_new;
+ }
+ if (pEnt->rac->io_mem_new) {
+ org_mem_io = acc_mem_io;
+ acc_mem_io = pEnt->rac->io_mem_new;
+ }
+ }
+
+ if (state == OPERATING) {
+ prop = pEnt->entityProp;
+ switch(pEnt->entityProp & NEED_SHARED) {
+ case NEED_SHARED:
+ pEnt->access->rt = MEM_IO;
+ break;
+ case NEED_IO_SHARED:
+ pEnt->access->rt = IO;
+ break;
+ case NEED_MEM_SHARED:
+ pEnt->access->rt = MEM;
+ break;
+ default:
+ pEnt->access->rt = NONE;
+ }
+ } else {
+ prop = NEED_SHARED | NEED_MEM | NEED_IO;
+ pEnt->access->rt = MEM_IO;
+ }
+
+ switch(pEnt->access->rt) {
+ case IO:
+ pEnt->access->pAccess = acc_io;
+ break;
+ case MEM:
+ pEnt->access->pAccess = acc_mem;
+ break;
+ case MEM_IO:
+ pEnt->access->pAccess = acc_mem_io;
+ break;
+ default: /* no conflicts at all */
+ pEnt->access->pAccess = NULL; /* remove from RAC */
+ break;
+ }
+
+ if (org_io) {
+ /* does the driver want the old access func? */
+ if (pEnt->rac->old) {
+ /* give it to the driver, leave state disabled */
+ pEnt->rac->old->io = org_io;
+ } else if (org_io->AccessEnable) {
+ /* driver doesn't want it - enable generic access */
+ org_io->AccessEnable(org_io->arg);
+ }
+ }
+
+ if (org_mem_io) {
+ /* does the driver want the old access func? */
+ if (pEnt->rac->old) {
+ /* give it to the driver, leave state disabled */
+ pEnt->rac->old->io_mem = org_mem_io;
+ } else if (org_mem_io->AccessEnable) {
+ /* driver doesn't want it - enable generic access */
+ org_mem_io->AccessEnable(org_mem_io->arg);
+ }
+ }
+
+ if (org_mem) {
+ /* does the driver want the old access func? */
+ if (pEnt->rac->old) {
+ /* give it to the driver, leave state disabled */
+ pEnt->rac->old->mem = org_mem;
+ } else if (org_mem->AccessEnable) {
+ /* driver doesn't want it - enable generic access */
+ org_mem->AccessEnable(org_mem->arg);
+ }
+ }
+
+ if (!(prop & NEED_MEM_SHARED)){
+ if (prop & NEED_MEM) {
+ if (acc_mem && acc_mem->AccessEnable)
+ acc_mem->AccessEnable(acc_mem->arg);
+ } else {
+ if (acc_mem && acc_mem->AccessDisable)
+ acc_mem->AccessDisable(acc_mem->arg);
+ }
+ }
+
+ if (!(prop & NEED_IO_SHARED)) {
+ if (prop & NEED_IO) {
+ if (acc_io && acc_io->AccessEnable)
+ acc_io->AccessEnable(acc_io->arg);
+ } else {
+ if (acc_io && acc_io->AccessDisable)
+ acc_io->AccessDisable(acc_io->arg);
+ }
+ }
+
+ /* disable shared resources */
+ if (pEnt->access->pAccess
+ && pEnt->access->pAccess->AccessDisable)
+ pEnt->access->pAccess->AccessDisable(pEnt->access->pAccess->arg);
+
+ /*
+ * If device is not under access control it is enabled.
+ * If it needs bus routing do it here as it isn't bus
+ * type specific. Any conflicts should be checked at this
+ * stage
+ */
+ if (!pEnt->access->pAccess
+ && (pEnt->entityProp & (state == SETUP ? NEED_VGA_ROUTED_SETUP :
+ NEED_VGA_ROUTED)))
+ ((BusAccPtr)pEnt->busAcc)->set_f(pEnt->busAcc);
+}
+
+
+/*
+ * xf86EnterServerState() -- set state the server is in.
+ */
+
+typedef enum { TRI_UNSET, TRI_TRUE, TRI_FALSE } TriState;
+
+static void
+SetSIGIOForState(xf86State state)
+{
+ static int sigio_state;
+ static TriState sigio_blocked = TRI_UNSET;
+
+ if ((state == SETUP) && (sigio_blocked != TRI_TRUE)) {
+ sigio_state = xf86BlockSIGIO();
+ sigio_blocked = TRI_TRUE;
+ } else if ((state == OPERATING) && (sigio_blocked != TRI_UNSET)) {
+ xf86UnblockSIGIO(sigio_state);
+ sigio_blocked = TRI_FALSE;
+ }
+}
+
+void
+xf86EnterServerState(xf86State state)
+{
+ EntityPtr pEnt;
+ ScrnInfoPtr pScrn;
+ int i,j;
+ int needVGA = 0;
+ resType rt;
+ /*
+ * This is a good place to block SIGIO during SETUP state.
+ * SIGIO should be blocked in SETUP state otherwise (u)sleep()
+ * might get interrupted early.
+ * We take care not to call xf86BlockSIGIO() twice.
+ */
+ SetSIGIOForState(state);
+#ifdef DEBUG
+ if (state == SETUP)
+ ErrorF("Entering SETUP state\n");
+ else
+ ErrorF("Entering OPERATING state\n");
+#endif
+
+ /* When servicing a dumb framebuffer we don't need to do anything */
+ if (doFramebufferMode) return;
+
+ for (i=0; i<xf86NumScreens; i++) {
+ pScrn = xf86Screens[i];
+ j = pScrn->entityList[pScrn->numEntities - 1];
+ pScrn->access = xf86Entities[j]->access;
+
+ for (j = 0; j<xf86Screens[i]->numEntities; j++) {
+ pEnt = xf86Entities[xf86Screens[i]->entityList[j]];
+ if (pEnt->entityProp & (state == SETUP ? NEED_VGA_ROUTED_SETUP
+ : NEED_VGA_ROUTED))
+ xf86Screens[i]->busAccess = pEnt->busAcc;
+ }
+ if (xf86Screens[i]->busAccess)
+ needVGA ++;
+ }
+
+ /*
+ * if we just have one screen we don't have RAC.
+ * Therefore just enable the screen and return.
+ */
+ if (!needRAC) {
+ xf86EnableAccess(xf86Screens[0]);
+ notifyStateChange(NOTIFY_ENABLE);
+ return;
+ }
+
+ if (state == SETUP)
+ notifyStateChange(NOTIFY_SETUP_TRANSITION);
+ else
+ notifyStateChange(NOTIFY_OPERATING_TRANSITION);
+
+ clearAccess();
+ for (i=0; i<xf86NumScreens;i++) {
+
+ rt = NONE;
+
+ for (j = 0; j<xf86Screens[i]->numEntities; j++) {
+ pEnt = xf86Entities[xf86Screens[i]->entityList[j]];
+ setAccess(pEnt,state);
+
+ if (pEnt->access->rt != NONE) {
+ if (rt != NONE && rt != pEnt->access->rt)
+ rt = MEM_IO;
+ else
+ rt = pEnt->access->rt;
+ }
+ }
+ xf86Screens[i]->resourceType = rt;
+ if (rt == NONE) {
+ xf86Screens[i]->access = NULL;
+ if (needVGA < 2)
+ xf86Screens[i]->busAccess = NULL;
+ }
+
+#ifdef DEBUG
+ if (xf86Screens[i]->busAccess)
+ ErrorF("Screen %i setting vga route\n",i);
+#endif
+ switch (rt) {
+ case MEM_IO:
+ xf86MsgVerb(X_INFO, 3, "Screen %i shares mem & io resources\n",i);
+ break;
+ case IO:
+ xf86MsgVerb(X_INFO, 3, "Screen %i shares io resources\n",i);
+ break;
+ case MEM:
+ xf86MsgVerb(X_INFO, 3, "Screen %i shares mem resources\n",i);
+ break;
+ default:
+ xf86MsgVerb(X_INFO, 3, "Entity %i shares no resources\n",i);
+ break;
+ }
+ }
+ if (state == SETUP)
+ notifyStateChange(NOTIFY_SETUP);
+ else
+ notifyStateChange(NOTIFY_OPERATING);
+}
+
+/*
+ * xf86SetOperatingState() -- Set ResOperMask for resources listed.
+ */
+resPtr
+xf86SetOperatingState(resList list, int entityIndex, int mask)
+{
+ resPtr acc;
+ resPtr r_fail = NULL;
+ resRange range;
+
+ while (list->type != ResEnd) {
+ range = *list;
+ convertRange2Host(entityIndex,&range);
+
+ acc = Acc;
+ while (acc) {
+#define MASK (ResTypeMask | ResExtMask)
+ if ((acc->entityIndex == entityIndex)
+ && (acc->val.a == range.a) && (acc->val.b == range.b)
+ && ((acc->val.type & MASK) == (range.type & MASK)))
+ break;
+#undef MASK
+ acc = acc->next;
+ }
+ if (acc)
+ acc->val.type = (acc->val.type & ~ResOprMask)
+ | (mask & ResOprMask);
+ else {
+ r_fail = xf86AddResToList(r_fail,&range,entityIndex);
+ }
+ list ++;
+ }
+
+ return r_fail;
+}
+
+/*
+ * Stage specific code
+ */
+ /*
+ * ProcessEstimatedConflicts() -- Do something about driver-registered
+ * resources that conflict with estimated resources. For now, just register
+ * them with a logged warning.
+ */
+#ifdef REDUCER
+static void
+ProcessEstimatedConflicts(void)
+{
+ if (!AccReducers)
+ return;
+
+ /* Temporary */
+ xf86MsgVerb(X_WARNING, 3,
+ "Registering the following despite conflicts with estimated"
+ " resources:\n");
+ xf86PrintResList(3, AccReducers);
+ Acc = xf86JoinResLists(Acc, AccReducers);
+ AccReducers = NULL;
+}
+#endif
+
+/*
+ * xf86ClaimFixedResources() -- This function gets called from the
+ * driver Probe() function to claim fixed resources.
+ */
+static void
+resError(resList list)
+{
+ FatalError("A driver tried to allocate the %s %sresource at \n"
+ "0x%x:0x%x which conflicted with another resource. Send the\n"
+ "output of the server to %s. Please \n"
+ "specify your computer hardware as closely as possible.\n",
+ ResIsBlock(list)?"Block":"Sparse",
+ ResIsMem(list)?"Mem":"Io",
+ ResIsBlock(list)?list->rBegin:list->rBase,
+ ResIsBlock(list)?list->rEnd:list->rMask,BUILDERADDR);
+}
+
+/*
+ * xf86ClaimFixedResources() is used to allocate non-relocatable resources.
+ * This should only be done by a driver's Probe() function.
+ */
+void
+xf86ClaimFixedResources(resList list, int entityIndex)
+{
+ resPtr ptr = NULL;
+ resRange range;
+
+ if (!list) return;
+
+ while (list->type !=ResEnd) {
+ range = *list;
+
+ convertRange2Host(entityIndex,&range);
+
+ range.type &= ~ResEstimated; /* Not allowed for drivers */
+ switch (range.type & ResAccMask) {
+ case ResExclusive:
+ if (!xf86ChkConflict(&range, entityIndex)) {
+ Acc = xf86AddResToList(Acc, &range, entityIndex);
+#ifdef REDUCER
+ } else {
+ range.type |= ResEstimated;
+ if (!xf86ChkConflict(&range, entityIndex) &&
+ !checkConflict(&range, AccReducers, entityIndex,
+ SETUP, FALSE)) {
+ range.type &= ~(ResEstimated | ResBios);
+ AccReducers =
+ xf86AddResToList(AccReducers, &range, entityIndex);
+#endif
+ } else resError(&range); /* no return */
+#ifdef REDUCER
+ }
+#endif
+ break;
+ case ResShared:
+ /* at this stage the resources are just added to the
+ * EntityRec. After the Probe() phase this list is checked by
+ * xf86PostProbe(). All resources which don't
+ * conflict with already allocated ones are allocated
+ * and removed from the EntityRec. Thus a non-empty resource
+ * list in the EntityRec indicates resource conflicts the
+ * driver should either handle or fail.
+ */
+ if (xf86Entities[entityIndex]->active)
+ ptr = xf86AddResToList(ptr,&range,entityIndex);
+ break;
+ }
+ list++;
+ }
+ xf86Entities[entityIndex]->resources =
+ xf86JoinResLists(xf86Entities[entityIndex]->resources,ptr);
+ xf86MsgVerb(X_INFO, 3,
+ "resource ranges after xf86ClaimFixedResources() call:\n");
+ xf86PrintResList(3,Acc);
+#ifdef REDUCER
+ ProcessEstimatedConflicts();
+#endif
+#ifdef DEBUG
+ if (ptr) {
+ xf86MsgVerb(X_INFO, 3, "to be registered later:\n");
+ xf86PrintResList(3,ptr);
+ }
+#endif
+}
+
+static void
+checkRoutingForScreens(xf86State state)
+{
+ resList list = resVgaUnusedExclusive;
+ resPtr pResVGA = NULL;
+ resPtr pResVGAHost;
+ pointer vga = NULL;
+ int i,j;
+ int entityIndex;
+ EntityPtr pEnt;
+ resPtr pAcc;
+ resRange range;
+
+ /*
+ * find devices that need VGA routed: ie the ones that have
+ * registered VGA resources without ResUnused. ResUnused
+ * doesn't conflict with itself therefore use it here.
+ */
+ while (list->type != ResEnd) { /* create resPtr from resList for VGA */
+ range = *list;
+ range.type &= ~(ResBios | ResEstimated); /* if set remove them */
+ pResVGA = xf86AddResToList(pResVGA, &range, -1);
+ list++;
+ }
+
+ for (i = 0; i < xf86NumScreens; i++) {
+ for (j = 0; j < xf86Screens[i]->numEntities; j++) {
+ entityIndex = xf86Screens[i]->entityList[j];
+ pEnt = xf86Entities[entityIndex];
+ pAcc = Acc;
+ vga = NULL;
+ pResVGAHost = xf86DupResList(pResVGA);
+ xf86ConvertListToHost(entityIndex,pResVGAHost);
+ while (pAcc) {
+ if (pAcc->entityIndex == entityIndex)
+ if (checkConflict(&pAcc->val, pResVGAHost,
+ entityIndex, state, FALSE)) {
+ if (vga && vga != pEnt->busAcc) {
+ xf86Msg(X_ERROR, "Screen %i needs vga routed to"
+ "different buses - deleting\n",i);
+ xf86DeleteScreen(i--,0);
+ }
+#ifdef DEBUG
+ {
+ resPtr rlist = xf86AddResToList(NULL,&pAcc->val,
+ pAcc->entityIndex);
+ xf86MsgVerb(X_INFO,3,"====== %s\n",
+ state == OPERATING ? "OPERATING"
+ : "SETUP");
+ xf86MsgVerb(X_INFO,3,"%s Resource:\n",
+ (pAcc->val.type) & ResMem ? "Mem" :"Io");
+ xf86PrintResList(3,rlist);
+ xf86FreeResList(rlist);
+ xf86MsgVerb(X_INFO,3,"Conflicts with:\n");
+ xf86PrintResList(3,pResVGAHost);
+ xf86MsgVerb(X_INFO,3,"=====\n");
+ }
+#endif
+ vga = pEnt->busAcc;
+ pEnt->entityProp |= (state == SETUP
+ ? NEED_VGA_ROUTED_SETUP : NEED_VGA_ROUTED);
+ if (state == OPERATING) {
+ if (pAcc->val.type & ResMem)
+ pEnt->entityProp |= NEED_VGA_MEM;
+ else
+ pEnt->entityProp |= NEED_VGA_IO;
+ }
+ }
+ pAcc = pAcc->next;
+ }
+ if (vga)
+ xf86MsgVerb(X_INFO, 3,"Setting vga for screen %i.\n",i);
+ xf86FreeResList(pResVGAHost);
+ }
+ }
+ xf86FreeResList(pResVGA);
+}
+
+/*
+ * xf86PostProbe() -- Allocate all non conflicting resources
+ * This function gets called by xf86Init().
+ */
+void
+xf86PostProbe(void)
+{
+ memType val;
+ int i,j;
+ resPtr resp, acc, tmp, resp_x, *pprev_next;
+
+ if (fbSlotClaimed) {
+ if (pciSlotClaimed || isaSlotClaimed
+#if defined(__sparc__) && !defined(__OpenBSD__)
+ || sbusSlotClaimed
+#endif
+ ) {
+ FatalError("Cannot run in framebuffer mode. Please specify busIDs "
+ " for all framebuffer devices\n");
+ return;
+ } else {
+ xf86Msg(X_INFO,"Running in FRAMEBUFFER Mode\n");
+ xf86AccessRestoreState();
+ notifyStateChange(NOTIFY_ENABLE);
+ doFramebufferMode = TRUE;
+
+ return;
+ }
+ }
+ /* don't compare against ResInit - remove it from clone.*/
+ acc = tmp = xf86DupResList(Acc);
+ pprev_next = &acc;
+ while (tmp) {
+ if (tmp->res_type & ResInit) {
+ (*pprev_next) = tmp->next;
+ xfree(tmp);
+ } else
+ pprev_next = &(tmp->next);
+ tmp = (*pprev_next);
+ }
+
+ for (i=0; i<xf86NumEntities; i++) {
+ resp = xf86Entities[i]->resources;
+ xf86Entities[i]->resources = NULL;
+ resp_x = NULL;
+ while (resp) {
+ if (! (val = checkConflict(&resp->val,acc,i,SETUP,FALSE))) {
+ resp->res_type &= ~(ResBios); /* just used for chkConflict() */
+ tmp = resp_x;
+ resp_x = resp;
+ resp = resp->next;
+ resp_x->next = tmp;
+#ifdef REDUCER
+ } else {
+ resp->res_type |= ResEstimated;
+ if (!checkConflict(&resp->val, acc, i, SETUP, FALSE)) {
+ resp->res_type &= ~(ResEstimated | ResBios);
+ tmp = AccReducers;
+ AccReducers = resp;
+ resp = resp->next;
+ AccReducers->next = tmp;
+#endif
+ } else {
+ xf86MsgVerb(X_INFO, 3, "Found conflict at: 0x%lx\n",val);
+ resp->res_type &= ~ResEstimated;
+ tmp = xf86Entities[i]->resources;
+ xf86Entities[i]->resources = resp;
+ resp = resp->next;
+ xf86Entities[i]->resources->next = tmp;
+ }
+#ifdef REDUCER
+ }
+#endif
+ }
+ xf86JoinResLists(Acc,resp_x);
+#ifdef REDUCER
+ ProcessEstimatedConflicts();
+#endif
+ }
+ xf86FreeResList(acc);
+
+#if !(defined(__alpha__) && defined(linux)) && \
+ !(defined(__sparc64__) && defined(__OpenBSD__))
+ /*
+ * No need to validate on Alpha Linux or OpenBSD/sparc64,
+ * trust the kernel.
+ */
+ ValidatePci();
+#endif
+
+ xf86MsgVerb(X_INFO, 3, "resource ranges after probing:\n");
+ xf86PrintResList(3, Acc);
+ checkRoutingForScreens(SETUP);
+
+ for (i = 0; i < xf86NumScreens; i++) {
+ for (j = 0; j<xf86Screens[i]->numEntities; j++) {
+ EntityPtr pEnt = xf86Entities[xf86Screens[i]->entityList[j]];
+ if ((pEnt->entityProp & NEED_VGA_ROUTED_SETUP) &&
+ ((xf86Screens[i]->busAccess = pEnt->busAcc)))
+ break;
+ }
+ }
+}
+
+static void
+checkRequiredResources(int entityIndex)
+{
+ resRange range;
+ resPtr pAcc = Acc;
+ const EntityPtr pEnt = xf86Entities[entityIndex];
+ while (pAcc) {
+ if (pAcc->entityIndex == entityIndex) {
+ range = pAcc->val;
+ /* ResAny to find conflicts with anything. */
+ range.type = (range.type & ~ResAccMask) | ResAny | ResBios;
+ if (checkConflict(&range,Acc,entityIndex,OPERATING,FALSE))
+ switch (pAcc->res_type & ResPhysMask) {
+ case ResMem:
+ pEnt->entityProp |= NEED_MEM_SHARED;
+ break;
+ case ResIo:
+ pEnt->entityProp |= NEED_IO_SHARED;
+ break;
+ }
+ if (!(pAcc->res_type & ResOprMask)) {
+ switch (pAcc->res_type & ResPhysMask) {
+ case ResMem:
+ pEnt->entityProp |= NEED_MEM;
+ break;
+ case ResIo:
+ pEnt->entityProp |= NEED_IO;
+ break;
+ }
+ }
+ }
+ pAcc = pAcc->next;
+ }
+
+ /* check if we can separately enable mem/io resources */
+ /* XXX we still need to find out how to set this yet */
+ if ( ((pEnt->entityProp & NO_SEPARATE_MEM_FROM_IO)
+ && (pEnt->entityProp & NEED_MEM_SHARED))
+ || ((pEnt->entityProp & NO_SEPARATE_IO_FROM_MEM)
+ && (pEnt->entityProp & NEED_IO_SHARED)) )
+ pEnt->entityProp |= NEED_SHARED;
+ /*
+ * After we have checked all resources of an entity agains any
+ * other resource we know if the entity need this resource type
+ * (ie. mem/io) at all. if not we can disable this type completely,
+ * so no need to share it either.
+ */
+ if ((pEnt->entityProp & NEED_MEM_SHARED)
+ && (!(pEnt->entityProp & NEED_MEM))
+ && (!(pEnt->entityProp & NO_SEPARATE_MEM_FROM_IO)))
+ pEnt->entityProp &= ~(unsigned long)NEED_MEM_SHARED;
+
+ if ((pEnt->entityProp & NEED_IO_SHARED)
+ && (!(pEnt->entityProp & NEED_IO))
+ && (!(pEnt->entityProp & NO_SEPARATE_IO_FROM_MEM)))
+ pEnt->entityProp &= ~(unsigned long)NEED_IO_SHARED;
+}
+
+void
+xf86PostPreInit()
+{
+ if (doFramebufferMode) return;
+
+ if (xf86NumScreens > 1)
+ needRAC = TRUE;
+
+#ifdef XFree86LOADER
+ xf86MsgVerb(X_INFO, 3, "do I need RAC?");
+
+ if (needRAC) {
+ xf86ErrorFVerb(3, " Yes, I do.\n");
+
+ if (!xf86LoadOneModule("rac",NULL))
+ FatalError("Cannot load RAC module\n");
+ } else
+ xf86ErrorFVerb(3, " No, I don't.\n");
+#endif
+
+ xf86MsgVerb(X_INFO, 3, "resource ranges after preInit:\n");
+ xf86PrintResList(3, Acc);
+}
+
+void
+xf86PostScreenInit(void)
+{
+ int i,j;
+ ScreenPtr pScreen;
+ unsigned int flags;
+ int nummem = 0, numio = 0;
+#ifdef XFree86LOADER
+ pointer xf86RACInit = NULL;
+#endif
+
+ if (doFramebufferMode) {
+ SetSIGIOForState(OPERATING);
+ return;
+ }
+
+#ifdef XFree86LOADER
+ if (needRAC) {
+ xf86RACInit = LoaderSymbol("xf86RACInit");
+ if (!xf86RACInit)
+ FatalError("Cannot resolve symbol \"xf86RACInit\"\n");
+ }
+#endif
+#ifdef DEBUG
+ ErrorF("PostScreenInit generation: %i\n",serverGeneration);
+#endif
+ if (serverGeneration == 1) {
+ checkRoutingForScreens(OPERATING);
+ for (i=0; i<xf86NumEntities; i++) {
+ checkRequiredResources(i);
+ }
+
+ /*
+ * after removing NEED_XXX_SHARED from entities that
+ * don't need need XXX resources at all we might have
+ * a single entity left that has NEED_XXX_SHARED set.
+ * In this case we can delete that, too.
+ */
+ for (i = 0; i < xf86NumEntities; i++) {
+ if (xf86Entities[i]->entityProp & NEED_MEM_SHARED)
+ nummem++;
+ if (xf86Entities[i]->entityProp & NEED_IO_SHARED)
+ numio++;
+ }
+ for (i = 0; i < xf86NumEntities; i++) {
+ if (nummem < 2)
+ xf86Entities[i]->entityProp &= ~NEED_MEM_SHARED;
+ if (numio < 2)
+ xf86Entities[i]->entityProp &= ~NEED_IO_SHARED;
+ }
+ }
+
+ if (xf86Screens && needRAC) {
+ int needRACforVga = 0;
+
+ for (i = 0; i < xf86NumScreens; i++) {
+ for (j = 0; j < xf86Screens[i]->numEntities; j++) {
+ if (xf86Entities[xf86Screens[i]->entityList[j]]->entityProp
+ & NEED_VGA_ROUTED) {
+ needRACforVga ++;
+ break; /* only count each screen once */
+ }
+ }
+ }
+
+ for (i = 0; i < xf86NumScreens; i++) {
+ Bool needRACforMem = FALSE, needRACforIo = FALSE;
+
+ for (j = 0; j < xf86Screens[i]->numEntities; j++) {
+ if (xf86Entities[xf86Screens[i]->entityList[j]]->entityProp
+ & NEED_MEM_SHARED)
+ needRACforMem = TRUE;
+ if (xf86Entities[xf86Screens[i]->entityList[j]]->entityProp
+ & NEED_IO_SHARED)
+ needRACforIo = TRUE;
+ /*
+ * We may need RAC although we don't share any resources
+ * as we need to route VGA to the correct bus. This can
+ * only be done simultaniously for MEM and IO.
+ */
+ if (needRACforVga > 1) {
+ if (xf86Entities[xf86Screens[i]->entityList[j]]->entityProp
+ & NEED_VGA_MEM)
+ needRACforMem = TRUE;
+ if (xf86Entities[xf86Screens[i]->entityList[j]]->entityProp
+ & NEED_VGA_IO)
+ needRACforIo = TRUE;
+ }
+ }
+
+ pScreen = xf86Screens[i]->pScreen;
+ flags = 0;
+ if (needRACforMem) {
+ flags |= xf86Screens[i]->racMemFlags;
+ xf86ErrorFVerb(3, "Screen %d is using RAC for mem\n", i);
+ }
+ if (needRACforIo) {
+ flags |= xf86Screens[i]->racIoFlags;
+ xf86ErrorFVerb(3, "Screen %d is using RAC for io\n", i);
+ }
+
+#ifdef XFree86LOADER
+ ((Bool(*)(ScreenPtr,unsigned int))xf86RACInit)
+ (pScreen,flags);
+#else
+ xf86RACInit(pScreen,flags);
+#endif
+ }
+ }
+
+ xf86EnterServerState(OPERATING);
+
+}
+
+/*
+ * Sets
+ */
+
+
+static resPtr
+decomposeSparse(resRange range)
+{
+ resRange new;
+ resPtr ret = NULL;
+ memType val = range.rBegin;
+ int i = 0;
+
+ new.type = (range.type & ~ResExtMask) | ResSparse;
+
+ while (1) {
+ if (val & 0x01) {
+ new.rBase = (val << i);
+ new.rMask = ~((1 << i) - 1);
+ ret = xf86AddResToList(ret,&new,-1);
+ val ++;
+ }
+ i++;
+ val >>= 1;
+ if ((((val + 1) << i) - 1) > range.rEnd)
+ break;
+ }
+ i--;
+ val <<= 1;
+
+ while (1) {
+ if((((val + 1) << i) - 1)> range.rEnd) {
+ if (--i < 0) break;
+ val <<= 1;
+ } else {
+ new.rBase = (val << i);
+ new.rMask = ~((1 << i) - 1);
+ val++;
+ ret = xf86AddResToList(ret,&new,-1);
+ }
+ }
+ return ret;
+}
+
+static Bool
+x_isSubsetOf(resRange range, resPtr list1, resPtr list2)
+{
+ resRange range1, range2;
+ memType m1_A_m2;
+ Bool ret;
+ resPtr list;
+
+ if (list1) {
+ list = list1;
+ if ((range.type & ResTypeMask) == (list->res_type & ResTypeMask)) {
+ switch (range.type & ResExtMask) {
+ case ResBlock:
+ if ((list->res_type & ResExtMask) == ResBlock) {
+ if (range.rBegin >= list->block_begin
+ && range.rEnd <= list->block_end)
+ return TRUE;
+ else if (range.rBegin < list->block_begin
+ && range.rEnd > list->block_end) {
+ RANGE(range1, range.rBegin, list->block_begin - 1,
+ range.type);
+ RANGE(range2, list->block_end + 1, range.rEnd,
+ range.type);
+ return (x_isSubsetOf(range1,list->next,list2) &&
+ x_isSubsetOf(range2,list->next,list2));
+ }
+ else if (range.rBegin >= list->block_begin
+ && range.rBegin <= list->block_end) {
+ RANGE(range1, list->block_end + 1, range.rEnd,
+ range.type);
+ return (x_isSubsetOf(range1,list->next,list2));
+ } else if (range.rEnd >= list->block_begin
+ && range.rEnd <= list->block_end) {
+ RANGE(range1,range.rBegin, list->block_begin - 1,
+ range.type);
+ return (x_isSubsetOf(range1,list->next,list2));
+ }
+ }
+ break;
+ case ResSparse:
+ if ((list->res_type & ResExtMask) == ResSparse) {
+ memType test;
+ int i;
+
+ m1_A_m2 = range.rMask & list->sparse_mask;
+ if ((range.rBase ^ list->sparse_base) & m1_A_m2)
+ break;
+ /*
+ * We use the following system:
+ * let 0 ^= mask:1 base:0, 1 ^= mask:1 base:1,
+ * X mask:0 ; S: set TSS: test set for subset
+ * NTSS: new test set after test
+ * S: 1 0 1 0 X X 0 1 X
+ * TSS: 1 0 0 1 1 0 X X X
+ * T: 0 0 1 1 0 0 0 0 0
+ * NTSS: 1 0 0/X 1/X 1 0 1 0 X
+ * R: 0 0 0 0 0 0 1 1 0
+ * If R != 0 TSS and S are disjunct
+ * If R == 0 TSS is subset of S
+ * If R != 0 NTSS contains elements from TSS
+ * which are not also members of S.
+ * If a T is set one of the correspondig bits
+ * in NTSS must be set to the specified value
+ * all other are X
+ */
+ test = list->sparse_mask & ~range.rMask;
+ if (test == 0)
+ return TRUE;
+ for (i = 0; i < sizeof(memType); i++) {
+ if ((test >> i) & 0x1) {
+ RANGE(range1, ((range.rBase & list->sparse_base)
+ | (range.rBase & ~list->sparse_mask)
+ | ((~list->sparse_base & list->sparse_mask)
+ & ~range.rMask)) & range1.rMask,
+ ((range.rMask | list->sparse_mask) & ~test)
+ | (1 << i), range.type);
+ return (x_isSubsetOf(range1,list->next,list2));
+ }
+ }
+ }
+ break;
+ }
+ }
+ return (x_isSubsetOf(range,list->next,list2));
+ } else if (list2) {
+ resPtr tmpList = NULL;
+ switch (range.type & ResExtMask) {
+ case ResBlock:
+ tmpList = decomposeSparse(range);
+ while (tmpList) {
+ if (!x_isSubsetOf(tmpList->val,list2,NULL)) {
+ xf86FreeResList(tmpList);
+ return FALSE;
+ }
+ tmpList = tmpList->next;
+ }
+ xf86FreeResList(tmpList);
+ return TRUE;
+ break;
+ case ResSparse:
+ while (list2) {
+ tmpList = xf86JoinResLists(tmpList,decomposeSparse(list2->val));
+ list2 = list2->next;
+ }
+ ret = x_isSubsetOf(range,tmpList,NULL);
+ xf86FreeResList(tmpList);
+ return ret;
+ break;
+ }
+ } else
+ return FALSE;
+
+ return FALSE;
+}
+
+Bool
+xf86IsSubsetOf(resRange range, resPtr list)
+{
+ resPtr dup = xf86DupResList(list);
+ resPtr r_sp = NULL, r = NULL, tmp = NULL;
+ Bool ret = FALSE;
+
+ while (dup) {
+ tmp = dup;
+ dup = dup->next;
+ switch (tmp->res_type & ResExtMask) {
+ case ResBlock:
+ tmp->next = r;
+ r = tmp;
+ break;
+ case ResSparse:
+ tmp->next = r_sp;
+ r_sp = tmp;
+ break;
+ }
+ }
+
+ switch (range.type & ResExtMask) {
+ case ResBlock:
+ ret = x_isSubsetOf(range,r,r_sp);
+ break;
+ case ResSparse:
+ ret = x_isSubsetOf(range,r_sp,r);
+ break;
+ }
+ xf86FreeResList(r);
+ xf86FreeResList(r_sp);
+
+ return ret;
+}
+
+Bool
+xf86IsListSubsetOf(resPtr list, resPtr BaseList)
+{
+ while (list) {
+ if (! xf86IsSubsetOf(list->val,BaseList))
+ return FALSE;
+ list = list->next;
+ }
+ return TRUE;
+}
+
+resPtr
+findIntersect(resRange Range, resPtr list)
+{
+ resRange range;
+ resPtr new = NULL;
+
+ while (list) {
+ if ((Range.type & ResTypeMask) == (list->res_type & ResTypeMask)) {
+ switch (Range.type & ResExtMask) {
+ case ResBlock:
+ switch (list->res_type & ResExtMask) {
+ case ResBlock:
+ if (Range.rBegin >= list->block_begin)
+ range.rBegin = Range.rBegin;
+ else
+ range.rBegin = list->block_begin;
+ if (Range.rEnd <= list->block_end)
+ range.rEnd = Range.rEnd;
+ else
+ range.rEnd = list->block_end;
+ if (range.rEnd > range.rBegin) {
+ range.type = Range.type;
+ new = xf86AddResToList(new,&range,-1);
+ }
+ break;
+ case ResSparse:
+ new = xf86JoinResLists(new,xf86FindIntersectOfLists(new,decomposeSparse(list->val)));
+ break;
+ }
+ break;
+ case ResSparse:
+ switch (list->res_type & ResExtMask) {
+ case ResSparse:
+ if (!((~(range.rBase ^ list->sparse_base)
+ & (range.rMask & list->sparse_mask)))) {
+ RANGE(range, (range.rBase & list->sparse_base)
+ | (~range.rMask & list->sparse_base)
+ | (~list->sparse_mask & range.rBase),
+ range.rMask | list->sparse_mask,
+ Range.type);
+ new = xf86AddResToList(new,&range,-1);
+ }
+ break;
+ case ResBlock:
+ new = xf86JoinResLists(new,xf86FindIntersectOfLists(
+ decomposeSparse(range),list));
+ break;
+ }
+ }
+ }
+ list = list->next;
+ }
+ return new;
+}
+
+resPtr
+xf86FindIntersectOfLists(resPtr l1, resPtr l2)
+{
+ resPtr ret = NULL;
+
+ while (l1) {
+ ret = xf86JoinResLists(ret,findIntersect(l1->val,l2));
+ l1 = l1->next;
+ }
+ return ret;
+}
+
+#if 0 /* Not used */
+static resPtr
+xf86FindComplement(resRange Range)
+{
+ resRange range;
+ memType tmp;
+ resPtr new = NULL;
+ int i;
+
+ switch (Range.type & ResExtMask) {
+ case ResBlock:
+ if (Range.rBegin > 0) {
+ RANGE(range, 0, Range.rBegin - 1, Range.type);
+ new = xf86AddResToList(new,&range,-1);
+ }
+ if (Range.rEnd < (memType)~0) {
+ RANGE(range,Range.rEnd + 1, (memType)~0, Range.type);
+ new = xf86AddResToList(new,&range,-1);
+ }
+ break;
+ case ResSparse:
+ tmp = Range.rMask;
+ for (i = 0; i < sizeof(memType); i++) {
+ if (tmp & 0x1) {
+ RANGE(range,(~Range.rMask & range.rMask),(1 << i), Range.type);
+ new = xf86AddResToList(new,&range,-1);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ return new;
+}
+#endif
+
+resPtr
+xf86ExtractTypeFromList(resPtr list, unsigned long type)
+{
+ resPtr ret = NULL;
+
+ while (list) {
+ if ((list->res_type & ResTypeMask) == type)
+ ret = xf86AddResToList(ret,&(list->val),list->entityIndex);
+ list = list->next;
+ }
+ return ret;
+}
+
+/*------------------------------------------------------------*/
+static void CheckGenericGA(void);
+
+/*
+ * xf86FindPrimaryDevice() - Find the display device which
+ * was active when the server was started.
+ */
+void
+xf86FindPrimaryDevice()
+{
+ /* if no VGA device is found check for primary PCI device */
+ if (primaryBus.type == BUS_NONE)
+ CheckGenericGA();
+ if (primaryBus.type != BUS_NONE) {
+ char *bus;
+ char *loc = xnfcalloc(1,9);
+ if (loc == NULL) return;
+
+ switch (primaryBus.type) {
+ case BUS_PCI:
+ bus = "PCI";
+ sprintf(loc," %2.2x:%2.2x:%1.1x",primaryBus.id.pci.bus,
+ primaryBus.id.pci.device,primaryBus.id.pci.func);
+ break;
+ case BUS_ISA:
+ bus = "ISA";
+ loc[0] = '\0';
+ break;
+ case BUS_SBUS:
+ bus = "SBUS";
+ sprintf(loc," %2.2x",primaryBus.id.sbus.fbNum);
+ break;
+ default:
+ bus = "";
+ loc[0] = '\0';
+ }
+
+ xf86MsgVerb(X_INFO, 2, "Primary Device is: %s%s\n",bus,loc);
+ xfree(loc);
+ }
+
+}
+
+#if !defined(__sparc__) && !defined(__powerpc__) && !defined(__mips__)
+#include "vgaHW.h"
+#include "compiler.h"
+#endif
+
+/*
+ * CheckGenericGA() - Check for presence of a VGA device.
+ */
+static void
+CheckGenericGA()
+{
+/* This needs to be changed for multiple domains */
+#if !defined(__sparc__) && !defined(__powerpc__) && !defined(__mips__)
+ IOADDRESS GenericIOBase = VGAHW_GET_IOBASE();
+ CARD8 CurrentValue, TestValue;
+
+ /* VGA CRTC registers are not used here, so don't bother unlocking them */
+
+ /* VGA has one more read/write attribute register than EGA */
+ (void) inb(GenericIOBase + VGA_IN_STAT_1_OFFSET); /* Reset flip-flop */
+ outb(VGA_ATTR_INDEX, 0x14 | 0x20);
+ CurrentValue = inb(VGA_ATTR_DATA_R);
+ outb(VGA_ATTR_DATA_W, CurrentValue ^ 0x0F);
+ outb(VGA_ATTR_INDEX, 0x14 | 0x20);
+ TestValue = inb(VGA_ATTR_DATA_R);
+ outb(VGA_ATTR_DATA_W, CurrentValue);
+
+ if ((CurrentValue ^ 0x0F) == TestValue) {
+ primaryBus.type = BUS_ISA;
+ }
+#endif
+}
+
+Bool
+xf86NoSharedResources(int screenIndex,resType res)
+{
+ int j;
+
+ if (screenIndex > xf86NumScreens)
+ return TRUE;
+
+ for (j = 0; j < xf86Screens[screenIndex]->numEntities; j++) {
+ switch (res) {
+ case IO:
+ if ( xf86Entities[xf86Screens[screenIndex]->entityList[j]]->entityProp
+ & NEED_IO_SHARED)
+ return FALSE;
+ break;
+ case MEM:
+ if ( xf86Entities[xf86Screens[screenIndex]->entityList[j]]->entityProp
+ & NEED_MEM_SHARED)
+ return FALSE;
+ break;
+ case MEM_IO:
+ if ( xf86Entities[xf86Screens[screenIndex]->entityList[j]]->entityProp
+ & NEED_SHARED)
+ return FALSE;
+ break;
+ case NONE:
+ break;
+ }
+ }
+ return TRUE;
+}
+
+void
+xf86ConvertListToHost(int entityIndex, resPtr list)
+{
+ while (list) {
+ convertRange2Host(entityIndex, &list->val);
+ list = list->next;
+ }
+}
+
+void
+xf86RegisterStateChangeNotificationCallback(xf86StateChangeNotificationCallbackFunc func, pointer arg)
+{
+ StateChangeNotificationPtr ptr =
+ (StateChangeNotificationPtr)xnfalloc(sizeof(StateChangeNotificationRec));
+
+ ptr->func = func;
+ ptr->arg = arg;
+ ptr->next = StateChangeNotificationList;
+ StateChangeNotificationList = ptr;
+}
+
+Bool
+xf86DeregisterStateChangeNotificationCallback(xf86StateChangeNotificationCallbackFunc func)
+{
+ StateChangeNotificationPtr *ptr = &StateChangeNotificationList;
+ StateChangeNotificationPtr tmp;
+
+ while (*ptr) {
+ if ((*ptr)->func == func) {
+ tmp = (*ptr);
+ (*ptr) = (*ptr)->next;
+ xfree(tmp);
+ return TRUE;
+ }
+ ptr = &((*ptr)->next);
+ }
+ return FALSE;
+}
+
+static void
+notifyStateChange(xf86NotifyState state)
+{
+ StateChangeNotificationPtr ptr = StateChangeNotificationList;
+ while (ptr) {
+ ptr->func(state,ptr->arg);
+ ptr = ptr->next;
+ }
+}
+
+#ifdef async
+Bool
+xf86QueueAsyncEvent(void (*func)(pointer),pointer arg)
+{
+ AsyncQPtr new;
+
+ if (!AsyncQ) return FALSE;
+
+ new = (AsyncQPtr)xfnalloc(sizeof(AsyncQRec));
+ new->func = func;
+ new->arg = arg;
+ (*AsyncQPtr)->next = new;
+ AsyncQPtr = &new;
+ return TRUE;
+}
+#endif
+
+/* Multihead accel sharing accessor functions and entity Private handling */
+
+int
+xf86GetLastScrnFlag(int entityIndex)
+{
+ if(entityIndex < xf86NumEntities) {
+ return(xf86Entities[entityIndex]->lastScrnFlag);
+ } else {
+ return -1;
+ }
+}
+
+void
+xf86SetLastScrnFlag(int entityIndex, int scrnIndex)
+{
+ if(entityIndex < xf86NumEntities) {
+ xf86Entities[entityIndex]->lastScrnFlag = scrnIndex;
+ }
+}
+
+Bool
+xf86IsEntityShared(int entityIndex)
+{
+ if(entityIndex < xf86NumEntities) {
+ if(xf86Entities[entityIndex]->entityProp & IS_SHARED_ACCEL) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+void
+xf86SetEntityShared(int entityIndex)
+{
+ if(entityIndex < xf86NumEntities) {
+ xf86Entities[entityIndex]->entityProp |= IS_SHARED_ACCEL;
+ }
+}
+
+Bool
+xf86IsEntitySharable(int entityIndex)
+{
+ if(entityIndex < xf86NumEntities) {
+ if(xf86Entities[entityIndex]->entityProp & ACCEL_IS_SHARABLE) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+void
+xf86SetEntitySharable(int entityIndex)
+{
+ if(entityIndex < xf86NumEntities) {
+ xf86Entities[entityIndex]->entityProp |= ACCEL_IS_SHARABLE;
+ }
+}
+
+Bool
+xf86IsPrimInitDone(int entityIndex)
+{
+ if(entityIndex < xf86NumEntities) {
+ if(xf86Entities[entityIndex]->entityProp & SA_PRIM_INIT_DONE) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+void
+xf86SetPrimInitDone(int entityIndex)
+{
+ if(entityIndex < xf86NumEntities) {
+ xf86Entities[entityIndex]->entityProp |= SA_PRIM_INIT_DONE;
+ }
+}
+
+void
+xf86ClearPrimInitDone(int entityIndex)
+{
+ if(entityIndex < xf86NumEntities) {
+ xf86Entities[entityIndex]->entityProp &= ~SA_PRIM_INIT_DONE;
+ }
+}
+
+
+/*
+ * Allocate a private in the entities.
+ */
+
+int
+xf86AllocateEntityPrivateIndex(void)
+{
+ int idx, i;
+ EntityPtr pEnt;
+ DevUnion *nprivs;
+
+ idx = xf86EntityPrivateCount++;
+ for (i = 0; i < xf86NumEntities; i++) {
+ pEnt = xf86Entities[i];
+ nprivs = xnfrealloc(pEnt->entityPrivates,
+ xf86EntityPrivateCount * sizeof(DevUnion));
+ /* Zero the new private */
+ bzero(&nprivs[idx], sizeof(DevUnion));
+ pEnt->entityPrivates = nprivs;
+ }
+ return idx;
+}
+
+DevUnion *
+xf86GetEntityPrivate(int entityIndex, int privIndex)
+{
+ if (entityIndex >= xf86NumEntities || privIndex >= xf86EntityPrivateCount)
+ return NULL;
+
+ return &(xf86Entities[entityIndex]->entityPrivates[privIndex]);
+}
+
diff --git a/hw/xfree86/common/xf86Bus.h b/hw/xfree86/common/xf86Bus.h
new file mode 100644
index 000000000..6a129ad56
--- /dev/null
+++ b/hw/xfree86/common/xf86Bus.h
@@ -0,0 +1,135 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86Bus.h,v 1.21 2002/11/25 14:04:56 eich Exp $ */
+/*
+ * Copyright (c) 1997 by The XFree86 Project, Inc.
+ */
+
+/*
+ * This file contains definitions of the bus-related data structures/types.
+ * Everything contained here is private to xf86Bus.c. In particular the
+ * video drivers must not include this file.
+ */
+
+#ifndef _XF86_BUS_H
+#define _XF86_BUS_H
+
+#include "xf86pciBus.h"
+#ifdef __sparc__
+#include "xf86sbusBus.h"
+#endif
+
+typedef struct racInfo {
+ xf86AccessPtr mem_new;
+ xf86AccessPtr io_new;
+ xf86AccessPtr io_mem_new;
+ xf86SetAccessFuncPtr old;
+} AccessFuncRec, *AccessFuncPtr;
+
+
+typedef struct {
+ DriverPtr driver;
+ int chipset;
+ int entityProp;
+ EntityProc entityInit;
+ EntityProc entityEnter;
+ EntityProc entityLeave;
+ pointer private;
+ resPtr resources;
+ Bool active;
+ Bool inUse;
+ BusRec bus;
+ EntityAccessPtr access;
+ AccessFuncPtr rac;
+ pointer busAcc;
+ int lastScrnFlag;
+ DevUnion * entityPrivates;
+ int numInstances;
+ GDevPtr * devices;
+ IOADDRESS domainIO;
+} EntityRec, *EntityPtr;
+
+/* asynchronous event handling */
+#ifdef async
+typedef struct _AsyncQRec {
+ void (*func)(pointer);
+ pointer arg;
+ struct _AsyncQRec *next;
+} AsyncQRec, *AsyncQPtr;
+#endif
+
+#define NO_SEPARATE_IO_FROM_MEM 0x0001
+#define NO_SEPARATE_MEM_FROM_IO 0x0002
+#define NEED_VGA_ROUTED 0x0004
+#define NEED_VGA_ROUTED_SETUP 0x0008
+#define NEED_MEM 0x0010
+#define NEED_IO 0x0020
+#define NEED_MEM_SHARED 0x0040
+#define NEED_IO_SHARED 0x0080
+#define ACCEL_IS_SHARABLE 0x0100
+#define IS_SHARED_ACCEL 0x0200
+#define SA_PRIM_INIT_DONE 0x0400
+#define NEED_VGA_MEM 0x1000
+#define NEED_VGA_IO 0x2000
+
+#define NEED_SHARED (NEED_MEM_SHARED | NEED_IO_SHARED)
+
+#define busType bus.type
+#define pciBusId bus.id.pci
+#define isaBusId bus.id.isa
+#define sbusBusId bus.id.sbus
+
+struct x_BusAccRec;
+typedef void (*BusAccProcPtr)(struct x_BusAccRec *ptr);
+
+typedef struct x_BusAccRec {
+ BusAccProcPtr set_f;
+ BusAccProcPtr enable_f;
+ BusAccProcPtr disable_f;
+ BusAccProcPtr save_f;
+ BusAccProcPtr restore_f;
+ struct x_BusAccRec *current; /* pointer to bridge open on this bus */
+ struct x_BusAccRec *primary; /* pointer to the bus connecting to this */
+ struct x_BusAccRec *next; /* this links the different buses together */
+ BusType type;
+ BusType busdep_type;
+ /* Bus-specific fields */
+ union {
+ struct {
+ int bus;
+ int primary_bus;
+ PCITAG acc;
+ pciBridgesSave save;
+ void (*func)(PCITAG,int,CARD32,CARD32);
+ } pci;
+ } busdep;
+} BusAccRec, *BusAccPtr;
+
+/* state change notification callback */
+typedef struct _stateChange {
+ xf86StateChangeNotificationCallbackFunc func;
+ pointer arg;
+ struct _stateChange *next;
+} StateChangeNotificationRec, *StateChangeNotificationPtr;
+
+
+extern EntityPtr *xf86Entities;
+extern int xf86NumEntities;
+extern xf86AccessRec AccessNULL;
+extern BusRec primaryBus;
+extern resPtr Acc;
+extern resPtr osRes;
+extern resPtr ResRange;
+extern BusAccPtr xf86BusAccInfo;
+
+int xf86AllocateEntity(void);
+BusType StringToBusType(const char* busID, const char **retID);
+memType ChkConflict(resRange *rgp, resPtr res, xf86State state);
+Bool xf86IsSubsetOf(resRange range, resPtr list);
+Bool xf86IsListSubsetOf(resPtr list, resPtr BaseList);
+resPtr xf86ExtractTypeFromList(resPtr list, unsigned long type);
+resPtr findIntersect(resRange Range, resPtr list);
+resPtr xf86FindIntersect(resRange Range, resPtr list);
+void RemoveOverlaps(resPtr target, resPtr list, Bool pow2Alignment,
+ Bool useEstimated);
+void xf86ConvertListToHost(int entityIndex, resPtr list);
+
+#endif /* _XF86_BUS_H */
diff --git a/hw/xfree86/common/xf86Config.h b/hw/xfree86/common/xf86Config.h
new file mode 100644
index 000000000..6a24df0e0
--- /dev/null
+++ b/hw/xfree86/common/xf86Config.h
@@ -0,0 +1,27 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86Config.h,v 1.5 2000/02/24 05:36:50 tsi Exp $ */
+/*
+ * Copyright 1997 by The XFree86 Project, Inc
+ */
+
+#ifndef _xf86_config_h
+#define _xf86_config_h
+
+#ifdef HAVE_PARSER_DECLS
+/*
+ * global structure that holds the result of parsing the config file
+ */
+extern XF86ConfigPtr xf86configptr;
+#endif
+
+/*
+ * prototypes
+ */
+char ** xf86ModulelistFromConfig(pointer **);
+char ** xf86DriverlistFromConfig(void);
+char ** xf86DriverlistFromCompile(void);
+char ** xf86InputDriverlistFromConfig(void);
+char ** xf86InputDriverlistFromCompile(void);
+Bool xf86BuiltinInputDriver(const char *);
+Bool xf86HandleConfigFile(void);
+
+#endif /* _xf86_config_h */
diff --git a/hw/xfree86/common/xf86Configure.c b/hw/xfree86/common/xf86Configure.c
new file mode 100644
index 000000000..687730ea5
--- /dev/null
+++ b/hw/xfree86/common/xf86Configure.c
@@ -0,0 +1,997 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86Configure.c,v 3.78 2003/01/18 07:27:13 paulo Exp $ */
+/*
+ * Copyright 2000-2002 by Alan Hourihane, Flint Mountain, North Wales.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Alan Hourihane not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Alan Hourihane makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as is" without express or implied warranty.
+ *
+ * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Alan Hourihane, alanh@fairlite.demon.co.uk
+ *
+ */
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include "X.h"
+#include "Xmd.h"
+#include "os.h"
+#ifdef XFree86LOADER
+#include "loaderProcs.h"
+#endif
+#include "xf86.h"
+#include "xf86Config.h"
+#include "xf86Priv.h"
+#include "xf86PciData.h"
+#define IN_XSERVER
+#include "xf86Parser.h"
+#include "xf86tokens.h"
+#include "Configint.h"
+#include "vbe.h"
+#include "xf86DDC.h"
+#ifdef __sparc__
+#include "xf86Bus.h"
+#include "xf86Sbus.h"
+#endif
+#include "globals.h"
+
+typedef struct _DevToConfig {
+ GDevRec GDev;
+ pciVideoPtr pVideo;
+#ifdef __sparc__
+ sbusDevicePtr sVideo;
+#endif
+ int iDriver;
+} DevToConfigRec, *DevToConfigPtr;
+
+static DevToConfigPtr DevToConfig = NULL;
+static int nDevToConfig = 0, CurrentDriver;
+
+xf86MonPtr ConfiguredMonitor;
+Bool xf86DoConfigurePass1 = TRUE;
+Bool foundMouse = FALSE;
+
+#if defined(__UNIXOS2__)
+#define DFLT_MOUSE_DEV "mouse$"
+#define DFLT_MOUSE_PROTO "OS2Mouse"
+#elif defined(SCO)
+static char *DFLT_MOUSE_PROTO = "OSMouse";
+#elif defined(QNX4)
+static char *DFLT_MOUSE_PROTO = "OSMouse";
+static char *DFLT_MOUSE_DEV = "/dev/mouse";
+#elif defined(__QNXNTO__)
+static char *DFLT_MOUSE_PROTO = "OSMouse";
+static char *DFLT_MOUSE_DEV = "/dev/devi/mouse0";
+#elif defined(__FreeBSD__)
+static char *DFLT_MOUSE_DEV = "/dev/sysmouse";
+static char *DFLT_MOUSE_PROTO = "auto";
+#else
+static char *DFLT_MOUSE_DEV = "/dev/mouse";
+static char *DFLT_MOUSE_PROTO = "auto";
+#endif
+
+/*
+ * This is called by the driver, either through xf86Match???Instances() or
+ * directly. We allocate a GDevRec and fill it in as much as we can, letting
+ * the caller fill in the rest and/or change it as it sees fit.
+ */
+GDevPtr
+xf86AddBusDeviceToConfigure(const char *driver, BusType bus, void *busData, int chipset)
+{
+ int i, j;
+ pciVideoPtr pVideo = NULL;
+ Bool isPrimary = FALSE;
+
+ if (xf86DoProbe || !xf86DoConfigure || !xf86DoConfigurePass1)
+ return NULL;
+
+ /* Check for duplicates */
+ switch (bus) {
+ case BUS_PCI:
+ pVideo = (pciVideoPtr) busData;
+ for (i = 0; i < nDevToConfig; i++)
+ if (DevToConfig[i].pVideo &&
+ (DevToConfig[i].pVideo->bus == pVideo->bus) &&
+ (DevToConfig[i].pVideo->device == pVideo->device) &&
+ (DevToConfig[i].pVideo->func == pVideo->func))
+ return NULL;
+ isPrimary = xf86IsPrimaryPci(pVideo);
+ break;
+ case BUS_ISA:
+ /*
+ * This needs to be revisited as it doesn't allow for non-PCI
+ * multihead.
+ */
+ if (!xf86IsPrimaryIsa())
+ return NULL;
+ isPrimary = TRUE;
+ for (i = 0; i < nDevToConfig; i++)
+ if (!DevToConfig[i].pVideo)
+ return NULL;
+ break;
+#if defined(__sparc__) && !defined(__OpenBSD__)
+ case BUS_SBUS:
+ for (i = 0; i < nDevToConfig; i++)
+ if (DevToConfig[i].sVideo &&
+ DevToConfig[i].sVideo->fbNum == ((sbusDevicePtr) busData)->fbNum)
+ return NULL;
+ break;
+#endif
+ default:
+ return NULL;
+ }
+
+ /* Allocate new structure occurrence */
+ i = nDevToConfig++;
+ DevToConfig =
+ xnfrealloc(DevToConfig, nDevToConfig * sizeof(DevToConfigRec));
+#if 1 /* Doesn't work when a driver detects more than one adapter */
+ if ((i > 0) && isPrimary) {
+ memmove(DevToConfig + 1,DevToConfig,
+ (nDevToConfig - 1) * sizeof(DevToConfigRec));
+ i = 0;
+ }
+#endif
+ memset(DevToConfig + i, 0, sizeof(DevToConfigRec));
+
+# define NewDevice DevToConfig[i]
+
+ NewDevice.GDev.chipID = NewDevice.GDev.chipRev = NewDevice.GDev.irq = -1;
+
+ NewDevice.iDriver = CurrentDriver;
+
+ /* Fill in what we know, converting the driver name to lower case */
+ NewDevice.GDev.driver = xnfalloc(strlen(driver) + 1);
+ for (j = 0; (NewDevice.GDev.driver[j] = tolower(driver[j])); j++);
+
+ switch (bus) {
+ case BUS_PCI: {
+ const char *VendorName;
+ const char *CardName;
+ char busnum[8];
+
+ NewDevice.pVideo = pVideo;
+ xf86FindPciNamesByDevice(pVideo->vendor, pVideo->chipType,
+ NOVENDOR, NOSUBSYS,
+ &VendorName, &CardName, NULL, NULL);
+
+ if (!VendorName) {
+ VendorName = xnfalloc(15);
+ sprintf((char*)VendorName, "Unknown Vendor");
+ }
+
+ if (!CardName) {
+ CardName = xnfalloc(14);
+ sprintf((char*)CardName, "Unknown Board");
+ }
+
+ NewDevice.GDev.identifier =
+ xnfalloc(strlen(VendorName) + strlen(CardName) + 2);
+ sprintf(NewDevice.GDev.identifier, "%s %s", VendorName, CardName);
+
+ NewDevice.GDev.vendor = (char *)VendorName;
+ NewDevice.GDev.board = (char *)CardName;
+
+ NewDevice.GDev.busID = xnfalloc(16);
+ xf86FormatPciBusNumber(pVideo->bus, busnum);
+ sprintf(NewDevice.GDev.busID, "PCI:%s:%d:%d",
+ busnum, pVideo->device, pVideo->func);
+
+ NewDevice.GDev.chipID = pVideo->chipType;
+ NewDevice.GDev.chipRev = pVideo->chipRev;
+
+ if (chipset < 0)
+ chipset = (pVideo->vendor << 16) | pVideo->chipType;
+ }
+ break;
+ case BUS_ISA:
+ NewDevice.GDev.identifier = "ISA Adapter";
+ NewDevice.GDev.busID = "ISA";
+ break;
+#if defined(__sparc__) && !defined(__OpenBSD__)
+ case BUS_SBUS: {
+ char *promPath = NULL;
+ NewDevice.sVideo = (sbusDevicePtr) busData;
+ NewDevice.GDev.identifier = NewDevice.sVideo->descr;
+ if (sparcPromInit() >= 0) {
+ promPath = sparcPromNode2Pathname(&NewDevice.sVideo->node);
+ sparcPromClose();
+ }
+ if (promPath) {
+ NewDevice.GDev.busID = xnfalloc(strlen(promPath) + 6);
+ sprintf(NewDevice.GDev.busID, "SBUS:%s", promPath);
+ xfree(promPath);
+ } else {
+ NewDevice.GDev.busID = xnfalloc(12);
+ sprintf(NewDevice.GDev.busID, "SBUS:fb%d", NewDevice.sVideo->fbNum);
+ }
+ }
+ break;
+#endif
+ default:
+ break;
+ }
+
+ /* Get driver's available options */
+ if (xf86DriverList[CurrentDriver]->AvailableOptions)
+ NewDevice.GDev.options = (OptionInfoPtr)
+ (*xf86DriverList[CurrentDriver]->AvailableOptions)(chipset,
+ bus);
+
+ return &NewDevice.GDev;
+
+# undef NewDevice
+}
+
+/*
+ * Backwards compatibility
+ */
+GDevPtr
+xf86AddDeviceToConfigure(const char *driver, pciVideoPtr pVideo, int chipset)
+{
+ return xf86AddBusDeviceToConfigure(driver, pVideo ? BUS_PCI : BUS_ISA,
+ pVideo, chipset);
+}
+
+static XF86ConfInputPtr
+configureInputSection (void)
+{
+ XF86ConfInputPtr mouse = NULL;
+ parsePrologue (XF86ConfInputPtr, XF86ConfInputRec)
+
+ ptr->inp_identifier = "Keyboard0";
+ ptr->inp_driver = "keyboard";
+ ptr->list.next = NULL;
+
+ /* Crude mechanism to auto-detect mouse (os dependent) */
+ {
+ int fd;
+#if 0 && defined linux
+ /* Our autodetection code can do a better job */
+ int len;
+ char path[32];
+
+ if ((len = readlink(DFLT_MOUSE_DEV, path, sizeof(path) - 1)) > 0) {
+ path[len] = '\0';
+ if (strstr(path, "psaux") != NULL)
+ DFLT_MOUSE_PROTO = "PS/2";
+ }
+#endif
+#ifdef WSCONS_SUPPORT
+ fd = open("/dev/wsmouse", 0);
+ if (fd > 0) {
+ DFLT_MOUSE_DEV = "/dev/wsmouse";
+ DFLT_MOUSE_PROTO = "wsmouse";
+ close(fd);
+ }
+#endif
+
+#ifndef SCO
+ fd = open(DFLT_MOUSE_DEV, 0);
+ if (fd != -1) {
+ foundMouse = TRUE;
+ close(fd);
+ }
+#else
+ foundMouse = TRUE;
+#endif
+ }
+
+ mouse = xf86confmalloc(sizeof(XF86ConfInputRec));
+ memset((XF86ConfInputPtr)mouse,0,sizeof(XF86ConfInputRec));
+ mouse->inp_identifier = "Mouse0";
+ mouse->inp_driver = "mouse";
+ mouse->inp_option_lst =
+ xf86addNewOption(mouse->inp_option_lst, "Protocol", DFLT_MOUSE_PROTO);
+#ifndef SCO
+ mouse->inp_option_lst =
+ xf86addNewOption(mouse->inp_option_lst, "Device", DFLT_MOUSE_DEV);
+#endif
+ ptr = (XF86ConfInputPtr)xf86addListItem((glp)ptr, (glp)mouse);
+ return ptr;
+}
+
+static XF86ConfDRIPtr
+configureDRISection (void)
+{
+#ifdef NOTYET
+ parsePrologue (XF86ConfDRIPtr, XF86ConfDRIRec)
+
+ return ptr;
+#else
+ return NULL;
+#endif
+}
+
+static XF86ConfVendorPtr
+configureVendorSection (void)
+{
+ parsePrologue (XF86ConfVendorPtr, XF86ConfVendorRec)
+
+ return NULL;
+#if 0
+ return ptr;
+#endif
+}
+
+static XF86ConfScreenPtr
+configureScreenSection (int screennum)
+{
+ int i;
+ int depths[] = { 1, 4, 8, 15, 16, 24/*, 32*/ };
+ parsePrologue (XF86ConfScreenPtr, XF86ConfScreenRec)
+
+ ptr->scrn_identifier = xf86confmalloc(18);
+ sprintf(ptr->scrn_identifier, "Screen%d", screennum);
+ ptr->scrn_monitor_str = xf86confmalloc(19);
+ sprintf(ptr->scrn_monitor_str, "Monitor%d", screennum);
+ ptr->scrn_device_str = xf86confmalloc(16);
+ sprintf(ptr->scrn_device_str, "Card%d", screennum);
+
+ for (i=0; i<sizeof(depths)/sizeof(depths[0]); i++)
+ {
+ XF86ConfDisplayPtr display;
+
+ display = xf86confmalloc(sizeof(XF86ConfDisplayRec));
+ memset((XF86ConfDisplayPtr)display,0,sizeof(XF86ConfDisplayRec));
+ display->disp_depth = depths[i];
+ display->disp_black.red = display->disp_white.red = -1;
+ display->disp_black.green = display->disp_white.green = -1;
+ display->disp_black.blue = display->disp_white.blue = -1;
+ ptr->scrn_display_lst = (XF86ConfDisplayPtr)xf86addListItem(
+ (glp)ptr->scrn_display_lst, (glp)display);
+ }
+
+ return ptr;
+}
+
+static const char*
+optionTypeToSting(OptionValueType type)
+{
+ switch (type) {
+ case OPTV_NONE:
+ return "";
+ case OPTV_INTEGER:
+ return "<i>";
+ case OPTV_STRING:
+ return "<str>";
+ case OPTV_ANYSTR:
+ return "[<str>]";
+ case OPTV_REAL:
+ return "<f>";
+ case OPTV_BOOLEAN:
+ return "[<bool>]";
+ case OPTV_FREQ:
+ return "<freq>";
+ default:
+ return "";
+ }
+}
+
+static XF86ConfDevicePtr
+configureDeviceSection (int screennum)
+{
+ char identifier[16];
+ OptionInfoPtr p;
+ int i = 0;
+#ifdef DO_FBDEV_PROBE
+ Bool foundFBDEV = FALSE;
+#endif
+ parsePrologue (XF86ConfDevicePtr, XF86ConfDeviceRec)
+
+ /* Move device info to parser structure */
+ sprintf(identifier, "Card%d", screennum);
+ ptr->dev_identifier = strdup(identifier);
+/* ptr->dev_identifier = DevToConfig[screennum].GDev.identifier;*/
+ ptr->dev_vendor = DevToConfig[screennum].GDev.vendor;
+ ptr->dev_board = DevToConfig[screennum].GDev.board;
+ ptr->dev_chipset = DevToConfig[screennum].GDev.chipset;
+ ptr->dev_busid = DevToConfig[screennum].GDev.busID;
+ ptr->dev_driver = DevToConfig[screennum].GDev.driver;
+ ptr->dev_ramdac = DevToConfig[screennum].GDev.ramdac;
+ for (i = 0; (i < MAXDACSPEEDS) && (i < CONF_MAXDACSPEEDS); i++)
+ ptr->dev_dacSpeeds[i] = DevToConfig[screennum].GDev.dacSpeeds[i];
+ ptr->dev_videoram = DevToConfig[screennum].GDev.videoRam;
+ ptr->dev_textclockfreq = DevToConfig[screennum].GDev.textClockFreq;
+ ptr->dev_bios_base = DevToConfig[screennum].GDev.BiosBase;
+ ptr->dev_mem_base = DevToConfig[screennum].GDev.MemBase;
+ ptr->dev_io_base = DevToConfig[screennum].GDev.IOBase;
+ ptr->dev_clockchip = DevToConfig[screennum].GDev.clockchip;
+ for (i = 0; (i < MAXCLOCKS) && (i < DevToConfig[screennum].GDev.numclocks); i++)
+ ptr->dev_clock[i] = DevToConfig[screennum].GDev.clock[i];
+ ptr->dev_clocks = i;
+ ptr->dev_chipid = DevToConfig[screennum].GDev.chipID;
+ ptr->dev_chiprev = DevToConfig[screennum].GDev.chipRev;
+ ptr->dev_irq = DevToConfig[screennum].GDev.irq;
+
+ /* Make sure older drivers don't segv */
+ if (DevToConfig[screennum].GDev.options) {
+ /* Fill in the available driver options for people to use */
+ const char *descrip =
+ " ### Available Driver options are:-\n"
+ " ### Values: <i>: integer, <f>: float, "
+ "<bool>: \"True\"/\"False\",\n"
+ " ### <string>: \"String\", <freq>: \"<f> Hz/kHz/MHz\"\n"
+ " ### [arg]: arg optional\n";
+ ptr->dev_comment = xstrdup(descrip);
+ if (ptr->dev_comment) {
+ for (p = DevToConfig[screennum].GDev.options;
+ p->name != NULL; p++) {
+ char *p_e;
+ const char *prefix = " #Option ";
+ const char *middle = " \t# ";
+ const char *suffix = "\n";
+ const char *opttype = optionTypeToSting(p->type);
+ char *optname;
+ int len = strlen(ptr->dev_comment) + strlen(prefix) +
+ strlen(middle) + strlen(suffix) + 1;
+
+ optname = xalloc(strlen(p->name) + 2 + 1);
+ if (!optname)
+ break;
+ sprintf(optname, "\"%s\"", p->name);
+
+ len += max(20, strlen(optname));
+ len += strlen(opttype);
+
+ ptr->dev_comment = xrealloc(ptr->dev_comment, len);
+ if (!ptr->dev_comment)
+ break;
+ p_e = ptr->dev_comment + strlen(ptr->dev_comment);
+ sprintf(p_e, "%s%-20s%s%s%s", prefix, optname, middle,
+ opttype, suffix);
+ xfree(optname);
+ }
+ }
+ }
+
+#ifdef DO_FBDEV_PROBE
+ /* Crude mechanism to auto-detect fbdev (os dependent) */
+ /* Skip it for now. Options list it anyway, and we can't
+ * determine which screen/driver this belongs too anyway. */
+ {
+ int fd;
+
+ fd = open("/dev/fb0", 0);
+ if (fd != -1) {
+ foundFBDEV = TRUE;
+ close(fd);
+ }
+ }
+
+ if (foundFBDEV) {
+ XF86OptionPtr fbdev;
+
+ fbdev = xf86confmalloc(sizeof(XF86OptionRec));
+ memset((XF86OptionPtr)fbdev,0,sizeof(XF86OptionRec));
+ fbdev->opt_name = "UseFBDev";
+ fbdev->opt_val = "ON";
+ ptr->dev_option_lst = (XF86OptionPtr)xf86addListItem(
+ (glp)ptr->dev_option_lst, (glp)fbdev);
+ }
+#endif
+
+ return ptr;
+}
+
+static XF86ConfLayoutPtr
+configureLayoutSection (void)
+{
+ int scrnum = 0;
+ parsePrologue (XF86ConfLayoutPtr, XF86ConfLayoutRec)
+
+ ptr->lay_identifier = "XFree86 Configured";
+
+ {
+ XF86ConfInputrefPtr iptr;
+
+ iptr = xf86confmalloc (sizeof (XF86ConfInputrefRec));
+ iptr->list.next = NULL;
+ iptr->iref_option_lst = NULL;
+ iptr->iref_inputdev_str = "Mouse0";
+ iptr->iref_option_lst =
+ xf86addNewOption (iptr->iref_option_lst, "CorePointer", NULL);
+ ptr->lay_input_lst = (XF86ConfInputrefPtr)
+ xf86addListItem ((glp) ptr->lay_input_lst, (glp) iptr);
+ }
+
+ {
+ XF86ConfInputrefPtr iptr;
+
+ iptr = xf86confmalloc (sizeof (XF86ConfInputrefRec));
+ iptr->list.next = NULL;
+ iptr->iref_option_lst = NULL;
+ iptr->iref_inputdev_str = "Keyboard0";
+ iptr->iref_option_lst =
+ xf86addNewOption (iptr->iref_option_lst, "CoreKeyboard", NULL);
+ ptr->lay_input_lst = (XF86ConfInputrefPtr)
+ xf86addListItem ((glp) ptr->lay_input_lst, (glp) iptr);
+ }
+
+ for (scrnum = 0; scrnum < nDevToConfig; scrnum++) {
+ XF86ConfAdjacencyPtr aptr;
+
+ aptr = xf86confmalloc (sizeof (XF86ConfAdjacencyRec));
+ aptr->list.next = NULL;
+ aptr->adj_x = 0;
+ aptr->adj_y = 0;
+ aptr->adj_scrnum = scrnum;
+ aptr->adj_screen_str = xnfalloc(18);
+ sprintf(aptr->adj_screen_str, "Screen%d", scrnum);
+ if (scrnum == 0) {
+ aptr->adj_where = CONF_ADJ_ABSOLUTE;
+ aptr->adj_refscreen = NULL;
+ }
+ else {
+ aptr->adj_where = CONF_ADJ_RIGHTOF;
+ aptr->adj_refscreen = xnfalloc(18);
+ sprintf(aptr->adj_refscreen, "Screen%d", scrnum - 1);
+ }
+ ptr->lay_adjacency_lst =
+ (XF86ConfAdjacencyPtr)xf86addListItem((glp)ptr->lay_adjacency_lst,
+ (glp)aptr);
+ }
+
+ return ptr;
+}
+
+static XF86ConfModesPtr
+configureModesSection (void)
+{
+#ifdef NOTYET
+ parsePrologue (XF86ConfModesPtr, XF86ConfModesRec)
+
+ return ptr;
+#else
+ return NULL;
+#endif
+}
+
+static XF86ConfVideoAdaptorPtr
+configureVideoAdaptorSection (void)
+{
+ parsePrologue (XF86ConfVideoAdaptorPtr, XF86ConfVideoAdaptorRec)
+
+ return NULL;
+#if 0
+ return ptr;
+#endif
+}
+
+static XF86ConfFlagsPtr
+configureFlagsSection (void)
+{
+ parsePrologue (XF86ConfFlagsPtr, XF86ConfFlagsRec)
+
+ return ptr;
+}
+
+static XF86ConfModulePtr
+configureModuleSection (void)
+{
+#ifdef XFree86LOADER
+ char **elist, **el;
+ /* Find the list of extension modules. */
+ const char *esubdirs[] = {
+ "extensions",
+ NULL
+ };
+ const char *fsubdirs[] = {
+ "fonts",
+ NULL
+ };
+#endif
+ parsePrologue (XF86ConfModulePtr, XF86ConfModuleRec)
+
+#ifdef XFree86LOADER
+ elist = LoaderListDirs(esubdirs, NULL);
+ if (elist) {
+ for (el = elist; *el; el++) {
+ XF86LoadPtr module;
+
+ module = xf86confmalloc(sizeof(XF86LoadRec));
+ memset((XF86LoadPtr)module,0,sizeof(XF86LoadRec));
+ module->load_name = *el;
+ /* HACK, remove GLcore, glx, loads it as a submodule */
+ if (strcmp(*el, "GLcore"))
+ ptr->mod_load_lst = (XF86LoadPtr)xf86addListItem(
+ (glp)ptr->mod_load_lst, (glp)module);
+ }
+ xfree(elist);
+ }
+
+ /* Process list of font backends separately to include only required ones */
+ elist = LoaderListDirs(fsubdirs, NULL);
+ if (elist) {
+ for (el = elist; *el; el++) {
+ XF86LoadPtr module;
+
+ module = xf86confmalloc(sizeof(XF86LoadRec));
+ memset((XF86LoadPtr)module,0,sizeof(XF86LoadRec));
+ module->load_name = *el;
+
+ /* Add only those font backends which are referenced by fontpath */
+ /* 'strstr(dFP,"/dir")' is meant as 'dFP =~ m(/dir\W)' */
+ if (defaultFontPath && (
+ (strcmp(*el, "xtt") == 0 &&
+ strstr(defaultFontPath, "/TrueType")) ||
+ (strcmp(*el, "type1") == 0 &&
+ strstr(defaultFontPath, "/Type1")) ||
+ (strcmp(*el, "speedo") == 0 &&
+ strstr(defaultFontPath, "/Speedo"))))
+ ptr->mod_load_lst = (XF86LoadPtr)xf86addListItem(
+ (glp)ptr->mod_load_lst, (glp)module);
+ }
+ xfree(elist);
+ }
+#endif
+
+ return ptr;
+}
+
+static XF86ConfFilesPtr
+configureFilesSection (void)
+{
+ parsePrologue (XF86ConfFilesPtr, XF86ConfFilesRec)
+
+#ifdef XFree86LOADER
+ if (xf86ModulePath)
+ ptr->file_modulepath = strdup(xf86ModulePath);
+#endif
+ if (defaultFontPath)
+ ptr->file_fontpath = strdup(defaultFontPath);
+ if (rgbPath)
+ ptr->file_rgbpath = strdup(rgbPath);
+
+ return ptr;
+}
+
+static XF86ConfMonitorPtr
+configureMonitorSection (int screennum)
+{
+ parsePrologue (XF86ConfMonitorPtr, XF86ConfMonitorRec)
+
+ ptr->mon_identifier = xf86confmalloc(19);
+ sprintf(ptr->mon_identifier, "Monitor%d", screennum);
+ ptr->mon_vendor = strdup("Monitor Vendor");
+ ptr->mon_modelname = strdup("Monitor Model");
+
+ return ptr;
+}
+
+static XF86ConfMonitorPtr
+configureDDCMonitorSection (int screennum)
+{
+ int i = 0;
+ int len, mon_width, mon_height;
+#define displaySizeMaxLen 80
+ char displaySize_string[displaySizeMaxLen];
+ int displaySizeLen;
+
+ parsePrologue (XF86ConfMonitorPtr, XF86ConfMonitorRec)
+
+ ptr->mon_identifier = xf86confmalloc(19);
+ sprintf(ptr->mon_identifier, "Monitor%d", screennum);
+ ptr->mon_vendor = strdup(ConfiguredMonitor->vendor.name);
+ ptr->mon_modelname = xf86confmalloc(12);
+ sprintf(ptr->mon_modelname, "%x", ConfiguredMonitor->vendor.prod_id);
+
+ /* features in centimetres, we want millimetres */
+ mon_width = 10 * ConfiguredMonitor->features.hsize ;
+ mon_height = 10 * ConfiguredMonitor->features.vsize ;
+
+#ifdef CONFIGURE_DISPLAYSIZE
+ ptr->mon_width = mon_width;
+ ptr->mon_height = mon_height;
+#else
+ if (mon_width && mon_height) {
+ /* when values available add DisplaySize option AS A COMMENT */
+
+ displaySizeLen = snprintf(displaySize_string, displaySizeMaxLen,
+ "\t#DisplaySize\t%5d %5d\t# mm\n",
+ mon_width, mon_height);
+
+ if (displaySizeLen>0 && displaySizeLen<displaySizeMaxLen) {
+ if (ptr->mon_comment) {
+ len = strlen(ptr->mon_comment);
+ } else {
+ len = 0;
+ }
+ if ((ptr->mon_comment =
+ xf86confrealloc(ptr->mon_comment,
+ len+strlen(displaySize_string)))) {
+ strcpy(ptr->mon_comment + len, displaySize_string);
+ }
+ }
+ }
+#endif /* def CONFIGURE_DISPLAYSIZE */
+
+ for (i=0;i<4;i++) {
+ switch (ConfiguredMonitor->det_mon[i].type) {
+ case DT:
+ case DS_STD_TIMINGS:
+ case DS_WHITE_P:
+ break;
+ case DS_NAME:
+ ptr->mon_modelname = xf86confrealloc(ptr->mon_modelname,
+ strlen((char*)(ConfiguredMonitor->det_mon[i].section.name))
+ + 1);
+ strcpy(ptr->mon_modelname,
+ (char*)(ConfiguredMonitor->det_mon[i].section.name));
+ break;
+ case DS_ASCII_STR:
+ case DS_SERIAL:
+ case DS_RANGES:
+ default:
+ break;
+ }
+ }
+
+ if (ConfiguredMonitor->features.dpms) {
+ ptr->mon_option_lst = xf86addNewOption(ptr->mon_option_lst, "DPMS", NULL);
+ }
+
+ return ptr;
+}
+
+void
+DoConfigure()
+{
+ int i,j, screennum = -1;
+ char *home = NULL;
+ char *filename = NULL;
+ XF86ConfigPtr xf86config = NULL;
+ char **vlist, **vl;
+ int *dev2screen;
+
+ vlist = xf86DriverlistFromCompile();
+
+ if (!vlist) {
+ ErrorF("Missing output drivers. Configuration failed.\n");
+ goto bail;
+ }
+
+ ErrorF("List of video drivers:\n");
+ for (vl = vlist; *vl; vl++)
+ ErrorF("\t%s\n", *vl);
+
+#ifdef XFree86LOADER
+ /* Load all the drivers that were found. */
+ xf86LoadModules(vlist, NULL);
+#endif /* XFree86LOADER */
+
+ xfree(vlist);
+
+ /* Disable PCI devices */
+ xf86ResourceBrokerInit();
+ xf86AccessInit();
+ xf86FindPrimaryDevice();
+
+ /* Create XF86Config file structure */
+ xf86config = malloc(sizeof(XF86ConfigRec));
+ memset ((XF86ConfigPtr)xf86config, 0, sizeof(XF86ConfigRec));
+ xf86config->conf_device_lst = NULL;
+ xf86config->conf_screen_lst = NULL;
+ xf86config->conf_monitor_lst = NULL;
+
+ /* Call all of the probe functions, reporting the results. */
+ for (CurrentDriver = 0; CurrentDriver < xf86NumDrivers; CurrentDriver++) {
+
+ if (xf86DriverList[CurrentDriver]->Probe == NULL) continue;
+
+ if ((*xf86DriverList[CurrentDriver]->Probe)(
+ xf86DriverList[CurrentDriver], PROBE_DETECT) &&
+ xf86DriverList[CurrentDriver]->Identify)
+ (*xf86DriverList[CurrentDriver]->Identify)(0);
+ }
+
+ if (nDevToConfig <= 0) {
+ ErrorF("No devices to configure. Configuration failed.\n");
+ goto bail;
+ }
+
+ /* Add device, monitor and screen sections for detected devices */
+ for (screennum = 0; screennum < nDevToConfig; screennum++) {
+ XF86ConfDevicePtr DevicePtr;
+ XF86ConfMonitorPtr MonitorPtr;
+ XF86ConfScreenPtr ScreenPtr;
+
+ DevicePtr = configureDeviceSection(screennum);
+ xf86config->conf_device_lst = (XF86ConfDevicePtr)xf86addListItem(
+ (glp)xf86config->conf_device_lst, (glp)DevicePtr);
+ MonitorPtr = configureMonitorSection(screennum);
+ xf86config->conf_monitor_lst = (XF86ConfMonitorPtr)xf86addListItem(
+ (glp)xf86config->conf_monitor_lst, (glp)MonitorPtr);
+ ScreenPtr = configureScreenSection(screennum);
+ xf86config->conf_screen_lst = (XF86ConfScreenPtr)xf86addListItem(
+ (glp)xf86config->conf_screen_lst, (glp)ScreenPtr);
+ }
+
+ xf86config->conf_files = configureFilesSection();
+ xf86config->conf_modules = configureModuleSection();
+ xf86config->conf_flags = configureFlagsSection();
+ xf86config->conf_videoadaptor_lst = configureVideoAdaptorSection();
+ xf86config->conf_modes_lst = configureModesSection();
+ xf86config->conf_vendor_lst = configureVendorSection();
+ xf86config->conf_dri = configureDRISection();
+ xf86config->conf_input_lst = configureInputSection();
+ xf86config->conf_layout_lst = configureLayoutSection();
+
+ if (!(home = getenv("HOME")))
+ home = "/";
+ {
+#ifdef __UNIXOS2__
+#define PATH_MAX 2048
+#endif
+#if defined(SCO) || defined(SCO325)
+#define PATH_MAX 1024
+#endif
+ const char* configfile = XF86CONFIGFILE".new";
+ char homebuf[PATH_MAX];
+ /* getenv might return R/O memory, as with OS/2 */
+ strncpy(homebuf,home,PATH_MAX-1);
+ homebuf[PATH_MAX-1] = '\0';
+ home = homebuf;
+ if (!(filename =
+ (char *)ALLOCATE_LOCAL(strlen(home) +
+ strlen(configfile) + 3)))
+
+ if (home[0] == '/' && home[1] == '\0')
+ home[0] = '\0';
+#ifndef QNX4
+ sprintf(filename, "%s/%s", home,configfile);
+#else
+ sprintf(filename, "//%d%s/%s", getnid(),home,configfile);
+#endif
+
+ }
+
+ xf86writeConfigFile(filename, xf86config);
+
+ xf86DoConfigurePass1 = FALSE;
+ /* Try to get DDC information filled in */
+ xf86ConfigFile = filename;
+ if (!xf86HandleConfigFile()) {
+ goto bail;
+ }
+
+ xf86DoConfigurePass1 = FALSE;
+
+ dev2screen = xnfcalloc(1,xf86NumDrivers*sizeof(int));
+
+ {
+ Bool *driverProbed = xnfcalloc(1,xf86NumDrivers*sizeof(Bool));
+ for (screennum = 0; screennum < nDevToConfig; screennum++) {
+ int k,l,n,oldNumScreens;
+
+ i = DevToConfig[screennum].iDriver;
+
+ if (driverProbed[i]) continue;
+ driverProbed[i] = TRUE;
+
+ oldNumScreens = xf86NumScreens;
+
+ (*xf86DriverList[i]->Probe)(xf86DriverList[i], 0);
+
+ /* reorder */
+ k = screennum > 0 ? screennum : 1;
+ for (l = oldNumScreens; l < xf86NumScreens; l++) {
+ /* is screen primary? */
+ Bool primary = FALSE;
+ for (n = 0; n<xf86Screens[l]->numEntities; n++) {
+ if (xf86IsEntityPrimary(xf86Screens[l]->entityList[n])) {
+ dev2screen[0] = l;
+ primary = TRUE;
+ break;
+ }
+ }
+ if (primary) continue;
+ /* not primary: assign it to next device of same driver */
+ /*
+ * NOTE: we assume that devices in DevToConfig
+ * and xf86Screens[] have the same order except
+ * for the primary device which always comes first.
+ */
+ for (; k < nDevToConfig; k++) {
+ if (DevToConfig[k].iDriver == i) {
+ dev2screen[k++] = l;
+ break;
+ }
+ }
+ }
+ xf86SetPciVideo(NULL,NONE);
+ }
+ xfree(driverProbed);
+ }
+
+
+ if (nDevToConfig != xf86NumScreens) {
+ ErrorF("Number of created screens does not match number of detected"
+ " devices.\n Configuration failed.\n");
+ goto bail;
+ }
+
+ xf86PostProbe();
+ xf86EntityInit();
+
+ for (j = 0; j < xf86NumScreens; j++) {
+ xf86Screens[j]->scrnIndex = j;
+ }
+
+ xf86freeMonitorList(xf86config->conf_monitor_lst);
+ xf86config->conf_monitor_lst = NULL;
+ xf86freeScreenList(xf86config->conf_screen_lst);
+ xf86config->conf_screen_lst = NULL;
+ for (j = 0; j < xf86NumScreens; j++) {
+ XF86ConfMonitorPtr MonitorPtr;
+ XF86ConfScreenPtr ScreenPtr;
+
+ ConfiguredMonitor = NULL;
+
+ xf86EnableAccess(xf86Screens[dev2screen[j]]);
+ if ((*xf86Screens[dev2screen[j]]->PreInit)(xf86Screens[dev2screen[j]],
+ PROBE_DETECT) &&
+ ConfiguredMonitor) {
+ MonitorPtr = configureDDCMonitorSection(j);
+ } else {
+ MonitorPtr = configureMonitorSection(j);
+ }
+ ScreenPtr = configureScreenSection(j);
+ xf86config->conf_monitor_lst = (XF86ConfMonitorPtr)xf86addListItem(
+ (glp)xf86config->conf_monitor_lst, (glp)MonitorPtr);
+ xf86config->conf_screen_lst = (XF86ConfScreenPtr)xf86addListItem(
+ (glp)xf86config->conf_screen_lst, (glp)ScreenPtr);
+ }
+
+ xf86writeConfigFile(filename, xf86config);
+
+ ErrorF("\n");
+
+#ifdef SCO
+ ErrorF("\nXFree86 is using the kernel event driver to access the mouse.\n"
+ "If you wish to use the internal XFree86 mouse drivers, please\n"
+ "edit the file and correct the Device.\n");
+#else /* !SCO */
+ if (!foundMouse) {
+ ErrorF("\nXFree86 is not able to detect your mouse.\n"
+ "Edit the file and correct the Device.\n");
+ } else {
+#ifndef __UNIXOS2__ /* OS/2 definitely has a mouse */
+ ErrorF("\nXFree86 detected your mouse at device %s.\n"
+ "Please check your config if the mouse is still not\n"
+ "operational, as by default XFree86 tries to autodetect\n"
+ "the protocol.\n",DFLT_MOUSE_DEV);
+#endif
+ }
+#endif /* !SCO */
+
+ if (xf86NumScreens > 1) {
+ ErrorF("\nXFree86 has configured a multihead system, please check your config.\n");
+ }
+
+ ErrorF("\nYour XF86Config file is %s\n\n", filename);
+ ErrorF("To test the server, run 'XFree86 -xf86config %s'\n\n", filename);
+
+bail:
+ OsCleanup();
+ AbortDDX();
+ fflush(stderr);
+ exit(0);
+}
diff --git a/hw/xfree86/common/xf86DGA.c b/hw/xfree86/common/xf86DGA.c
new file mode 100644
index 000000000..1ad8b42ff
--- /dev/null
+++ b/hw/xfree86/common/xf86DGA.c
@@ -0,0 +1,1181 @@
+/*
+ Copyright (c) 1999 - The XFree86 Project, Inc.
+
+ Written by Mark Vojkovich
+*/
+/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86DGA.c,v 1.46 2002/12/03 18:17:40 tsi Exp $ */
+
+#include "xf86.h"
+#include "xf86str.h"
+#include "xf86Priv.h"
+#include "dgaproc.h"
+#include "xf86dgastr.h"
+#include "colormapst.h"
+#include "pixmapstr.h"
+#include "inputstr.h"
+#include "globals.h"
+#include "servermd.h"
+#include "micmap.h"
+#ifdef XKB
+#include "XKBsrv.h"
+#endif
+#include "xf86Xinput.h"
+
+static unsigned long DGAGeneration = 0;
+static int DGAScreenIndex = -1;
+
+static Bool DGACloseScreen(int i, ScreenPtr pScreen);
+static void DGADestroyColormap(ColormapPtr pmap);
+static void DGAInstallColormap(ColormapPtr pmap);
+static void DGAUninstallColormap(ColormapPtr pmap);
+
+static void
+DGACopyModeInfo(
+ DGAModePtr mode,
+ XDGAModePtr xmode
+);
+
+#if defined(XFree86LOADER) || !defined(XFreeXDGA)
+int *XDGAEventBase = NULL;
+#else
+int *XDGAEventBase = &DGAEventBase;
+#endif
+
+#define DGA_GET_SCREEN_PRIV(pScreen) \
+ ((DGAScreenPtr)((pScreen)->devPrivates[DGAScreenIndex].ptr))
+
+
+typedef struct _FakedVisualList{
+ Bool free;
+ VisualPtr pVisual;
+ struct _FakedVisualList *next;
+} FakedVisualList;
+
+
+typedef struct {
+ ScrnInfoPtr pScrn;
+ int numModes;
+ DGAModePtr modes;
+ CloseScreenProcPtr CloseScreen;
+ DestroyColormapProcPtr DestroyColormap;
+ InstallColormapProcPtr InstallColormap;
+ UninstallColormapProcPtr UninstallColormap;
+ DGADevicePtr current;
+ DGAFunctionPtr funcs;
+ int input;
+ ClientPtr client;
+ int pixmapMode;
+ FakedVisualList *fakedVisuals;
+ ColormapPtr dgaColormap;
+ ColormapPtr savedColormap;
+ Bool grabMouse;
+ Bool grabKeyboard;
+} DGAScreenRec, *DGAScreenPtr;
+
+
+Bool
+DGAInit(
+ ScreenPtr pScreen,
+ DGAFunctionPtr funcs,
+ DGAModePtr modes,
+ int num
+){
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ DGAScreenPtr pScreenPriv;
+ int i;
+
+ if(!funcs || !funcs->SetMode || !funcs->OpenFramebuffer)
+ return FALSE;
+
+ if(!modes || num <= 0)
+ return FALSE;
+
+ if(DGAGeneration != serverGeneration) {
+ if((DGAScreenIndex = AllocateScreenPrivateIndex()) < 0)
+ return FALSE;
+ DGAGeneration = serverGeneration;
+ }
+
+ if(!(pScreenPriv = (DGAScreenPtr)xalloc(sizeof(DGAScreenRec))))
+ return FALSE;
+
+ pScreenPriv->pScrn = pScrn;
+ pScreenPriv->numModes = num;
+ pScreenPriv->modes = modes;
+ pScreenPriv->current = NULL;
+
+ pScreenPriv->funcs = funcs;
+ pScreenPriv->input = 0;
+ pScreenPriv->client = NULL;
+ pScreenPriv->fakedVisuals = NULL;
+ pScreenPriv->dgaColormap = NULL;
+ pScreenPriv->savedColormap = NULL;
+ pScreenPriv->grabMouse = FALSE;
+ pScreenPriv->grabKeyboard = FALSE;
+
+ for(i = 0; i < num; i++)
+ modes[i].num = i + 1;
+
+#ifdef PANORAMIX
+ if(!noPanoramiXExtension)
+ for(i = 0; i < num; i++)
+ modes[i].flags &= ~DGA_PIXMAP_AVAILABLE;
+#endif
+
+
+ pScreen->devPrivates[DGAScreenIndex].ptr = (pointer)pScreenPriv;
+ pScreenPriv->CloseScreen = pScreen->CloseScreen;
+ pScreen->CloseScreen = DGACloseScreen;
+ pScreenPriv->DestroyColormap = pScreen->DestroyColormap;
+ pScreen->DestroyColormap = DGADestroyColormap;
+ pScreenPriv->InstallColormap = pScreen->InstallColormap;
+ pScreen->InstallColormap = DGAInstallColormap;
+ pScreenPriv->UninstallColormap = pScreen->UninstallColormap;
+ pScreen->UninstallColormap = DGAUninstallColormap;
+
+ /*
+ * This is now set in InitOutput().
+ *
+ pScrn->SetDGAMode = xf86SetDGAMode;
+ */
+
+ return TRUE;
+}
+
+
+static void
+FreeMarkedVisuals(ScreenPtr pScreen)
+{
+ DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen);
+ FakedVisualList *prev, *curr, *tmp;
+
+ if(!pScreenPriv->fakedVisuals)
+ return;
+
+ prev = NULL;
+ curr = pScreenPriv->fakedVisuals;
+
+ while(curr) {
+ if(curr->free) {
+ tmp = curr;
+ curr = curr->next;
+ if(prev)
+ prev->next = curr;
+ else
+ pScreenPriv->fakedVisuals = curr;
+ xfree(tmp->pVisual);
+ xfree(tmp);
+ } else {
+ prev = curr;
+ curr = curr->next;
+ }
+ }
+}
+
+
+static Bool
+DGACloseScreen(int i, ScreenPtr pScreen)
+{
+ DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen);
+
+ FreeMarkedVisuals(pScreen);
+
+ pScreen->CloseScreen = pScreenPriv->CloseScreen;
+ pScreen->DestroyColormap = pScreenPriv->DestroyColormap;
+ pScreen->InstallColormap = pScreenPriv->InstallColormap;
+ pScreen->UninstallColormap = pScreenPriv->UninstallColormap;
+
+ /* DGAShutdown() should have ensured that no DGA
+ screen were active by here */
+
+ xfree(pScreenPriv);
+
+ return((*pScreen->CloseScreen)(i, pScreen));
+}
+
+
+static void
+DGADestroyColormap(ColormapPtr pmap)
+{
+ ScreenPtr pScreen = pmap->pScreen;
+ DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen);
+ VisualPtr pVisual = pmap->pVisual;
+
+ if(pScreenPriv->fakedVisuals) {
+ FakedVisualList *curr = pScreenPriv->fakedVisuals;
+
+ while(curr) {
+ if(curr->pVisual == pVisual) {
+ /* We can't get rid of them yet since FreeColormap
+ still needs the pVisual during the cleanup */
+ curr->free = TRUE;
+ break;
+ }
+ curr = curr->next;
+ }
+ }
+
+ if(pScreenPriv->DestroyColormap) {
+ pScreen->DestroyColormap = pScreenPriv->DestroyColormap;
+ (*pScreen->DestroyColormap)(pmap);
+ pScreen->DestroyColormap = DGADestroyColormap;
+ }
+}
+
+
+static void
+DGAInstallColormap(ColormapPtr pmap)
+{
+ ScreenPtr pScreen = pmap->pScreen;
+ DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen);
+
+ if(pScreenPriv->current && pScreenPriv->dgaColormap) {
+ if (pmap != pScreenPriv->dgaColormap) {
+ pScreenPriv->savedColormap = pmap;
+ pmap = pScreenPriv->dgaColormap;
+ }
+ }
+
+ pScreen->InstallColormap = pScreenPriv->InstallColormap;
+ (*pScreen->InstallColormap)(pmap);
+ pScreen->InstallColormap = DGAInstallColormap;
+}
+
+static void
+DGAUninstallColormap(ColormapPtr pmap)
+{
+ ScreenPtr pScreen = pmap->pScreen;
+ DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen);
+
+ if(pScreenPriv->current && pScreenPriv->dgaColormap) {
+ if (pmap == pScreenPriv->dgaColormap) {
+ pScreenPriv->dgaColormap = NULL;
+ }
+ }
+
+ pScreen->UninstallColormap = pScreenPriv->UninstallColormap;
+ (*pScreen->UninstallColormap)(pmap);
+ pScreen->UninstallColormap = DGAUninstallColormap;
+}
+
+int
+xf86SetDGAMode(
+ int index,
+ int num,
+ DGADevicePtr devRet
+){
+ ScreenPtr pScreen = screenInfo.screens[index];
+ DGAScreenPtr pScreenPriv;
+ ScrnInfoPtr pScrn;
+ DGADevicePtr device;
+ PixmapPtr pPix = NULL;
+ DGAModePtr pMode = NULL;
+
+ /* First check if DGAInit was successful on this screen */
+ if (DGAScreenIndex < 0)
+ return BadValue;
+ pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen);
+ if (!pScreenPriv)
+ return BadValue;
+ pScrn = pScreenPriv->pScrn;
+
+ if(!num) {
+ if(pScreenPriv->current) {
+ PixmapPtr oldPix = pScreenPriv->current->pPix;
+ if(oldPix) {
+ if(oldPix->drawable.id)
+ FreeResource(oldPix->drawable.id, RT_NONE);
+ else
+ (*pScreen->DestroyPixmap)(oldPix);
+ }
+ xfree(pScreenPriv->current);
+ pScreenPriv->current = NULL;
+ pScrn->vtSema = TRUE;
+ (*pScreenPriv->funcs->SetMode)(pScrn, NULL);
+ if(pScreenPriv->savedColormap) {
+ (*pScreen->InstallColormap)(pScreenPriv->savedColormap);
+ pScreenPriv->savedColormap = NULL;
+ }
+ pScreenPriv->dgaColormap = NULL;
+ (*pScrn->EnableDisableFBAccess)(index, TRUE);
+
+ FreeMarkedVisuals(pScreen);
+ }
+
+ pScreenPriv->grabMouse = FALSE;
+ pScreenPriv->grabKeyboard = FALSE;
+
+ return Success;
+ }
+
+ if(!pScrn->vtSema && !pScreenPriv->current) /* Really switched away */
+ return BadAlloc;
+
+ if((num > 0) && (num <= pScreenPriv->numModes))
+ pMode = &(pScreenPriv->modes[num - 1]);
+ else
+ return BadValue;
+
+ if(!(device = (DGADevicePtr)xalloc(sizeof(DGADeviceRec))))
+ return BadAlloc;
+
+ if(!pScreenPriv->current) {
+ Bool oldVTSema = pScrn->vtSema;
+
+ pScrn->vtSema = FALSE; /* kludge until we rewrite VT switching */
+ (*pScrn->EnableDisableFBAccess)(index, FALSE);
+ pScrn->vtSema = oldVTSema;
+ }
+
+ if(!(*pScreenPriv->funcs->SetMode)(pScrn, pMode)) {
+ xfree(device);
+ return BadAlloc;
+ }
+
+ pScrn->currentMode = pMode->mode;
+
+ if(!pScreenPriv->current && !pScreenPriv->input) {
+ /* if it's multihead we need to warp the cursor off of
+ our screen so it doesn't get trapped */
+ }
+
+ pScrn->vtSema = FALSE;
+
+ if(pScreenPriv->current) {
+ PixmapPtr oldPix = pScreenPriv->current->pPix;
+ if(oldPix) {
+ if(oldPix->drawable.id)
+ FreeResource(oldPix->drawable.id, RT_NONE);
+ else
+ (*pScreen->DestroyPixmap)(oldPix);
+ }
+ xfree(pScreenPriv->current);
+ pScreenPriv->current = NULL;
+ }
+
+ if(pMode->flags & DGA_PIXMAP_AVAILABLE) {
+ if((pPix = (*pScreen->CreatePixmap)(pScreen, 0, 0, pMode->depth))) {
+ (*pScreen->ModifyPixmapHeader)(pPix,
+ pMode->pixmapWidth, pMode->pixmapHeight,
+ pMode->depth, pMode->bitsPerPixel,
+ pMode->bytesPerScanline,
+ (pointer)(pMode->address));
+ }
+ }
+
+ devRet->mode = device->mode = pMode;
+ devRet->pPix = device->pPix = pPix;
+ pScreenPriv->current = device;
+ pScreenPriv->pixmapMode = FALSE;
+ pScreenPriv->grabMouse = TRUE;
+ pScreenPriv->grabKeyboard = TRUE;
+
+ return Success;
+}
+
+
+
+/*********** exported ones ***************/
+
+void
+DGASetInputMode(int index, Bool keyboard, Bool mouse)
+{
+ ScreenPtr pScreen = screenInfo.screens[index];
+ DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen);
+
+ if (pScreenPriv)
+ {
+ pScreenPriv->grabMouse = mouse;
+ pScreenPriv->grabKeyboard = keyboard;
+ }
+}
+
+Bool
+DGAChangePixmapMode(int index, int *x, int *y, int mode)
+{
+ DGAScreenPtr pScreenPriv;
+ DGADevicePtr pDev;
+ DGAModePtr pMode;
+ PixmapPtr pPix;
+
+ if(DGAScreenIndex < 0)
+ return FALSE;
+
+ pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]);
+
+ if(!pScreenPriv || !pScreenPriv->current || !pScreenPriv->current->pPix)
+ return FALSE;
+
+ pDev = pScreenPriv->current;
+ pPix = pDev->pPix;
+ pMode = pDev->mode;
+
+ if(mode) {
+ int shift = 2;
+
+ if(*x > (pMode->pixmapWidth - pMode->viewportWidth))
+ *x = pMode->pixmapWidth - pMode->viewportWidth;
+ if(*y > (pMode->pixmapHeight - pMode->viewportHeight))
+ *y = pMode->pixmapHeight - pMode->viewportHeight;
+
+ switch(xf86Screens[index]->bitsPerPixel) {
+ case 16: shift = 1; break;
+ case 32: shift = 0; break;
+ default: break;
+ }
+
+ if(BITMAP_SCANLINE_PAD == 64)
+ shift++;
+
+ *x = (*x >> shift) << shift;
+
+ pPix->drawable.x = *x;
+ pPix->drawable.y = *y;
+ pPix->drawable.width = pMode->viewportWidth;
+ pPix->drawable.height = pMode->viewportHeight;
+ } else {
+ pPix->drawable.x = 0;
+ pPix->drawable.y = 0;
+ pPix->drawable.width = pMode->pixmapWidth;
+ pPix->drawable.height = pMode->pixmapHeight;
+ }
+ pPix->drawable.serialNumber = NEXT_SERIAL_NUMBER;
+ pScreenPriv->pixmapMode = mode;
+
+ return TRUE;
+}
+
+Bool
+DGAAvailable(int index)
+{
+ if(DGAScreenIndex < 0)
+ return FALSE;
+
+ if (!xf86NoSharedResources(((ScrnInfoPtr)screenInfo.screens[index]->
+ devPrivates[xf86ScreenIndex].ptr)->scrnIndex,MEM))
+ return FALSE;
+
+ if(DGA_GET_SCREEN_PRIV(screenInfo.screens[index]))
+ return TRUE;
+
+ return FALSE;
+}
+
+Bool
+DGAActive(int index)
+{
+ DGAScreenPtr pScreenPriv;
+
+ if(DGAScreenIndex < 0)
+ return FALSE;
+
+ pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]);
+
+ if(pScreenPriv && pScreenPriv->current)
+ return TRUE;
+
+ return FALSE;
+}
+
+
+
+/* Called by the event code in case the server is abruptly terminated */
+
+void
+DGAShutdown()
+{
+ ScrnInfoPtr pScrn;
+ int i;
+
+ if(DGAScreenIndex < 0)
+ return;
+
+ for(i = 0; i < screenInfo.numScreens; i++) {
+ pScrn = xf86Screens[i];
+
+ (void)(*pScrn->SetDGAMode)(pScrn->scrnIndex, 0, NULL);
+ }
+}
+
+/* Called by the extension to initialize a mode */
+
+int
+DGASetMode(
+ int index,
+ int num,
+ XDGAModePtr mode,
+ PixmapPtr *pPix
+){
+ ScrnInfoPtr pScrn = xf86Screens[index];
+ DGADeviceRec device;
+ int ret;
+
+ /* We rely on the extension to check that DGA is available */
+
+ ret = (*pScrn->SetDGAMode)(index, num, &device);
+ if((ret == Success) && num) {
+ DGACopyModeInfo(device.mode, mode);
+ *pPix = device.pPix;
+ }
+
+ return ret;
+}
+
+/* Called from the extension to let the DDX know which events are requested */
+
+void
+DGASelectInput(
+ int index,
+ ClientPtr client,
+ long mask
+){
+ DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]);
+
+ /* We rely on the extension to check that DGA is available */
+ pScreenPriv->client = client;
+ pScreenPriv->input = mask;
+}
+
+int
+DGAGetViewportStatus(int index)
+{
+ DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]);
+
+ /* We rely on the extension to check that DGA is active */
+
+ if (!pScreenPriv->funcs->GetViewport)
+ return 0;
+
+ return (*pScreenPriv->funcs->GetViewport)(pScreenPriv->pScrn);
+}
+
+int
+DGASetViewport(
+ int index,
+ int x, int y,
+ int mode
+){
+ DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]);
+
+ if (pScreenPriv->funcs->SetViewport)
+ (*pScreenPriv->funcs->SetViewport)(pScreenPriv->pScrn, x, y, mode);
+ return Success;
+}
+
+
+static int
+BitsClear(CARD32 data)
+{
+ int bits = 0;
+ CARD32 mask;
+
+ for(mask = 1; mask; mask <<= 1) {
+ if(!(data & mask)) bits++;
+ else break;
+ }
+
+ return bits;
+}
+
+int
+DGACreateColormap(int index, ClientPtr client, int id, int mode, int alloc)
+{
+ ScreenPtr pScreen = screenInfo.screens[index];
+ DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen);
+ FakedVisualList *fvlp;
+ VisualPtr pVisual;
+ DGAModePtr pMode;
+ ColormapPtr pmap;
+
+ if(!mode || (mode > pScreenPriv->numModes))
+ return BadValue;
+
+ if((alloc != AllocNone) && (alloc != AllocAll))
+ return BadValue;
+
+ pMode = &(pScreenPriv->modes[mode - 1]);
+
+ if(!(pVisual = xalloc(sizeof(VisualRec))))
+ return BadAlloc;
+
+ pVisual->vid = FakeClientID(0);
+ pVisual->class = pMode->visualClass;
+ pVisual->nplanes = pMode->depth;
+ pVisual->ColormapEntries = 1 << pMode->depth;
+ pVisual->bitsPerRGBValue = (pMode->depth + 2) / 3;
+
+ switch (pVisual->class) {
+ case PseudoColor:
+ case GrayScale:
+ case StaticGray:
+ pVisual->bitsPerRGBValue = 8; /* not quite */
+ pVisual->redMask = 0;
+ pVisual->greenMask = 0;
+ pVisual->blueMask = 0;
+ pVisual->offsetRed = 0;
+ pVisual->offsetGreen = 0;
+ pVisual->offsetBlue = 0;
+ break;
+ case DirectColor:
+ case TrueColor:
+ pVisual->ColormapEntries = 1 << pVisual->bitsPerRGBValue;
+ /* fall through */
+ case StaticColor:
+ pVisual->redMask = pMode->red_mask;
+ pVisual->greenMask = pMode->green_mask;
+ pVisual->blueMask = pMode->blue_mask;
+ pVisual->offsetRed = BitsClear(pVisual->redMask);
+ pVisual->offsetGreen = BitsClear(pVisual->greenMask);
+ pVisual->offsetBlue = BitsClear(pVisual->blueMask);
+ }
+
+ if(!(fvlp = xalloc(sizeof(FakedVisualList)))) {
+ xfree(pVisual);
+ return BadAlloc;
+ }
+
+ fvlp->free = FALSE;
+ fvlp->pVisual = pVisual;
+ fvlp->next = pScreenPriv->fakedVisuals;
+ pScreenPriv->fakedVisuals = fvlp;
+
+ LEGAL_NEW_RESOURCE(id, client);
+
+ return CreateColormap(id, pScreen, pVisual, &pmap, alloc, client->index);
+}
+
+/* Called by the extension to install a colormap on DGA active screens */
+
+void
+DGAInstallCmap(ColormapPtr cmap)
+{
+ ScreenPtr pScreen = cmap->pScreen;
+ DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen);
+
+ /* We rely on the extension to check that DGA is active */
+
+ if(!pScreenPriv->dgaColormap)
+ pScreenPriv->savedColormap = miInstalledMaps[pScreen->myNum];
+
+ pScreenPriv->dgaColormap = cmap;
+
+ (*pScreen->InstallColormap)(cmap);
+}
+
+int
+DGASync(int index)
+{
+ DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]);
+
+ /* We rely on the extension to check that DGA is active */
+
+ if (pScreenPriv->funcs->Sync)
+ (*pScreenPriv->funcs->Sync)(pScreenPriv->pScrn);
+
+ return Success;
+}
+
+int
+DGAFillRect(
+ int index,
+ int x, int y, int w, int h,
+ unsigned long color
+){
+ DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]);
+
+ /* We rely on the extension to check that DGA is active */
+
+ if(pScreenPriv->funcs->FillRect &&
+ (pScreenPriv->current->mode->flags & DGA_FILL_RECT)) {
+
+ (*pScreenPriv->funcs->FillRect)(pScreenPriv->pScrn, x, y, w, h, color);
+ return Success;
+ }
+ return BadMatch;
+}
+
+int
+DGABlitRect(
+ int index,
+ int srcx, int srcy,
+ int w, int h,
+ int dstx, int dsty
+){
+ DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]);
+
+ /* We rely on the extension to check that DGA is active */
+
+ if(pScreenPriv->funcs->BlitRect &&
+ (pScreenPriv->current->mode->flags & DGA_BLIT_RECT)) {
+
+ (*pScreenPriv->funcs->BlitRect)(pScreenPriv->pScrn,
+ srcx, srcy, w, h, dstx, dsty);
+ return Success;
+ }
+ return BadMatch;
+}
+
+int
+DGABlitTransRect(
+ int index,
+ int srcx, int srcy,
+ int w, int h,
+ int dstx, int dsty,
+ unsigned long color
+){
+ DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]);
+
+ /* We rely on the extension to check that DGA is active */
+
+ if(pScreenPriv->funcs->BlitTransRect &&
+ (pScreenPriv->current->mode->flags & DGA_BLIT_RECT_TRANS)) {
+
+ (*pScreenPriv->funcs->BlitTransRect)(pScreenPriv->pScrn,
+ srcx, srcy, w, h, dstx, dsty, color);
+ return Success;
+ }
+ return BadMatch;
+}
+
+
+int
+DGAGetModes(int index)
+{
+ DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]);
+ /* We rely on the extension to check that DGA is available */
+
+ return pScreenPriv->numModes;
+}
+
+
+int
+DGAGetModeInfo(
+ int index,
+ XDGAModePtr mode,
+ int num
+){
+ DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]);
+ /* We rely on the extension to check that DGA is available */
+
+ if((num <= 0) || (num > pScreenPriv->numModes))
+ return BadValue;
+
+ DGACopyModeInfo(&(pScreenPriv->modes[num - 1]), mode);
+
+ return Success;
+}
+
+
+static void
+DGACopyModeInfo(
+ DGAModePtr mode,
+ XDGAModePtr xmode
+){
+ DisplayModePtr dmode = mode->mode;
+
+ xmode->num = mode->num;
+ xmode->name = dmode->name;
+ xmode->VSync_num = (int)(dmode->VRefresh * 1000.0);
+ xmode->VSync_den = 1000;
+ xmode->flags = mode->flags;
+ xmode->imageWidth = mode->imageWidth;
+ xmode->imageHeight = mode->imageHeight;
+ xmode->pixmapWidth = mode->pixmapWidth;
+ xmode->pixmapHeight = mode->pixmapHeight;
+ xmode->bytesPerScanline = mode->bytesPerScanline;
+ xmode->byteOrder = mode->byteOrder;
+ xmode->depth = mode->depth;
+ xmode->bitsPerPixel = mode->bitsPerPixel;
+ xmode->red_mask = mode->red_mask;
+ xmode->green_mask = mode->green_mask;
+ xmode->blue_mask = mode->blue_mask;
+ xmode->visualClass = mode->visualClass;
+ xmode->viewportWidth = mode->viewportWidth;
+ xmode->viewportHeight = mode->viewportHeight;
+ xmode->xViewportStep = mode->xViewportStep;
+ xmode->yViewportStep = mode->yViewportStep;
+ xmode->maxViewportX = mode->maxViewportX;
+ xmode->maxViewportY = mode->maxViewportY;
+ xmode->viewportFlags = mode->viewportFlags;
+ xmode->reserved1 = mode->reserved1;
+ xmode->reserved2 = mode->reserved2;
+ xmode->offset = mode->offset;
+
+ if(dmode->Flags & V_INTERLACE) xmode->flags |= DGA_INTERLACED;
+ if(dmode->Flags & V_DBLSCAN) xmode->flags |= DGA_DOUBLESCAN;
+}
+
+
+Bool
+DGAVTSwitch(void)
+{
+ ScreenPtr pScreen;
+ int i;
+
+ for(i = 0; i < screenInfo.numScreens; i++) {
+ pScreen = screenInfo.screens[i];
+
+ /* Alternatively, this could send events to DGA clients */
+
+ if(DGAScreenIndex >= 0) {
+ DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen);
+
+ if(pScreenPriv && pScreenPriv->current)
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+
+/* We have the power to steal or modify events that are about to get queued */
+
+Bool
+DGAStealKeyEvent(int index, xEvent *e)
+{
+ DGAScreenPtr pScreenPriv;
+ dgaEvent de;
+
+ if(DGAScreenIndex < 0) /* no DGA */
+ return FALSE;
+
+ pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]);
+
+ if(!pScreenPriv || !pScreenPriv->grabKeyboard) /* no direct mode */
+ return FALSE;
+
+ de.u.u.type = e->u.u.type + *XDGAEventBase;
+ de.u.u.detail = e->u.u.detail;
+ de.u.event.time = e->u.keyButtonPointer.time;
+ xf86eqEnqueue ((xEvent *) &de);
+ return TRUE;
+}
+
+static int DGAMouseX, DGAMouseY;
+
+Bool
+DGAStealMouseEvent(int index, xEvent *e, int dx, int dy)
+{
+ DGAScreenPtr pScreenPriv;
+ dgaEvent de;
+
+ if(DGAScreenIndex < 0) /* no DGA */
+ return FALSE;
+
+ pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]);
+
+ if(!pScreenPriv || !pScreenPriv->grabMouse) /* no direct mode */
+ return FALSE;
+
+ DGAMouseX += dx;
+ if (DGAMouseX < 0)
+ DGAMouseX = 0;
+ else if (DGAMouseX > screenInfo.screens[index]->width)
+ DGAMouseX = screenInfo.screens[index]->width;
+ DGAMouseY += dy;
+ if (DGAMouseY < 0)
+ DGAMouseY = 0;
+ else if (DGAMouseY > screenInfo.screens[index]->height)
+ DGAMouseY = screenInfo.screens[index]->height;
+ de.u.u.type = e->u.u.type + *XDGAEventBase;
+ de.u.u.detail = e->u.u.detail;
+ de.u.event.time = e->u.keyButtonPointer.time;
+ de.u.event.dx = dx;
+ de.u.event.dy = dy;
+ de.u.event.pad1 = DGAMouseX;
+ de.u.event.pad2 = DGAMouseY;
+ xf86eqEnqueue ((xEvent *) &de);
+ return TRUE;
+}
+
+Bool
+DGAIsDgaEvent (xEvent *e)
+{
+ int coreEquiv;
+ if (DGAScreenIndex < 0 || XDGAEventBase == 0)
+ return FALSE;
+ coreEquiv = e->u.u.type - *XDGAEventBase;
+ if (KeyPress <= coreEquiv && coreEquiv <= MotionNotify)
+ return TRUE;
+ return FALSE;
+}
+
+#define NoSuchEvent 0x80000000 /* so doesn't match NoEventMask */
+static Mask filters[] =
+{
+ NoSuchEvent, /* 0 */
+ NoSuchEvent, /* 1 */
+ KeyPressMask, /* KeyPress */
+ KeyReleaseMask, /* KeyRelease */
+ ButtonPressMask, /* ButtonPress */
+ ButtonReleaseMask, /* ButtonRelease */
+ PointerMotionMask, /* MotionNotify (initial state) */
+};
+
+static void
+DGAProcessKeyboardEvent (ScreenPtr pScreen, dgaEvent *de, DeviceIntPtr keybd)
+{
+ int key, bit;
+ register BYTE *kptr;
+ register int i;
+ register CARD8 modifiers;
+ register CARD16 mask;
+ int coreEquiv;
+ xEvent core;
+ KeyClassPtr keyc = keybd->key;
+ DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen);
+
+ coreEquiv = de->u.u.type - *XDGAEventBase;
+
+ /*
+ * Fill in remaining event state
+ */
+ de->u.event.dx = 0;
+ de->u.event.dy = 0;
+ de->u.event.screen = pScreen->myNum;
+ de->u.event.state = keyc->state | (inputInfo.pointer)->button->state;
+
+ /*
+ * Keep the core state in sync by duplicating what
+ * CoreProcessKeyboardEvent does
+ */
+ key = de->u.u.detail;
+ kptr = &keyc->down[key >> 3];
+ bit = 1 << (key & 7);
+ modifiers = keyc->modifierMap[key];
+ switch (coreEquiv)
+ {
+ case KeyPress:
+ inputInfo.pointer->valuator->motionHintWindow = NullWindow;
+ *kptr |= bit;
+ keyc->prev_state = keyc->state;
+ if (noXkbExtension) {
+ for (i = 0, mask = 1; modifiers; i++, mask <<= 1)
+ {
+ if (mask & modifiers)
+ {
+ /* This key affects modifier "i" */
+ keyc->modifierKeyCount[i]++;
+ keyc->state |= mask;
+ modifiers &= ~mask;
+ }
+ }
+ }
+ break;
+ case KeyRelease:
+ inputInfo.pointer->valuator->motionHintWindow = NullWindow;
+ *kptr &= ~bit;
+ keyc->prev_state = keyc->state;
+ if (noXkbExtension) {
+ for (i = 0, mask = 1; modifiers; i++, mask <<= 1)
+ {
+ if (mask & modifiers) {
+ /* This key affects modifier "i" */
+ if (--keyc->modifierKeyCount[i] <= 0) {
+ keyc->state &= ~mask;
+ keyc->modifierKeyCount[i] = 0;
+ }
+ modifiers &= ~mask;
+ }
+ }
+ }
+ break;
+ }
+ /*
+ * Deliver the DGA event
+ */
+ if (pScreenPriv->client)
+ {
+ /* If the DGA client has selected input, then deliver based on the usual filter */
+ TryClientEvents (pScreenPriv->client, (xEvent *) de, 1,
+ filters[coreEquiv], pScreenPriv->input, 0);
+ }
+ else
+ {
+ /* If the keyboard is actively grabbed, deliver a grabbed core event */
+ if (keybd->grab && !keybd->fromPassiveGrab)
+ {
+ core.u.u.type = coreEquiv;
+ core.u.u.detail = de->u.u.detail;
+ core.u.keyButtonPointer.time = de->u.event.time;
+ core.u.keyButtonPointer.eventX = de->u.event.dx;
+ core.u.keyButtonPointer.eventY = de->u.event.dy;
+ core.u.keyButtonPointer.rootX = de->u.event.dx;
+ core.u.keyButtonPointer.rootY = de->u.event.dy;
+ core.u.keyButtonPointer.state = de->u.event.state;
+ DeliverGrabbedEvent (&core, keybd, FALSE, 1);
+ }
+ }
+}
+
+static void
+DGAProcessPointerEvent (ScreenPtr pScreen, dgaEvent *de, DeviceIntPtr mouse)
+{
+ ButtonClassPtr butc = mouse->button;
+ int coreEquiv;
+ DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen);
+ xEvent core;
+
+ coreEquiv = de->u.u.type - *XDGAEventBase;
+ /*
+ * Fill in remaining event state
+ */
+ de->u.event.screen = pScreen->myNum;
+ de->u.event.state = butc->state | inputInfo.keyboard->key->state;
+ /*
+ * Keep the core state in sync by duplicating what
+ * CoreProcessPointerEvent does
+ */
+ if (coreEquiv != MotionNotify)
+ {
+ register int key;
+ register BYTE *kptr;
+ int bit;
+
+ key = de->u.u.detail;
+ kptr = &butc->down[key >> 3];
+ bit = 1 << (key & 7);
+ switch (coreEquiv)
+ {
+ case ButtonPress:
+ mouse->valuator->motionHintWindow = NullWindow;
+ if (!(*kptr & bit))
+ butc->buttonsDown++;
+ butc->motionMask = ButtonMotionMask;
+ *kptr |= bit;
+ if (key <= 5)
+ butc->state |= (Button1Mask >> 1) << key;
+ break;
+ case ButtonRelease:
+ mouse->valuator->motionHintWindow = NullWindow;
+ if (*kptr & bit)
+ --butc->buttonsDown;
+ if (!butc->buttonsDown)
+ butc->motionMask = 0;
+ *kptr &= ~bit;
+ if (key == 0)
+ return;
+ if (key <= 5)
+ butc->state &= ~((Button1Mask >> 1) << key);
+ break;
+ }
+ }
+ /*
+ * Deliver the DGA event
+ */
+ if (pScreenPriv->client)
+ {
+ /* If the DGA client has selected input, then deliver based on the usual filter */
+ TryClientEvents (pScreenPriv->client, (xEvent *) de, 1,
+ filters[coreEquiv], pScreenPriv->input, 0);
+ }
+ else
+ {
+ /* If the pointer is actively grabbed, deliver a grabbed core event */
+ if (mouse->grab && !mouse->fromPassiveGrab)
+ {
+ core.u.u.type = coreEquiv;
+ core.u.u.detail = de->u.u.detail;
+ core.u.keyButtonPointer.time = de->u.event.time;
+ core.u.keyButtonPointer.eventX = de->u.event.dx;
+ core.u.keyButtonPointer.eventY = de->u.event.dy;
+ core.u.keyButtonPointer.rootX = de->u.event.dx;
+ core.u.keyButtonPointer.rootY = de->u.event.dy;
+ core.u.keyButtonPointer.state = de->u.event.state;
+ DeliverGrabbedEvent (&core, mouse, FALSE, 1);
+ }
+ }
+}
+
+Bool
+DGADeliverEvent (ScreenPtr pScreen, xEvent *e)
+{
+ dgaEvent *de = (dgaEvent *) e;
+ DGAScreenPtr pScreenPriv;
+ int coreEquiv;
+
+ /* no DGA */
+ if (DGAScreenIndex < 0 || XDGAEventBase == 0)
+ return FALSE;
+ pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen);
+
+ /* DGA not initialized on this screen */
+ if (!pScreenPriv)
+ return FALSE;
+
+ coreEquiv = de->u.u.type - *XDGAEventBase;
+ /* Not a DGA event */
+ if (coreEquiv < KeyPress || coreEquiv > MotionNotify)
+ return FALSE;
+
+ switch (coreEquiv) {
+ case KeyPress:
+ case KeyRelease:
+ DGAProcessKeyboardEvent (pScreen, de, inputInfo.keyboard);
+ break;
+ default:
+ DGAProcessPointerEvent (pScreen, de, inputInfo.pointer);
+ break;
+ }
+ return TRUE;
+}
+
+Bool
+DGAOpenFramebuffer(
+ int index,
+ char **name,
+ unsigned char **mem,
+ int *size,
+ int *offset,
+ int *flags
+){
+ DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]);
+
+ /* We rely on the extension to check that DGA is available */
+
+ return (*pScreenPriv->funcs->OpenFramebuffer)(pScreenPriv->pScrn,
+ name, mem, size, offset, flags);
+}
+
+void
+DGACloseFramebuffer(int index)
+{
+ DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]);
+
+ /* We rely on the extension to check that DGA is available */
+ if(pScreenPriv->funcs->CloseFramebuffer)
+ (*pScreenPriv->funcs->CloseFramebuffer)(pScreenPriv->pScrn);
+}
+
+/* For DGA 1.0 backwards compatibility only */
+
+int
+DGAGetOldDGAMode(int index)
+{
+ DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]);
+ ScrnInfoPtr pScrn = pScreenPriv->pScrn;
+ DGAModePtr mode;
+ int i, w, h, p;
+
+ /* We rely on the extension to check that DGA is available */
+
+ w = pScrn->currentMode->HDisplay;
+ h = pScrn->currentMode->VDisplay;
+ p = ((pScrn->displayWidth * (pScrn->bitsPerPixel >> 3)) + 3) & ~3L;
+
+ for(i = 0; i < pScreenPriv->numModes; i++) {
+ mode = &(pScreenPriv->modes[i]);
+
+ if((mode->viewportWidth == w) && (mode->viewportHeight == h) &&
+ (mode->bytesPerScanline == p) &&
+ (mode->bitsPerPixel == pScrn->bitsPerPixel) &&
+ (mode->depth == pScrn->depth)) {
+
+ return mode->num;
+ }
+ }
+
+ return 0;
+}
+
diff --git a/hw/xfree86/common/xf86DPMS.c b/hw/xfree86/common/xf86DPMS.c
new file mode 100644
index 000000000..0de054ff3
--- /dev/null
+++ b/hw/xfree86/common/xf86DPMS.c
@@ -0,0 +1,175 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86DPMS.c,v 1.8 2003/02/13 02:41:09 dawes Exp $ */
+
+/*
+ * Copyright (c) 1997-1998 by The XFree86 Project, Inc.
+ */
+
+/*
+ * This file contains the DPMS functions required by the extension.
+ */
+
+#include "X.h"
+#include "os.h"
+#include "globals.h"
+#include "xf86.h"
+#include "xf86Priv.h"
+#ifdef DPMSExtension
+#include "dpmsproc.h"
+#endif
+
+
+#ifdef DPMSExtension
+static int DPMSGeneration = 0;
+static int DPMSIndex = -1;
+static Bool DPMSClose(int i, ScreenPtr pScreen);
+static int DPMSCount = 0;
+#endif
+
+
+Bool
+xf86DPMSInit(ScreenPtr pScreen, DPMSSetProcPtr set, int flags)
+{
+#ifdef DPMSExtension
+ DPMSPtr pDPMS;
+ pointer DPMSOpt;
+
+ if (serverGeneration != DPMSGeneration) {
+ if ((DPMSIndex = AllocateScreenPrivateIndex()) < 0)
+ return FALSE;
+ DPMSGeneration = serverGeneration;
+ }
+
+ if (DPMSDisabledSwitch)
+ DPMSEnabled = FALSE;
+ if (!(pScreen->devPrivates[DPMSIndex].ptr = xcalloc(sizeof(DPMSRec), 1)))
+ return FALSE;
+
+ pDPMS = (DPMSPtr)pScreen->devPrivates[DPMSIndex].ptr;
+ pDPMS->Set = set;
+ pDPMS->Flags = flags;
+ DPMSOpt = xf86FindOption(xf86Screens[pScreen->myNum]->options, "dpms");
+ if (DPMSOpt) {
+ if ((pDPMS->Enabled
+ = xf86SetBoolOption(xf86Screens[pScreen->myNum]->options,
+ "dpms",FALSE))
+ && !DPMSDisabledSwitch)
+ DPMSEnabled = TRUE;
+ xf86MarkOptionUsed(DPMSOpt);
+ xf86DrvMsg(pScreen->myNum, X_CONFIG, "DPMS enabled\n");
+ } else if (DPMSEnabledSwitch) {
+ if (!DPMSDisabledSwitch)
+ DPMSEnabled = TRUE;
+ pDPMS->Enabled = TRUE;
+ }
+ else {
+ pDPMS->Enabled = FALSE;
+ }
+ pDPMS->CloseScreen = pScreen->CloseScreen;
+ pScreen->CloseScreen = DPMSClose;
+ DPMSCount++;
+ return TRUE;
+#else
+ return FALSE;
+#endif
+}
+
+
+#ifdef DPMSExtension
+
+static Bool
+DPMSClose(int i, ScreenPtr pScreen)
+{
+ DPMSPtr pDPMS;
+
+ /* This shouldn't happen */
+ if (DPMSIndex < 0)
+ return FALSE;
+
+ pDPMS = (DPMSPtr)pScreen->devPrivates[DPMSIndex].ptr;
+
+ /* This shouldn't happen */
+ if (!pDPMS)
+ return FALSE;
+
+ pScreen->CloseScreen = pDPMS->CloseScreen;
+
+ xfree((pointer)pDPMS);
+ pScreen->devPrivates[DPMSIndex].ptr = NULL;
+ if (--DPMSCount == 0)
+ DPMSIndex = -1;
+ return pScreen->CloseScreen(i, pScreen);
+}
+
+
+/*
+ * DPMSSet --
+ * Device dependent DPMS mode setting hook. This is called whenever
+ * the DPMS mode is to be changed.
+ */
+void
+DPMSSet(int level)
+{
+ int i;
+ DPMSPtr pDPMS;
+
+ DPMSPowerLevel = level;
+
+ if (DPMSIndex < 0)
+ return;
+
+ /* For each screen, set the DPMS level */
+ for (i = 0; i < xf86NumScreens; i++) {
+ pDPMS = (DPMSPtr)screenInfo.screens[i]->devPrivates[DPMSIndex].ptr;
+ if (pDPMS && pDPMS->Set && pDPMS->Enabled && xf86Screens[i]->vtSema) {
+ xf86EnableAccess(xf86Screens[i]);
+ pDPMS->Set(xf86Screens[i], level, 0);
+ }
+ }
+}
+
+
+/*
+ * DPMSSupported --
+ * Return TRUE if any screen supports DPMS.
+ */
+Bool
+DPMSSupported(void)
+{
+ int i;
+ DPMSPtr pDPMS;
+
+ if (DPMSIndex < 0) {
+ return FALSE;
+ }
+
+ /* For each screen, check if DPMS is supported */
+ for (i = 0; i < xf86NumScreens; i++) {
+ pDPMS = (DPMSPtr)screenInfo.screens[i]->devPrivates[DPMSIndex].ptr;
+ if (pDPMS && pDPMS->Set)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+/*
+ * DPMSGet --
+ * Device dependent DPMS mode getting hook. This returns the current
+ * DPMS mode, or -1 if DPMS is not supported.
+ *
+ * This should hook in to the appropriate driver-level function, which
+ * will be added to the ScrnInfoRec.
+ *
+ * NOTES:
+ * 1. the calling interface should be changed to specify which
+ * screen to check.
+ * 2. It isn't clear that this function is ever used or what it should
+ * return.
+ */
+int
+DPMSGet(int *level)
+{
+ return DPMSPowerLevel;
+}
+
+#endif /* DPMSExtension */
diff --git a/hw/xfree86/common/xf86Date.h b/hw/xfree86/common/xf86Date.h
new file mode 100644
index 000000000..506e05370
--- /dev/null
+++ b/hw/xfree86/common/xf86Date.h
@@ -0,0 +1,7 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/xf86Date.h,v 1.3.2.3 2003/05/10 01:10:10 dawes Exp $ */
+
+#ifndef XF86_DATE
+
+#define XF86_DATE "9 May 2003"
+
+#endif
diff --git a/hw/xfree86/common/xf86Debug.c b/hw/xfree86/common/xf86Debug.c
new file mode 100644
index 000000000..b069743a1
--- /dev/null
+++ b/hw/xfree86/common/xf86Debug.c
@@ -0,0 +1,162 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86Debug.c,v 1.4 2001/12/13 18:01:50 eich Exp $ */
+
+#include <sys/time.h>
+#include <unistd.h>
+#include "X.h"
+#include "os.h"
+#include "xf86.h"
+#include "xf86Priv.h"
+#include "xf86_OSlib.h"
+#include "compiler.h"
+
+void xf86Break1(void)
+{
+}
+
+void xf86Break2(void)
+{
+}
+
+void xf86Break3(void)
+{
+}
+
+char *xf86p8bit[] = { "00000000", "00000001", "00000010", "00000011",
+ "00000100", "00000101", "00000110", "00000111",
+ "00001000", "00001001", "00001010", "00001011",
+ "00001100", "00001101", "00001110", "00001111",
+ "00010000", "00010001", "00010010", "00010011",
+ "00010100", "00010101", "00010110", "00010111",
+ "00011000", "00011001", "00011010", "00011011",
+ "00011100", "00011101", "00011110", "00011111",
+ "00100000", "00100001", "00100010", "00100011",
+ "00100100", "00100101", "00100110", "00100111",
+ "00101000", "00101001", "00101010", "00101011",
+ "00101100", "00101101", "00101110", "00101111",
+ "00110000", "00110001", "00110010", "00110011",
+ "00110100", "00110101", "00110110", "00110111",
+ "00111000", "00111001", "00111010", "00111011",
+ "00111100", "00111101", "00111110", "00111111",
+ "01000000", "01000001", "01000010", "01000011",
+ "01000100", "01000101", "01000110", "01000111",
+ "01001000", "01001001", "01001010", "01001011",
+ "01001100", "01001101", "01001110", "01001111",
+ "01010000", "01010001", "01010010", "01010011",
+ "01010100", "01010101", "01010110", "01010111",
+ "01011000", "01011001", "01011010", "01011011",
+ "01011100", "01011101", "01011110", "01011111",
+ "01100000", "01100001", "01100010", "01100011",
+ "01100100", "01100101", "01100110", "01100111",
+ "01101000", "01101001", "01101010", "01101011",
+ "01101100", "01101101", "01101110", "01101111",
+ "01110000", "01110001", "01110010", "01110011",
+ "01110100", "01110101", "01110110", "01110111",
+ "01111000", "01111001", "01111010", "01111011",
+ "01111100", "01111101", "01111110", "01111111",
+ "10000000", "10000001", "10000010", "10000011",
+ "10000100", "10000101", "10000110", "10000111",
+ "10001000", "10001001", "10001010", "10001011",
+ "10001100", "10001101", "10001110", "10001111",
+ "10010000", "10010001", "10010010", "10010011",
+ "10010100", "10010101", "10010110", "10010111",
+ "10011000", "10011001", "10011010", "10011011",
+ "10011100", "10011101", "10011110", "10011111",
+ "10100000", "10100001", "10100010", "10100011",
+ "10100100", "10100101", "10100110", "10100111",
+ "10101000", "10101001", "10101010", "10101011",
+ "10101100", "10101101", "10101110", "10101111",
+ "10110000", "10110001", "10110010", "10110011",
+ "10110100", "10110101", "10110110", "10110111",
+ "10111000", "10111001", "10111010", "10111011",
+ "10111100", "10111101", "10111110", "10111111",
+ "11000000", "11000001", "11000010", "11000011",
+ "11000100", "11000101", "11000110", "11000111",
+ "11001000", "11001001", "11001010", "11001011",
+ "11001100", "11001101", "11001110", "11001111",
+ "11010000", "11010001", "11010010", "11010011",
+ "11010100", "11010101", "11010110", "11010111",
+ "11011000", "11011001", "11011010", "11011011",
+ "11011100", "11011101", "11011110", "11011111",
+ "11100000", "11100001", "11100010", "11100011",
+ "11100100", "11100101", "11100110", "11100111",
+ "11101000", "11101001", "11101010", "11101011",
+ "11101100", "11101101", "11101110", "11101111",
+ "11110000", "11110001", "11110010", "11110011",
+ "11110100", "11110101", "11110110", "11110111",
+ "11111000", "11111001", "11111010", "11111011",
+ "11111100", "11111101", "11111110", "11111111"
+};
+
+CARD32 xf86DummyVar1;
+CARD32 xf86DummyVar2;
+CARD32 xf86DummyVar3;
+
+CARD8 xf86PeekFb8(CARD8 *p) { return *p; }
+CARD16 xf86PeekFb16(CARD16 *p) { return *p; }
+CARD32 xf86PeekFb32(CARD32 *p) { return *p; }
+void xf86PokeFb8(CARD8 *p, CARD8 v) { *p = v; }
+void xf86PokeFb16(CARD16 *p, CARD16 v) { *p = v; }
+void xf86PokeFb32(CARD16 *p, CARD32 v) { *p = v; }
+
+CARD8 xf86PeekMmio8(pointer Base, unsigned long Offset)
+{
+ return MMIO_IN8(Base,Offset);
+}
+
+CARD16 xf86PeekMmio16(pointer Base, unsigned long Offset)
+{
+ return MMIO_IN16(Base,Offset);
+}
+
+CARD32 xf86PeekMmio32(pointer Base, unsigned long Offset)
+{
+ return MMIO_IN32(Base,Offset);
+}
+
+void xf86PokeMmio8(pointer Base, unsigned long Offset, CARD8 v)
+{
+ MMIO_OUT8(Base,Offset,v);
+}
+
+void xf86PokeMmio16(pointer Base, unsigned long Offset, CARD16 v)
+{
+ MMIO_OUT16(Base,Offset,v);
+}
+
+void xf86PokeMmio32(pointer Base, unsigned long Offset, CARD32 v)
+{
+ MMIO_OUT32(Base,Offset,v);
+}
+
+
+void
+xf86STimestamp(xf86TsPtr* timestamp)
+{
+ if (*timestamp) {
+ gettimeofday((struct timeval*)*timestamp,NULL);
+ } else {
+ *timestamp = xnfalloc(sizeof(xf86TsRec));
+ gettimeofday((struct timeval*)*timestamp,NULL);
+ }
+}
+
+void
+xf86SPTimestamp(xf86TsPtr* timestamp, char *str)
+{
+ if (*timestamp) {
+ long diff;
+ struct timeval ts;
+ ts = **(struct timeval**)timestamp;
+ gettimeofday((struct timeval*)*timestamp,NULL);
+ if (ts.tv_usec > (*timestamp)->usec)
+ diff = ((*timestamp)->sec - ts.tv_sec - 1) * 1000
+ + (ts.tv_usec - (*timestamp)->usec) / 1000;
+ else
+ diff = ((*timestamp)->sec - ts.tv_sec) * 1000
+ +(- ts.tv_usec + (*timestamp)->usec) / 1000;
+ ErrorF("%s Elapsed: %i\n",str,diff);
+ } else {
+ *timestamp = xnfalloc(sizeof(xf86TsRec));
+ gettimeofday((struct timeval*)*timestamp,NULL);
+ }
+}
diff --git a/hw/xfree86/common/xf86DefModes.c b/hw/xfree86/common/xf86DefModes.c
new file mode 100644
index 000000000..abef13110
--- /dev/null
+++ b/hw/xfree86/common/xf86DefModes.c
@@ -0,0 +1,153 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86DefModes.c,v 1.9 2002/11/11 04:24:40 dawes Exp $ */
+
+/* THIS FILE IS AUTOMATICALLY GENERATED -- DO NOT EDIT -- LOOK at
+ * modeline2c.pl */
+
+/*
+ * Copyright 1999 by The XFree86 Project, Inc.
+ *
+ * Author: Dirk Hohndel <hohndel@XFree86.Org>
+ */
+
+#include "xf86.h"
+#include "xf86Config.h"
+#include "xf86Priv.h"
+#include "xf86_OSlib.h"
+
+#include "globals.h"
+
+#define MODEPREFIX(name) NULL, NULL, name, 0,M_T_DEFAULT
+#define MODESUFFIX 0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0,FALSE,FALSE,0,NULL,0,0.0,0.0
+
+DisplayModeRec xf86DefaultModes [] = {
+/* 640x350 @ 85Hz (VESA) hsync: 37.9kHz */
+ {MODEPREFIX("640x350"),31500, 640,672,736,832,0, 350,382,385,445,0, V_PHSYNC | V_NVSYNC, MODESUFFIX},
+ {MODEPREFIX("320x175"),15750, 320,336,368,416,0, 175,191,192,222,0, V_PHSYNC | V_NVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 640x400 @ 85Hz (VESA) hsync: 37.9kHz */
+ {MODEPREFIX("640x400"),31500, 640,672,736,832,0, 400,401,404,445,0, V_NHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("320x200"),15750, 320,336,368,416,0, 200,200,202,222,0, V_NHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 720x400 @ 85Hz (VESA) hsync: 37.9kHz */
+ {MODEPREFIX("720x400"),35500, 720,756,828,936,0, 400,401,404,446,0, V_NHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("360x200"),17750, 360,378,414,468,0, 200,200,202,223,0, V_NHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 640x480 @ 60Hz (Industry standard) hsync: 31.5kHz */
+ {MODEPREFIX("640x480"),25200, 640,656,752,800,0, 480,490,492,525,0, V_NHSYNC | V_NVSYNC, MODESUFFIX},
+ {MODEPREFIX("320x240"),12600, 320,328,376,400,0, 240,245,246,262,0, V_NHSYNC | V_NVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 640x480 @ 72Hz (VESA) hsync: 37.9kHz */
+ {MODEPREFIX("640x480"),31500, 640,664,704,832,0, 480,489,491,520,0, V_NHSYNC | V_NVSYNC, MODESUFFIX},
+ {MODEPREFIX("320x240"),15750, 320,332,352,416,0, 240,244,245,260,0, V_NHSYNC | V_NVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 640x480 @ 75Hz (VESA) hsync: 37.5kHz */
+ {MODEPREFIX("640x480"),31500, 640,656,720,840,0, 480,481,484,500,0, V_NHSYNC | V_NVSYNC, MODESUFFIX},
+ {MODEPREFIX("320x240"),15750, 320,328,360,420,0, 240,240,242,250,0, V_NHSYNC | V_NVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 640x480 @ 85Hz (VESA) hsync: 43.3kHz */
+ {MODEPREFIX("640x480"),36000, 640,696,752,832,0, 480,481,484,509,0, V_NHSYNC | V_NVSYNC, MODESUFFIX},
+ {MODEPREFIX("320x240"),18000, 320,348,376,416,0, 240,240,242,254,0, V_NHSYNC | V_NVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 800x600 @ 56Hz (VESA) hsync: 35.2kHz */
+ {MODEPREFIX("800x600"),36000, 800,824,896,1024,0, 600,601,603,625,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("400x300"),18000, 400,412,448,512,0, 300,300,301,312,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 800x600 @ 60Hz (VESA) hsync: 37.9kHz */
+ {MODEPREFIX("800x600"),40000, 800,840,968,1056,0, 600,601,605,628,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("400x300"),20000, 400,420,484,528,0, 300,300,302,314,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 800x600 @ 72Hz (VESA) hsync: 48.1kHz */
+ {MODEPREFIX("800x600"),50000, 800,856,976,1040,0, 600,637,643,666,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("400x300"),25000, 400,428,488,520,0, 300,318,321,333,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 800x600 @ 75Hz (VESA) hsync: 46.9kHz */
+ {MODEPREFIX("800x600"),49500, 800,816,896,1056,0, 600,601,604,625,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("400x300"),24750, 400,408,448,528,0, 300,300,302,312,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 800x600 @ 85Hz (VESA) hsync: 53.7kHz */
+ {MODEPREFIX("800x600"),56300, 800,832,896,1048,0, 600,601,604,631,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("400x300"),28150, 400,416,448,524,0, 300,300,302,315,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 1024x768i @ 43Hz (industry standard) hsync: 35.5kHz */
+ {MODEPREFIX("1024x768"),44900, 1024,1032,1208,1264,0, 768,768,776,817,0, V_PHSYNC | V_PVSYNC | V_INTERLACE, MODESUFFIX},
+ {MODEPREFIX("512x384"),22450, 512,516,604,632,0, 384,384,388,408,0, V_PHSYNC | V_PVSYNC | V_INTERLACE | V_DBLSCAN, MODESUFFIX},
+/* 1024x768 @ 60Hz (VESA) hsync: 48.4kHz */
+ {MODEPREFIX("1024x768"),65000, 1024,1048,1184,1344,0, 768,771,777,806,0, V_NHSYNC | V_NVSYNC, MODESUFFIX},
+ {MODEPREFIX("512x384"),32500, 512,524,592,672,0, 384,385,388,403,0, V_NHSYNC | V_NVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 1024x768 @ 70Hz (VESA) hsync: 56.5kHz */
+ {MODEPREFIX("1024x768"),75000, 1024,1048,1184,1328,0, 768,771,777,806,0, V_NHSYNC | V_NVSYNC, MODESUFFIX},
+ {MODEPREFIX("512x384"),37500, 512,524,592,664,0, 384,385,388,403,0, V_NHSYNC | V_NVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 1024x768 @ 75Hz (VESA) hsync: 60.0kHz */
+ {MODEPREFIX("1024x768"),78800, 1024,1040,1136,1312,0, 768,769,772,800,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("512x384"),39400, 512,520,568,656,0, 384,384,386,400,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 1024x768 @ 85Hz (VESA) hsync: 68.7kHz */
+ {MODEPREFIX("1024x768"),94500, 1024,1072,1168,1376,0, 768,769,772,808,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("512x384"),47250, 512,536,584,688,0, 384,384,386,404,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 1152x864 @ 75Hz (VESA) hsync: 67.5kHz */
+ {MODEPREFIX("1152x864"),108000, 1152,1216,1344,1600,0, 864,865,868,900,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("576x432"),54000, 576,608,672,800,0, 432,432,434,450,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 1280x960 @ 60Hz (VESA) hsync: 60.0kHz */
+ {MODEPREFIX("1280x960"),108000, 1280,1376,1488,1800,0, 960,961,964,1000,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("640x480"),54000, 640,688,744,900,0, 480,480,482,500,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 1280x960 @ 85Hz (VESA) hsync: 85.9kHz */
+ {MODEPREFIX("1280x960"),148500, 1280,1344,1504,1728,0, 960,961,964,1011,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("640x480"),74250, 640,672,752,864,0, 480,480,482,505,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 1280x1024 @ 60Hz (VESA) hsync: 64.0kHz */
+ {MODEPREFIX("1280x1024"),108000, 1280,1328,1440,1688,0, 1024,1025,1028,1066,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("640x512"),54000, 640,664,720,844,0, 512,512,514,533,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 1280x1024 @ 75Hz (VESA) hsync: 80.0kHz */
+ {MODEPREFIX("1280x1024"),135000, 1280,1296,1440,1688,0, 1024,1025,1028,1066,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("640x512"),67500, 640,648,720,844,0, 512,512,514,533,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 1280x1024 @ 85Hz (VESA) hsync: 91.1kHz */
+ {MODEPREFIX("1280x1024"),157500, 1280,1344,1504,1728,0, 1024,1025,1028,1072,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("640x512"),78750, 640,672,752,864,0, 512,512,514,536,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 1600x1200 @ 60Hz (VESA) hsync: 75.0kHz */
+ {MODEPREFIX("1600x1200"),162000, 1600,1664,1856,2160,0, 1200,1201,1204,1250,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("800x600"),81000, 800,832,928,1080,0, 600,600,602,625,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 1600x1200 @ 65Hz (VESA) hsync: 81.3kHz */
+ {MODEPREFIX("1600x1200"),175500, 1600,1664,1856,2160,0, 1200,1201,1204,1250,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("800x600"),87750, 800,832,928,1080,0, 600,600,602,625,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 1600x1200 @ 70Hz (VESA) hsync: 87.5kHz */
+ {MODEPREFIX("1600x1200"),189000, 1600,1664,1856,2160,0, 1200,1201,1204,1250,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("800x600"),94500, 800,832,928,1080,0, 600,600,602,625,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 1600x1200 @ 75Hz (VESA) hsync: 93.8kHz */
+ {MODEPREFIX("1600x1200"),202500, 1600,1664,1856,2160,0, 1200,1201,1204,1250,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("800x600"),101250, 800,832,928,1080,0, 600,600,602,625,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 1600x1200 @ 85Hz (VESA) hsync: 106.3kHz */
+ {MODEPREFIX("1600x1200"),229500, 1600,1664,1856,2160,0, 1200,1201,1204,1250,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("800x600"),114750, 800,832,928,1080,0, 600,600,602,625,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 1792x1344 @ 60Hz (VESA) hsync: 83.6kHz */
+ {MODEPREFIX("1792x1344"),204800, 1792,1920,2120,2448,0, 1344,1345,1348,1394,0, V_NHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("896x672"),102400, 896,960,1060,1224,0, 672,672,674,697,0, V_NHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 1792x1344 @ 75Hz (VESA) hsync: 106.3kHz */
+ {MODEPREFIX("1792x1344"),261000, 1792,1888,2104,2456,0, 1344,1345,1348,1417,0, V_NHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("896x672"),130500, 896,944,1052,1228,0, 672,672,674,708,0, V_NHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 1856x1392 @ 60Hz (VESA) hsync: 86.3kHz */
+ {MODEPREFIX("1856x1392"),218300, 1856,1952,2176,2528,0, 1392,1393,1396,1439,0, V_NHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("928x696"),109150, 928,976,1088,1264,0, 696,696,698,719,0, V_NHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 1856x1392 @ 75Hz (VESA) hsync: 112.5kHz */
+ {MODEPREFIX("1856x1392"),288000, 1856,1984,2208,2560,0, 1392,1393,1396,1500,0, V_NHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("928x696"),144000, 928,992,1104,1280,0, 696,696,698,750,0, V_NHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 1920x1440 @ 60Hz (VESA) hsync: 90.0kHz */
+ {MODEPREFIX("1920x1440"),234000, 1920,2048,2256,2600,0, 1440,1441,1444,1500,0, V_NHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("960x720"),117000, 960,1024,1128,1300,0, 720,720,722,750,0, V_NHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 1920x1440 @ 75Hz (VESA) hsync: 112.5kHz */
+ {MODEPREFIX("1920x1440"),297000, 1920,2064,2288,2640,0, 1440,1441,1444,1500,0, V_NHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("960x720"),148500, 960,1032,1144,1320,0, 720,720,722,750,0, V_NHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 832x624 @ 75Hz (74.55Hz) (fix if the official/Apple spec is different) hsync: 49.725kHz */
+ {MODEPREFIX("832x624"),57284, 832,864,928,1152,0, 624,625,628,667,0, V_NHSYNC | V_NVSYNC, MODESUFFIX},
+ {MODEPREFIX("416x312"),28642, 416,432,464,576,0, 312,312,314,333,0, V_NHSYNC | V_NVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 1152x768 @ 54.8Hz (Titanium PowerBook) hsync: 44.2kHz */
+ {MODEPREFIX("1152x768"),64995, 1152,1178,1314,1472,0, 768,771,777,806,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("576x384"),32497, 576,589,657,736,0, 384,385,388,403,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 1400x1050 @ 60Hz (VESA GTF) hsync: 65.5kHz */
+ {MODEPREFIX("1400x1050"),122000, 1400,1488,1640,1880,0, 1050,1052,1064,1082,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("700x525"),61000, 700,744,820,940,0, 525,526,532,541,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 1400x1050 @ 75Hz (VESA GTF) hsync: 82.2kHz */
+ {MODEPREFIX("1400x1050"),155800, 1400,1464,1784,1912,0, 1050,1052,1064,1090,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("700x525"),77900, 700,732,892,956,0, 525,526,532,545,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 1600x1024 @ 60Hz (SGI 1600SW) hsync: 64.0kHz */
+ {MODEPREFIX("1600x1024"),106910, 1600,1620,1640,1670,0, 1024,1027,1030,1067,0, V_NHSYNC | V_NVSYNC, MODESUFFIX},
+ {MODEPREFIX("800x512"),53455, 800,810,820,835,0, 512,513,515,533,0, V_NHSYNC | V_NVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 1920x1440 @ 85Hz (VESA GTF) hsync: 128.5kHz */
+ {MODEPREFIX("1920x1440"),341350, 1920,2072,2288,2656,0, 1440,1441,1444,1512,0, V_NHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("960x720"),170675, 960,1036,1144,1328,0, 720,720,722,756,0, V_NHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 2048x1536 @ 60Hz (VESA GTF) hsync: 95.3kHz */
+ {MODEPREFIX("2048x1536"),266950, 2048,2200,2424,2800,0, 1536,1537,1540,1589,0, V_NHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("1024x768"),133475, 1024,1100,1212,1400,0, 768,768,770,794,0, V_NHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 2048x1536 @ 75Hz (VESA GTF) hsync: 120.2kHz */
+ {MODEPREFIX("2048x1536"),340480, 2048,2216,2440,2832,0, 1536,1537,1540,1603,0, V_NHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("1024x768"),170240, 1024,1108,1220,1416,0, 768,768,770,801,0, V_NHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+/* 2048x1536 @ 85Hz (VESA GTF) hsync: 137.0kHz */
+ {MODEPREFIX("2048x1536"),388040, 2048,2216,2440,2832,0, 1536,1537,1540,1612,0, V_NHSYNC | V_PVSYNC, MODESUFFIX},
+ {MODEPREFIX("1024x768"),194020, 1024,1108,1220,1416,0, 768,768,770,806,0, V_NHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
+ {MODEPREFIX(NULL),0,0,0,0,0,0,0,0,0,0,0,0,MODESUFFIX}
+};
diff --git a/hw/xfree86/common/xf86DoProbe.c b/hw/xfree86/common/xf86DoProbe.c
new file mode 100644
index 000000000..518f67214
--- /dev/null
+++ b/hw/xfree86/common/xf86DoProbe.c
@@ -0,0 +1,83 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86DoProbe.c,v 1.11 2002/07/02 02:00:03 tsi Exp $ */
+/*
+ * finish setting up the server
+ * Load the driver modules and call their probe functions.
+ *
+ * Copyright 1999 by The XFree86 Project, Inc.
+ *
+ */
+
+#include <ctype.h>
+#include <stdlib.h>
+#include "X.h"
+#include "Xmd.h"
+#include "os.h"
+#ifdef XFree86LOADER
+#include "loaderProcs.h"
+#include "xf86Config.h"
+#endif /* XFree86LOADER */
+#include "xf86.h"
+#include "xf86Priv.h"
+
+void
+DoProbeArgs(int argc, char **argv, int i)
+{
+}
+
+void
+DoProbe()
+{
+ int i;
+ Bool probeResult;
+
+#ifdef XFree86LOADER
+ /* Find the list of video driver modules. */
+ char **list = xf86DriverlistFromCompile();
+ char **l;
+
+ if (list) {
+ ErrorF("List of video driver modules:\n");
+ for (l = list; *l; l++)
+ ErrorF("\t%s\n", *l);
+ } else {
+ ErrorF("No video driver modules found\n");
+ }
+
+ /* Load all the drivers that were found. */
+ xf86LoadModules(list, NULL);
+#endif /* XFree86LOADER */
+
+ /* Disable PCI devices */
+ xf86AccessInit();
+
+ /* Call all of the probe functions, reporting the results. */
+ for (i = 0; i < xf86NumDrivers; i++) {
+ if (xf86DriverList[i]->Probe == NULL) continue;
+
+ xf86MsgVerb(X_INFO, 3, "Probing in driver %s\n",
+ xf86DriverList[i]->driverName);
+ probeResult =
+ (*xf86DriverList[i]->Probe)(xf86DriverList[i], PROBE_DETECT);
+ if (!probeResult) {
+ xf86ErrorF("Probe in driver `%s' returns FALSE\n",
+ xf86DriverList[i]->driverName);
+ } else {
+ xf86ErrorF("Probe in driver `%s' returns TRUE\n",
+ xf86DriverList[i]->driverName);
+
+ /* If we have a result, then call driver's Identify function */
+ if (xf86DriverList[i]->Identify != NULL) {
+ int verbose = xf86Verbose;
+
+ xf86Verbose = 1;
+ (*xf86DriverList[i]->Identify)(0);
+ xf86Verbose = verbose;
+ }
+ }
+ }
+
+ OsCleanup();
+ AbortDDX();
+ fflush(stderr);
+ exit(0);
+}
diff --git a/hw/xfree86/common/xf86DoScanPci.c b/hw/xfree86/common/xf86DoScanPci.c
new file mode 100644
index 000000000..2328d2b05
--- /dev/null
+++ b/hw/xfree86/common/xf86DoScanPci.c
@@ -0,0 +1,97 @@
+
+/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86DoScanPci.c,v 1.12 2002/07/15 20:46:01 dawes Exp $ */
+/*
+ * Finish setting up the server.
+ * Call the functions from the scanpci module.
+ *
+ * Copyright 1999-2002 by The XFree86 Project, Inc.
+ *
+ */
+
+#include <ctype.h>
+#include <stdlib.h>
+#include "X.h"
+#include "Xmd.h"
+#include "os.h"
+#ifdef XFree86LOADER
+#include "loaderProcs.h"
+#endif
+#include "xf86.h"
+#include "xf86Priv.h"
+#include "xf86Pci.h"
+#include "xf86ScanPci.h"
+
+
+void DoScanPci(int argc, char **argv, int i)
+{
+ int j,skip,globalVerbose,scanpciVerbose;
+ ScanPciSetupProcPtr PciSetup;
+ ScanPciDisplayCardInfoProcPtr DisplayPCICardInfo;
+#ifdef XFree86LOADER
+ int errmaj, errmin;
+#endif
+
+ /*
+ * first we need to finish setup of the OS so that we can call other
+ * functions in the server
+ */
+ OsInit();
+
+ /*
+ * now we decrease verbosity and remember the value, in case a later
+ * -verbose on the command line increases it, because that is a
+ * verbose flag for scanpci...
+ */
+ globalVerbose = --xf86Verbose;
+ /*
+ * next we process the arguments that are remaining on the command line,
+ * so that things like the module path can be set there
+ */
+ for ( j = i+1; j < argc; j++ ) {
+ if ((skip = ddxProcessArgument(argc, argv, j)))
+ j += (skip - 1);
+ }
+ /*
+ * was the verbosity level increased?
+ */
+ if( (globalVerbose == 0) && (xf86Verbose > 0) )
+ scanpciVerbose = xf86Verbose - globalVerbose -1;
+ else
+ scanpciVerbose = xf86Verbose - globalVerbose;
+ xf86Verbose = globalVerbose;
+ /*
+ * now get the loader set up and load the scanpci module
+ */
+#ifdef XFree86LOADER
+ /* Initialise the loader */
+ LoaderInit();
+ /* Tell the loader the default module search path */
+ LoaderSetPath(xf86ModulePath);
+
+ if (!LoadModule("scanpci", NULL, NULL, NULL, NULL, NULL,
+ &errmaj, &errmin)) {
+ LoaderErrorMsg(NULL, "scanpci", errmaj, errmin);
+ exit(1);
+ }
+ if (LoaderCheckUnresolved(LD_RESOLV_IFDONE)) {
+ /* For now, just a warning */
+ xf86Msg(X_WARNING, "Some symbols could not be resolved!\n");
+ }
+ PciSetup = (ScanPciSetupProcPtr)LoaderSymbol("ScanPciSetupPciIds");
+ DisplayPCICardInfo =
+ (ScanPciDisplayCardInfoProcPtr)LoaderSymbol("ScanPciDisplayPCICardInfo");
+#else
+ PciSetup = ScanPciSetupPciIds;
+ DisplayPCICardInfo = ScanPciDisplayPCICardInfo;
+#endif
+
+ if (!(*PciSetup)())
+ FatalError("ScanPciSetupPciIds() failed\n");
+ (*DisplayPCICardInfo)(scanpciVerbose);
+
+ /*
+ * That's it; we really should clean things up, but a simple
+ * exit seems to be all we need.
+ */
+ exit(0);
+}
diff --git a/hw/xfree86/common/xf86Globals.c b/hw/xfree86/common/xf86Globals.c
new file mode 100644
index 000000000..99c53fb0b
--- /dev/null
+++ b/hw/xfree86/common/xf86Globals.c
@@ -0,0 +1,224 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86Globals.c,v 1.40 2003/02/20 04:05:14 dawes Exp $ */
+
+/*
+ * Copyright (c) 1997 by The XFree86 Project, Inc.
+ */
+
+/*
+ * This file contains all the XFree86 global variables.
+ */
+
+#include "X.h"
+#include "os.h"
+#include "windowstr.h"
+#include "propertyst.h"
+#include "xf86.h"
+#include "xf86Priv.h"
+#include "xf86Parser.h"
+#include "xf86Xinput.h"
+#include "xf86InPriv.h"
+
+/* Globals that video drivers may access */
+
+int xf86ScreenIndex = -1; /* Index of ScrnInfo in pScreen.devPrivates */
+int xf86CreateRootWindowIndex = -1; /* Index into pScreen.devPrivates */
+ScrnInfoPtr *xf86Screens = NULL; /* List of ScrnInfos */
+int xf86PixmapIndex = 0;
+const unsigned char byte_reversed[256] =
+{
+ 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
+ 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
+ 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
+ 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
+ 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
+ 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
+ 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
+ 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
+ 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
+ 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
+ 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
+ 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
+ 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
+ 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
+ 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
+ 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
+ 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
+ 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
+ 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
+ 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
+ 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
+ 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
+ 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
+ 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
+ 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
+ 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
+ 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
+ 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
+ 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
+ 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
+ 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
+ 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
+};
+
+/* Globals that input drivers may access */
+InputInfoPtr xf86InputDevs = NULL;
+
+
+/* Globals that video drivers may not access */
+
+xf86InfoRec xf86Info = {
+ NULL, /* pKeyboard */
+ NULL, /* kbdProc */
+ NULL, /* kbdEvents */
+ -1, /* consoleFd */
+ -1, /* kbdFd */
+ -1, /* vtno */
+ -1, /* kbdType */
+ -1, /* kbdRate */
+ -1, /* kbdDelay */
+ -1, /* bell_pitch */
+ -1, /* bell_duration */
+ TRUE, /* autoRepeat */
+ 0, /* leds */
+ 0, /* xleds */
+ NULL, /* vtinit */
+ 0, /* scanPrefix */
+ FALSE, /* capsLock */
+ FALSE, /* numLock */
+ FALSE, /* scrollLock */
+ FALSE, /* modeSwitchLock */
+ FALSE, /* composeLock */
+ FALSE, /* vtSysreq */
+ SKWhenNeeded, /* ddxSpecialKeys */
+ FALSE, /* ActionKeyBindingsSet */
+#if defined(SVR4) && defined(i386)
+ FALSE, /* panix106 */
+#endif
+#if defined(__OpenBSD__) || defined(__NetBSD__)
+ 0, /* wskbdType */
+#endif
+ NULL, /* pMouse */
+#ifdef XINPUT
+ NULL, /* mouseLocal */
+#endif
+ -1, /* lastEventTime */
+ FALSE, /* vtRequestsPending */
+ FALSE, /* inputPending */
+ FALSE, /* dontVTSwitch */
+ FALSE, /* dontZap */
+ FALSE, /* dontZoom */
+ FALSE, /* notrapSignals */
+ FALSE, /* caughtSignal */
+ FALSE, /* sharedMonitor */
+ NULL, /* currentScreen */
+#ifdef CSRG_BASED
+ -1, /* screenFd */
+ -1, /* consType */
+#endif
+#ifdef XKB
+ NULL, /* xkbkeymap */
+ NULL, /* xkbkeycodes */
+ NULL, /* xkbtypes */
+ NULL, /* xkbcompat */
+ NULL, /* xkbsymbols */
+ NULL, /* xkbgeometry */
+ FALSE, /* xkbcomponents_specified */
+ NULL, /* xkbrules */
+ NULL, /* xkbmodel */
+ NULL, /* xkblayout */
+ NULL, /* xkbvariant */
+ NULL, /* xkboptions */
+#endif
+ FALSE, /* allowMouseOpenFail */
+ TRUE, /* vidModeEnabled */
+ FALSE, /* vidModeAllowNonLocal */
+ TRUE, /* miscModInDevEnabled */
+ FALSE, /* miscModInDevAllowNonLocal */
+ PCIProbe1, /* pciFlags */
+ Pix24DontCare, /* pixmap24 */
+ X_DEFAULT, /* pix24From */
+#if defined(i386) || defined(__i386__)
+ FALSE, /* pc98 */
+#endif
+ TRUE, /* pmFlag */
+ LogNone, /* syncLog */
+ 0, /* estimateSizesAggressively */
+ FALSE, /* kbdCustomKeycodes */
+ FALSE, /* disableRandR */
+ X_DEFAULT /* randRFrom */
+};
+const char *xf86ConfigFile = NULL;
+const char *xf86InputDeviceList = NULL;
+const char *xf86ModulePath = DEFAULT_MODULE_PATH;
+MessageType xf86ModPathFrom = X_DEFAULT;
+const char *xf86LogFile = DEFAULT_LOGPREFIX;
+MessageType xf86LogFileFrom = X_DEFAULT;
+Bool xf86LogFileWasOpened = FALSE;
+serverLayoutRec xf86ConfigLayout = {NULL, };
+confDRIRec xf86ConfigDRI = {0, };
+XF86ConfigPtr xf86configptr = NULL;
+Bool xf86Resetting = FALSE;
+Bool xf86Initialising = FALSE;
+Bool xf86ProbeFailed = FALSE;
+Bool xf86DoProbe = FALSE;
+Bool xf86DoConfigure = FALSE;
+#ifdef XFree86LOADER
+DriverPtr *xf86DriverList = NULL;
+int xf86NumDrivers = 0;
+InputDriverPtr *xf86InputDriverList = NULL;
+int xf86NumInputDrivers = 0;
+ModuleInfoPtr *xf86ModuleInfoList = NULL;
+int xf86NumModuleInfos = 0;
+#endif
+int xf86NumScreens = 0;
+
+const char *xf86VisualNames[] = {
+ "StaticGray",
+ "GrayScale",
+ "StaticColor",
+ "PseudoColor",
+ "TrueColor",
+ "DirectColor"
+};
+
+/* Parameters set only from the command line */
+char *xf86ServerName = "no-name";
+Bool xf86fpFlag = FALSE;
+Bool xf86coFlag = FALSE;
+Bool xf86sFlag = FALSE;
+Bool xf86bsEnableFlag = FALSE;
+Bool xf86bsDisableFlag = FALSE;
+Bool xf86silkenMouseDisableFlag = FALSE;
+char *xf86LayoutName = NULL;
+char *xf86ScreenName = NULL;
+char *xf86PointerName = NULL;
+char *xf86KeyboardName = NULL;
+Bool xf86ProbeOnly = FALSE;
+int xf86Verbose = DEFAULT_VERBOSE;
+int xf86LogVerbose = DEFAULT_LOG_VERBOSE;
+int xf86FbBpp = -1;
+Pix24Flags xf86Pix24 = Pix24DontCare;
+int xf86Depth = -1;
+rgb xf86Weight = {0, 0, 0};
+Bool xf86FlipPixels = FALSE;
+Gamma xf86Gamma = {0.0, 0.0, 0.0};
+Bool xf86ShowUnresolved = DEFAULT_UNRESOLVED;
+Bool xf86BestRefresh = DEFAULT_BEST_REFRESH;
+Bool xf86AllowMouseOpenFail = FALSE;
+#ifdef XF86VIDMODE
+Bool xf86VidModeDisabled = FALSE;
+Bool xf86VidModeAllowNonLocal = FALSE;
+#endif
+#ifdef XF86MISC
+Bool xf86MiscModInDevDisabled = FALSE;
+Bool xf86MiscModInDevAllowNonLocal = FALSE;
+#endif
+PropertyPtr *xf86RegisteredPropertiesTable = NULL;
+Bool xf86inSuspend = FALSE;
+
+#ifdef DLOPEN_HACK
+/*
+ * This stuff is a hack to allow dlopen() modules to work. It is intended
+ * only to be used when using dlopen() modules for debugging purposes.
+ */
+#endif
diff --git a/hw/xfree86/common/xf86Helper.c b/hw/xfree86/common/xf86Helper.c
new file mode 100644
index 000000000..73050eab7
--- /dev/null
+++ b/hw/xfree86/common/xf86Helper.c
@@ -0,0 +1,2994 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86Helper.c,v 1.128 2003/02/26 23:45:24 dawes Exp $ */
+
+/*
+ * Copyright (c) 1997-1998 by The XFree86 Project, Inc.
+ *
+ * Authors: Dirk Hohndel <hohndel@XFree86.Org>
+ * David Dawes <dawes@XFree86.Org>
+ *
+ * This file includes the helper functions that the server provides for
+ * different drivers.
+ */
+
+#include "X.h"
+#include "os.h"
+#include "servermd.h"
+#include "pixmapstr.h"
+#include "windowstr.h"
+#include "propertyst.h"
+#include "gcstruct.h"
+#include "loaderProcs.h"
+#include "xf86.h"
+#include "xf86Priv.h"
+#include "xf86_OSlib.h"
+#include "micmap.h"
+#include "xf86PciInfo.h"
+#include "xf86DDC.h"
+#include "xf86Xinput.h"
+#include "xf86InPriv.h"
+#include "mivalidate.h"
+#include "xf86RAC.h"
+#include "xf86Bus.h"
+#include "xf86Version.h"
+
+/* For xf86GetClocks */
+#if defined(CSRG_BASED) || defined(__GNU__)
+#define HAS_SETPRIORITY
+#include <sys/resource.h>
+#endif
+
+static int xf86ScrnInfoPrivateCount = 0;
+static FILE *logfile = NULL;
+
+
+#ifdef XFree86LOADER
+/* Add a pointer to a new DriverRec to xf86DriverList */
+
+void
+xf86AddDriver(DriverPtr driver, pointer module, int flags)
+{
+ /* Don't add null entries */
+ if (!driver)
+ return;
+
+ if (xf86DriverList == NULL)
+ xf86NumDrivers = 0;
+
+ xf86NumDrivers++;
+ xf86DriverList = xnfrealloc(xf86DriverList,
+ xf86NumDrivers * sizeof(DriverPtr));
+ xf86DriverList[xf86NumDrivers - 1] = xnfalloc(sizeof(DriverRec));
+ *xf86DriverList[xf86NumDrivers - 1] = *driver;
+ xf86DriverList[xf86NumDrivers - 1]->module = module;
+ xf86DriverList[xf86NumDrivers - 1]->refCount = 0;
+}
+
+void
+xf86DeleteDriver(int drvIndex)
+{
+ if (xf86DriverList[drvIndex]
+ && (!xf86DriverHasEntities(xf86DriverList[drvIndex]))) {
+ if (xf86DriverList[drvIndex]->module)
+ UnloadModule(xf86DriverList[drvIndex]->module);
+ xfree(xf86DriverList[drvIndex]);
+ xf86DriverList[drvIndex] = NULL;
+ }
+}
+
+/* Add a pointer to a new InputDriverRec to xf86InputDriverList */
+
+void
+xf86AddInputDriver(InputDriverPtr driver, pointer module, int flags)
+{
+ /* Don't add null entries */
+ if (!driver)
+ return;
+
+ if (xf86InputDriverList == NULL)
+ xf86NumInputDrivers = 0;
+
+ xf86NumInputDrivers++;
+ xf86InputDriverList = xnfrealloc(xf86InputDriverList,
+ xf86NumInputDrivers * sizeof(InputDriverPtr));
+ xf86InputDriverList[xf86NumInputDrivers - 1] =
+ xnfalloc(sizeof(InputDriverRec));
+ *xf86InputDriverList[xf86NumInputDrivers - 1] = *driver;
+ xf86InputDriverList[xf86NumInputDrivers - 1]->module = module;
+ xf86InputDriverList[xf86NumInputDrivers - 1]->refCount = 0;
+}
+
+void
+xf86DeleteInputDriver(int drvIndex)
+{
+ if (xf86InputDriverList[drvIndex] && xf86InputDriverList[drvIndex]->module)
+ UnloadModule(xf86InputDriverList[drvIndex]->module);
+ xfree(xf86InputDriverList[drvIndex]);
+ xf86InputDriverList[drvIndex] = NULL;
+}
+
+void
+xf86AddModuleInfo(ModuleInfoPtr info, pointer module)
+{
+ /* Don't add null entries */
+ if (!module)
+ return;
+
+ if (xf86ModuleInfoList == NULL)
+ xf86NumModuleInfos = 0;
+
+ xf86NumModuleInfos++;
+ xf86ModuleInfoList = xnfrealloc(xf86ModuleInfoList,
+ xf86NumModuleInfos * sizeof(ModuleInfoPtr));
+ xf86ModuleInfoList[xf86NumModuleInfos - 1] = xnfalloc(sizeof(ModuleInfoRec));
+ *xf86ModuleInfoList[xf86NumModuleInfos - 1] = *info;
+ xf86ModuleInfoList[xf86NumModuleInfos - 1]->module = module;
+ xf86ModuleInfoList[xf86NumModuleInfos - 1]->refCount = 0;
+}
+
+void
+xf86DeleteModuleInfo(int idx)
+{
+ if (xf86ModuleInfoList[idx]) {
+ if (xf86ModuleInfoList[idx]->module)
+ UnloadModule(xf86ModuleInfoList[idx]->module);
+ xfree(xf86ModuleInfoList[idx]);
+ xf86ModuleInfoList[idx] = NULL;
+ }
+}
+#endif
+
+
+/* Allocate a new ScrnInfoRec in xf86Screens */
+
+ScrnInfoPtr
+xf86AllocateScreen(DriverPtr drv, int flags)
+{
+ int i;
+
+ if (xf86Screens == NULL)
+ xf86NumScreens = 0;
+
+ i = xf86NumScreens++;
+ xf86Screens = xnfrealloc(xf86Screens, xf86NumScreens * sizeof(ScrnInfoPtr));
+ xf86Screens[i] = xnfcalloc(sizeof(ScrnInfoRec), 1);
+ xf86Screens[i]->scrnIndex = i; /* Changes when a screen is removed */
+ xf86Screens[i]->origIndex = i; /* This never changes */
+ xf86Screens[i]->privates = xnfcalloc(sizeof(DevUnion),
+ xf86ScrnInfoPrivateCount);
+ /*
+ * EnableDisableFBAccess now gets initialized in InitOutput()
+ * xf86Screens[i]->EnableDisableFBAccess = xf86EnableDisableFBAccess;
+ */
+
+ xf86Screens[i]->drv = drv;
+ drv->refCount++;
+#ifdef XFree86LOADER
+ xf86Screens[i]->module = DuplicateModule(drv->module, NULL);
+#else
+ xf86Screens[i]->module = NULL;
+#endif
+ /*
+ * set the initial access state. This will be modified after PreInit.
+ * XXX Or should we do it some other place?
+ */
+ xf86Screens[i]->CurrentAccess = &xf86CurrentAccess;
+ xf86Screens[i]->resourceType = MEM_IO;
+
+#ifdef DEBUG
+ /* OOps -- What's this ? */
+ ErrorF("xf86AllocateScreen - xf86Screens[%d]->pScreen = %p\n",
+ i, xf86Screens[i]->pScreen );
+ if ( NULL != xf86Screens[i]->pScreen ) {
+ ErrorF("xf86Screens[%d]->pScreen->CreateWindow = %p\n",
+ i, xf86Screens[i]->pScreen->CreateWindow );
+ }
+#endif
+
+ return xf86Screens[i];
+}
+
+
+/*
+ * Remove an entry from xf86Screens. Ideally it should free all allocated
+ * data. To do this properly may require a driver hook.
+ */
+
+void
+xf86DeleteScreen(int scrnIndex, int flags)
+{
+ ScrnInfoPtr pScrn;
+ int i;
+
+ /* First check if the screen is valid */
+ if (xf86NumScreens == 0 || xf86Screens == NULL)
+ return;
+
+ if (scrnIndex > xf86NumScreens - 1)
+ return;
+
+ if (!(pScrn = xf86Screens[scrnIndex]))
+ return;
+
+ /* If a FreeScreen function is defined, call it here */
+ if (pScrn->FreeScreen != NULL)
+ pScrn->FreeScreen(scrnIndex, 0);
+
+ while (pScrn->modes)
+ xf86DeleteMode(&pScrn->modes, pScrn->modes);
+
+ while (pScrn->modePool)
+ xf86DeleteMode(&pScrn->modePool, pScrn->modePool);
+
+ xf86OptionListFree(pScrn->options);
+
+#ifdef XFree86LOADER
+ if (pScrn->module)
+ UnloadModule(pScrn->module);
+#endif
+
+ if (pScrn->drv)
+ pScrn->drv->refCount--;
+
+ if (pScrn->privates);
+ xfree(pScrn->privates);
+
+ xf86ClearEntityListForScreen(scrnIndex);
+
+ xfree(pScrn);
+
+ /* Move the other entries down, updating their scrnIndex fields */
+
+ xf86NumScreens--;
+
+ for (i = scrnIndex; i < xf86NumScreens; i++) {
+ xf86Screens[i] = xf86Screens[i + 1];
+ xf86Screens[i]->scrnIndex = i;
+ /* Also need to take care of the screen layout settings */
+ }
+}
+
+/*
+ * Allocate a private in ScrnInfoRec.
+ */
+
+int
+xf86AllocateScrnInfoPrivateIndex(void)
+{
+ int idx, i;
+ ScrnInfoPtr pScr;
+ DevUnion *nprivs;
+
+ idx = xf86ScrnInfoPrivateCount++;
+ for (i = 0; i < xf86NumScreens; i++) {
+ pScr = xf86Screens[i];
+ nprivs = xnfrealloc(pScr->privates,
+ xf86ScrnInfoPrivateCount * sizeof(DevUnion));
+ /* Zero the new private */
+ bzero(&nprivs[idx], sizeof(DevUnion));
+ pScr->privates = nprivs;
+ }
+ return idx;
+}
+
+/* Allocate a new InputInfoRec and add it to the head xf86InputDevs. */
+
+InputInfoPtr
+xf86AllocateInput(InputDriverPtr drv, int flags)
+{
+ InputInfoPtr new;
+
+ if (!(new = xcalloc(sizeof(InputInfoRec), 1)))
+ return NULL;
+
+ new->drv = drv;
+ drv->refCount++;
+#ifdef XFree86LOADER
+ new->module = DuplicateModule(drv->module, NULL);
+#else
+ new->module = NULL;
+#endif
+ new->next = xf86InputDevs;
+ xf86InputDevs = new;
+ return new;
+}
+
+
+/*
+ * Remove an entry from xf86InputDevs. Ideally it should free all allocated
+ * data. To do this properly may require a driver hook.
+ */
+
+void
+xf86DeleteInput(InputInfoPtr pInp, int flags)
+{
+ InputInfoPtr p;
+
+ /* First check if the inputdev is valid. */
+ if (pInp == NULL)
+ return;
+
+#if 0
+ /* If a free function is defined, call it here. */
+ if (pInp->free)
+ pInp->free(pInp, 0);
+#endif
+
+#ifdef XFree86LOADER
+ if (pInp->module)
+ UnloadModule(pInp->module);
+#endif
+
+ if (pInp->drv)
+ pInp->drv->refCount--;
+
+ if (pInp->private);
+ xfree(pInp->private);
+
+ /* Remove the entry from the list. */
+ if (pInp == xf86InputDevs)
+ xf86InputDevs = pInp->next;
+ else {
+ p = xf86InputDevs;
+ while (p && p->next != pInp)
+ p = p->next;
+ if (p)
+ p->next = pInp->next;
+ /* Else the entry wasn't in the xf86InputDevs list (ignore this). */
+ }
+ xfree(pInp);
+}
+
+Bool
+xf86AddPixFormat(ScrnInfoPtr pScrn, int depth, int bpp, int pad)
+{
+ int i;
+
+ if (pScrn->numFormats >= MAXFORMATS)
+ return FALSE;
+
+ if (bpp <= 0) {
+ if (depth == 1)
+ bpp = 1;
+ else if (depth <= 8)
+ bpp = 8;
+ else if (depth <= 16)
+ bpp = 16;
+ else if (depth <= 32)
+ bpp = 32;
+ else
+ return FALSE;
+ }
+ if (pad <= 0)
+ pad = BITMAP_SCANLINE_PAD;
+
+ i = pScrn->numFormats++;
+ pScrn->formats[i].depth = depth;
+ pScrn->formats[i].bitsPerPixel = bpp;
+ pScrn->formats[i].scanlinePad = pad;
+ return TRUE;
+}
+
+/*
+ * Set the depth we are using based on (in the following order of preference):
+ * - values given on the command line
+ * - values given in the config file
+ * - values provided by the driver
+ * - an overall default when nothing else is given
+ *
+ * Also find a Display subsection matching the depth/bpp found.
+ *
+ * Sets the following ScrnInfoRec fields:
+ * bitsPerPixel, pixmap24, depth, display, imageByteOrder,
+ * bitmapScanlinePad, bitmapScanlineUnit, bitmapBitOrder, numFormats,
+ * formats, fbFormat.
+ */
+
+/* Can the screen handle 24 bpp pixmaps */
+#define DO_PIX24(f) ((f & Support24bppFb) || \
+ ((f & Support32bppFb) && (f & SupportConvert24to32)))
+
+/* Can the screen handle 32 bpp pixmaps */
+#define DO_PIX32(f) ((f & Support32bppFb) || \
+ ((f & Support24bppFb) && (f & SupportConvert32to24)))
+
+/* Does the screen prefer 32bpp fb for 24bpp pixmaps */
+#define CHOOSE32FOR24(f) ((f & Support32bppFb) && (f & SupportConvert24to32) \
+ && (f & PreferConvert24to32))
+
+/* Does the screen prefer 24bpp fb for 32bpp pixmaps */
+#define CHOOSE24FOR32(f) ((f & Support24bppFb) && (f & SupportConvert32to24) \
+ && (f & PreferConvert32to24))
+
+/* Can the screen handle 32bpp pixmaps for 24bpp fb */
+#define DO_PIX32FOR24(f) ((f & Support24bppFb) && (f & SupportConvert32to24))
+
+/* Can the screen handle 24bpp pixmaps for 32bpp fb */
+#define DO_PIX24FOR32(f) ((f & Support32bppFb) && (f & SupportConvert24to32))
+
+Bool
+xf86SetDepthBpp(ScrnInfoPtr scrp, int depth, int dummy, int fbbpp,
+ int depth24flags)
+{
+ int i;
+ DispPtr disp;
+ Pix24Flags pix24 = xf86Info.pixmap24;
+ Bool nomatch = FALSE;
+
+ scrp->bitsPerPixel = -1;
+ scrp->depth = -1;
+ scrp->pixmap24 = Pix24DontCare;
+ scrp->bitsPerPixelFrom = X_DEFAULT;
+ scrp->depthFrom = X_DEFAULT;
+
+#if BITMAP_SCANLINE_UNIT == 64
+ /*
+ * For platforms with 64-bit scanlines, modify the driver's depth24flags
+ * to remove preferences for packed 24bpp modes, which are not currently
+ * supported on these platforms.
+ */
+ depth24flags &= ~(SupportConvert32to24 | SupportConvert32to24 |
+ PreferConvert24to32 | PreferConvert32to24);
+#endif
+
+ if (xf86FbBpp > 0) {
+ scrp->bitsPerPixel = xf86FbBpp;
+ scrp->bitsPerPixelFrom = X_CMDLINE;
+ }
+
+ if (xf86Depth > 0) {
+ scrp->depth = xf86Depth;
+ scrp->depthFrom = X_CMDLINE;
+ }
+
+ if (xf86FbBpp < 0 && xf86Depth < 0) {
+ if (scrp->confScreen->defaultfbbpp > 0) {
+ scrp->bitsPerPixel = scrp->confScreen->defaultfbbpp;
+ scrp->bitsPerPixelFrom = X_CONFIG;
+ }
+ if (scrp->confScreen->defaultdepth > 0) {
+ scrp->depth = scrp->confScreen->defaultdepth;
+ scrp->depthFrom = X_CONFIG;
+ }
+ }
+
+ /* If none of these is set, pick a default */
+ if (scrp->bitsPerPixel < 0 && scrp->depth < 0) {
+ if (fbbpp > 0 || depth > 0) {
+ if (fbbpp > 0)
+ scrp->bitsPerPixel = fbbpp;
+ if (depth > 0)
+ scrp->depth = depth;
+ } else {
+ scrp->bitsPerPixel = 8;
+ scrp->depth = 8;
+ }
+ }
+
+ /* If any are not given, determine a default for the others */
+
+ if (scrp->bitsPerPixel < 0) {
+ /* The depth must be set */
+ if (scrp->depth > -1) {
+ if (scrp->depth == 1)
+ scrp->bitsPerPixel = 1;
+ else if (scrp->depth <= 4)
+ scrp->bitsPerPixel = 4;
+ else if (scrp->depth <= 8)
+ scrp->bitsPerPixel = 8;
+ else if (scrp->depth <= 16)
+ scrp->bitsPerPixel = 16;
+ else if (scrp->depth <= 24) {
+ /*
+ * Figure out if a choice is possible based on the depth24
+ * and pix24 flags.
+ */
+ /* Check pix24 first */
+ if (pix24 != Pix24DontCare) {
+ if (pix24 == Pix24Use32) {
+ if (DO_PIX32(depth24flags)) {
+ if (CHOOSE24FOR32(depth24flags))
+ scrp->bitsPerPixel = 24;
+ else
+ scrp->bitsPerPixel = 32;
+ } else {
+ nomatch = TRUE;
+ }
+ } else if (pix24 == Pix24Use24) {
+ if (DO_PIX24(depth24flags)) {
+ if (CHOOSE32FOR24(depth24flags))
+ scrp->bitsPerPixel = 32;
+ else
+ scrp->bitsPerPixel = 24;
+ } else {
+ nomatch = TRUE;
+ }
+ }
+ } else {
+ if (DO_PIX32(depth24flags)) {
+ if (CHOOSE24FOR32(depth24flags))
+ scrp->bitsPerPixel = 24;
+ else
+ scrp->bitsPerPixel = 32;
+ } else if (DO_PIX24(depth24flags)) {
+ if (CHOOSE32FOR24(depth24flags))
+ scrp->bitsPerPixel = 32;
+ else
+ scrp->bitsPerPixel = 24;
+ }
+ }
+ } else if (scrp->depth <= 32)
+ scrp->bitsPerPixel = 32;
+ else {
+ xf86DrvMsg(scrp->scrnIndex, X_ERROR,
+ "Specified depth (%d) is greater than 32\n",
+ scrp->depth);
+ return FALSE;
+ }
+ } else {
+ xf86DrvMsg(scrp->scrnIndex, X_ERROR,
+ "xf86SetDepthBpp: internal error: depth and fbbpp"
+ " are both not set\n");
+ return FALSE;
+ }
+ if (scrp->bitsPerPixel < 0) {
+ if (nomatch)
+ xf86DrvMsg(scrp->scrnIndex, X_ERROR,
+ "Driver can't support depth 24 pixmap format (%d)\n",
+ PIX24TOBPP(pix24));
+ else if ((depth24flags & (Support24bppFb | Support32bppFb)) ==
+ NoDepth24Support)
+ xf86DrvMsg(scrp->scrnIndex, X_ERROR,
+ "Driver can't support depth 24\n");
+ else
+ xf86DrvMsg(scrp->scrnIndex, X_ERROR,
+ "Can't find fbbpp for depth 24\n");
+ return FALSE;
+ }
+ scrp->bitsPerPixelFrom = X_PROBED;
+ }
+
+ if (scrp->depth <= 0) {
+ /* bitsPerPixel is already set */
+ switch (scrp->bitsPerPixel) {
+ case 32:
+ scrp->depth = 24;
+ break;
+ default:
+ /* 1, 4, 8, 16 and 24 */
+ scrp->depth = scrp->bitsPerPixel;
+ break;
+ }
+ scrp->depthFrom = X_PROBED;
+ }
+
+ /* Sanity checks */
+ if (scrp->depth < 1 || scrp->depth > 32) {
+ xf86DrvMsg(scrp->scrnIndex, X_ERROR,
+ "Specified depth (%d) is not in the range 1-32\n",
+ scrp->depth);
+ return FALSE;
+ }
+ switch (scrp->bitsPerPixel) {
+ case 1:
+ case 4:
+ case 8:
+ case 16:
+ case 24:
+ case 32:
+ break;
+ default:
+ xf86DrvMsg(scrp->scrnIndex, X_ERROR,
+ "Specified fbbpp (%d) is not a permitted value\n",
+ scrp->bitsPerPixel);
+ return FALSE;
+ }
+ if (scrp->depth > scrp->bitsPerPixel) {
+ xf86DrvMsg(scrp->scrnIndex, X_ERROR,
+ "Specified depth (%d) is greater than the fbbpp (%d)\n",
+ scrp->depth, scrp->bitsPerPixel);
+ return FALSE;
+ }
+
+ /* set scrp->pixmap24 if the driver isn't flexible */
+ if (scrp->bitsPerPixel == 24 && !DO_PIX32FOR24(depth24flags)) {
+ scrp->pixmap24 = Pix24Use24;
+ }
+ if (scrp->bitsPerPixel == 32 && !DO_PIX24FOR32(depth24flags)) {
+ scrp->pixmap24 = Pix24Use32;
+ }
+
+ /*
+ * Find the Display subsection matching the depth/fbbpp and initialise
+ * scrp->display with it.
+ */
+ for (i = 0, disp = scrp->confScreen->displays;
+ i < scrp->confScreen->numdisplays; i++, disp++) {
+ if ((disp->depth == scrp->depth && disp->fbbpp == scrp->bitsPerPixel)
+ || (disp->depth == scrp->depth && disp->fbbpp <= 0)
+ || (disp->fbbpp == scrp->bitsPerPixel && disp->depth <= 0)) {
+ scrp->display = disp;
+ break;
+ }
+ }
+ if (i == scrp->confScreen->numdisplays) {
+ xf86DrvMsg(scrp->scrnIndex, X_ERROR, "No Display subsection "
+ "in Screen section \"%s\" for depth/fbbpp %d/%d\n",
+ scrp->confScreen->id, scrp->depth, scrp->bitsPerPixel);
+ return FALSE;
+ }
+
+ /*
+ * Setup defaults for the display-wide attributes the framebuffer will
+ * need. These defaults should eventually be set globally, and not
+ * dependent on the screens.
+ */
+ scrp->imageByteOrder = IMAGE_BYTE_ORDER;
+ scrp->bitmapScanlinePad = BITMAP_SCANLINE_PAD;
+ if (scrp->depth < 8) {
+ /* Planar modes need these settings */
+ scrp->bitmapScanlineUnit = 8;
+ scrp->bitmapBitOrder = MSBFirst;
+ } else {
+ scrp->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT;
+ scrp->bitmapBitOrder = BITMAP_BIT_ORDER;
+ }
+
+ /*
+ * If an unusual depth is required, add it to scrp->formats. The formats
+ * for the common depths are handled globally in InitOutput
+ */
+ switch (scrp->depth) {
+ case 1:
+ case 4:
+ case 8:
+ case 15:
+ case 16:
+ case 24:
+ /* Common depths. Nothing to do for them */
+ break;
+ default:
+ if (!xf86AddPixFormat(scrp, scrp->depth, 0, 0)) {
+ xf86DrvMsg(scrp->scrnIndex, X_ERROR,
+ "Can't add pixmap format for depth %d\n", scrp->depth);
+ return FALSE;
+ }
+ }
+
+ /* Initialise the framebuffer format for this screen */
+ scrp->fbFormat.depth = scrp->depth;
+ scrp->fbFormat.bitsPerPixel = scrp->bitsPerPixel;
+ scrp->fbFormat.scanlinePad = BITMAP_SCANLINE_PAD;
+
+ return TRUE;
+}
+
+/*
+ * Print out the selected depth and bpp.
+ */
+void
+xf86PrintDepthBpp(ScrnInfoPtr scrp)
+{
+ xf86DrvMsg(scrp->scrnIndex, scrp->depthFrom, "Depth %d, ", scrp->depth);
+ xf86Msg(scrp->bitsPerPixelFrom, "framebuffer bpp %d\n", scrp->bitsPerPixel);
+}
+
+/*
+ * xf86SetWeight sets scrp->weight, scrp->mask, scrp->offset, and for depths
+ * greater than MAX_PSEUDO_DEPTH also scrp->rgbBits.
+ */
+Bool
+xf86SetWeight(ScrnInfoPtr scrp, rgb weight, rgb mask)
+{
+ MessageType weightFrom = X_DEFAULT;
+
+ scrp->weight.red = 0;
+ scrp->weight.green = 0;
+ scrp->weight.blue = 0;
+
+ if (xf86Weight.red > 0 && xf86Weight.green > 0 && xf86Weight.blue > 0) {
+ scrp->weight = xf86Weight;
+ weightFrom = X_CMDLINE;
+ } else if (scrp->display->weight.red > 0 && scrp->display->weight.green > 0
+ && scrp->display->weight.blue > 0) {
+ scrp->weight = scrp->display->weight;
+ weightFrom = X_CONFIG;
+ } else if (weight.red > 0 && weight.green > 0 && weight.blue > 0) {
+ scrp->weight = weight;
+ } else {
+ switch (scrp->depth) {
+ case 1:
+ case 4:
+ case 8:
+ scrp->weight.red = scrp->weight.green =
+ scrp->weight.blue = scrp->rgbBits;
+ break;
+ case 15:
+ scrp->weight.red = scrp->weight.green = scrp->weight.blue = 5;
+ break;
+ case 16:
+ scrp->weight.red = scrp->weight.blue = 5;
+ scrp->weight.green = 6;
+ break;
+ case 24:
+ scrp->weight.red = scrp->weight.green = scrp->weight.blue = 8;
+ break;
+ case 30:
+ scrp->weight.red = scrp->weight.green = scrp->weight.blue = 10;
+ break;
+ }
+ }
+
+ if (scrp->weight.red)
+ xf86DrvMsg(scrp->scrnIndex, weightFrom, "RGB weight %d%d%d\n",
+ scrp->weight.red, scrp->weight.green, scrp->weight.blue);
+
+ if (scrp->depth > MAX_PSEUDO_DEPTH &&
+ (scrp->depth != scrp->weight.red + scrp->weight.green +
+ scrp->weight.blue)) {
+ xf86DrvMsg(scrp->scrnIndex, X_ERROR,
+ "Weight given (%d%d%d) is inconsistent with the "
+ "depth (%d)\n", scrp->weight.red, scrp->weight.green,
+ scrp->weight.blue, scrp->depth);
+ return FALSE;
+ }
+ if (scrp->depth > MAX_PSEUDO_DEPTH && scrp->weight.red) {
+ /*
+ * XXX Does this even mean anything for TrueColor visuals?
+ * If not, we shouldn't even be setting it here. However, this
+ * matches the behaviour of 3.x versions of XFree86.
+ */
+ scrp->rgbBits = scrp->weight.red;
+ if (scrp->weight.green > scrp->rgbBits)
+ scrp->rgbBits = scrp->weight.green;
+ if (scrp->weight.blue > scrp->rgbBits)
+ scrp->rgbBits = scrp->weight.blue;
+ }
+
+ /* Set the mask and offsets */
+ if (mask.red == 0 || mask.green == 0 || mask.blue == 0) {
+ /* Default to a setting common to PC hardware */
+ scrp->offset.red = scrp->weight.green + scrp->weight.blue;
+ scrp->offset.green = scrp->weight.blue;
+ scrp->offset.blue = 0;
+ scrp->mask.red = ((1 << scrp->weight.red) - 1) << scrp->offset.red;
+ scrp->mask.green = ((1 << scrp->weight.green) - 1)
+ << scrp->offset.green;
+ scrp->mask.blue = (1 << scrp->weight.blue) - 1;
+ } else {
+ /* Initialise to the values passed */
+ scrp->mask.red = mask.red;
+ scrp->mask.green = mask.green;
+ scrp->mask.blue = mask.blue;
+ scrp->offset.red = ffs(mask.red);
+ scrp->offset.green = ffs(mask.green);
+ scrp->offset.blue = ffs(mask.blue);
+ }
+ return TRUE;
+}
+
+Bool
+xf86SetDefaultVisual(ScrnInfoPtr scrp, int visual)
+{
+ MessageType visualFrom = X_DEFAULT;
+ Bool bad = FALSE;
+
+ if (defaultColorVisualClass >= 0) {
+ scrp->defaultVisual = defaultColorVisualClass;
+ visualFrom = X_CMDLINE;
+ } else if (scrp->display->defaultVisual >= 0) {
+ scrp->defaultVisual = scrp->display->defaultVisual;
+ visualFrom = X_CONFIG;
+ } else if (visual >= 0) {
+ scrp->defaultVisual = visual;
+ } else {
+ if (scrp->depth == 1)
+ scrp->defaultVisual = StaticGray;
+ else if (scrp->depth == 4)
+ scrp->defaultVisual = StaticColor;
+ else if (scrp->depth <= MAX_PSEUDO_DEPTH)
+ scrp->defaultVisual = PseudoColor;
+ else
+ scrp->defaultVisual = TrueColor;
+ }
+ switch (scrp->defaultVisual) {
+ case StaticGray:
+ case GrayScale:
+ case StaticColor:
+ case PseudoColor:
+ case TrueColor:
+ case DirectColor:
+ xf86DrvMsg(scrp->scrnIndex, visualFrom, "Default visual is %s\n",
+ xf86VisualNames[scrp->defaultVisual]);
+ /* Check if the visual is valid for the depth */
+ if (scrp->depth == 1 && scrp->defaultVisual != StaticGray)
+ bad = TRUE;
+#if 0
+ else if (scrp->depth == 4 &&
+ (scrp->defaultVisual == TrueColor ||
+ scrp->defaultVisual == DirectColor))
+ bad = TRUE;
+#endif
+ else if (scrp->depth > MAX_PSEUDO_DEPTH &&
+ scrp->defaultVisual != TrueColor &&
+ scrp->defaultVisual != DirectColor)
+ bad = TRUE;
+ if (bad) {
+ xf86DrvMsg(scrp->scrnIndex, X_ERROR, "Selected default "
+ "visual (%s) is not valid for depth %d\n",
+ xf86VisualNames[scrp->defaultVisual], scrp->depth);
+ return FALSE;
+ } else
+ return TRUE;
+ default:
+
+ xf86DrvMsg(scrp->scrnIndex, X_ERROR,
+ "Invalid default visual class (%d)\n", scrp->defaultVisual);
+ return FALSE;
+ }
+}
+
+#define TEST_GAMMA(g) \
+ (g).red > GAMMA_ZERO || (g).green > GAMMA_ZERO || (g).blue > GAMMA_ZERO
+
+#define SET_GAMMA(g) \
+ (g) > GAMMA_ZERO ? (g) : 1.0
+
+Bool
+xf86SetGamma(ScrnInfoPtr scrp, Gamma gamma)
+{
+ MessageType from = X_DEFAULT;
+#if 0
+ xf86MonPtr DDC = (xf86MonPtr)(scrp->monitor->DDC);
+#endif
+ if (TEST_GAMMA(xf86Gamma)) {
+ from = X_CMDLINE;
+ scrp->gamma.red = SET_GAMMA(xf86Gamma.red);
+ scrp->gamma.green = SET_GAMMA(xf86Gamma.green);
+ scrp->gamma.blue = SET_GAMMA(xf86Gamma.blue);
+ } else if (TEST_GAMMA(scrp->monitor->gamma)) {
+ from = X_CONFIG;
+ scrp->gamma.red = SET_GAMMA(scrp->monitor->gamma.red);
+ scrp->gamma.green = SET_GAMMA(scrp->monitor->gamma.green);
+ scrp->gamma.blue = SET_GAMMA(scrp->monitor->gamma.blue);
+#if 0
+ } else if ( DDC && DDC->features.gamma > GAMMA_ZERO ) {
+ from = X_PROBED;
+ scrp->gamma.red = SET_GAMMA(DDC->features.gamma);
+ scrp->gamma.green = SET_GAMMA(DDC->features.gamma);
+ scrp->gamma.blue = SET_GAMMA(DDC->features.gamma);
+ /* EDID structure version 2 gives optional seperate red, green & blue gamma values
+ * in bytes 0x57-0x59 */
+#endif
+ } else if (TEST_GAMMA(gamma)) {
+ scrp->gamma.red = SET_GAMMA(gamma.red);
+ scrp->gamma.green = SET_GAMMA(gamma.green);
+ scrp->gamma.blue = SET_GAMMA(gamma.blue);
+ } else {
+ scrp->gamma.red = 1.0;
+ scrp->gamma.green = 1.0;
+ scrp->gamma.blue = 1.0;
+ }
+ xf86DrvMsg(scrp->scrnIndex, from,
+ "Using gamma correction (%.1f, %.1f, %.1f)\n",
+ scrp->gamma.red, scrp->gamma.green, scrp->gamma.blue);
+
+ return TRUE;
+}
+
+#undef TEST_GAMMA
+#undef SET_GAMMA
+
+
+/*
+ * Set the DPI from the command line option. XXX should allow it to be
+ * calculated from the widthmm/heightmm values.
+ */
+
+#undef MMPERINCH
+#define MMPERINCH 25.4
+
+void
+xf86SetDpi(ScrnInfoPtr pScrn, int x, int y)
+{
+ MessageType from = X_DEFAULT;
+ xf86MonPtr DDC = (xf86MonPtr)(pScrn->monitor->DDC);
+ int ddcWidthmm, ddcHeightmm;
+ int widthErr, heightErr;
+
+ /* XXX Maybe there is no need for widthmm/heightmm in ScrnInfoRec */
+ pScrn->widthmm = pScrn->monitor->widthmm;
+ pScrn->heightmm = pScrn->monitor->heightmm;
+
+ if (DDC && (DDC->features.hsize > 0 && DDC->features.vsize > 0) ) {
+ /* DDC gives display size in mm for individual modes,
+ * but cm for monitor
+ */
+ ddcWidthmm = DDC->features.hsize * 10; /* 10mm in 1cm */
+ ddcHeightmm = DDC->features.vsize * 10; /* 10mm in 1cm */
+ } else {
+ ddcWidthmm = ddcHeightmm = 0;
+ }
+
+ if (monitorResolution > 0) {
+ pScrn->xDpi = monitorResolution;
+ pScrn->yDpi = monitorResolution;
+ from = X_CMDLINE;
+ } else if (pScrn->widthmm > 0 || pScrn->heightmm > 0) {
+ from = X_CONFIG;
+ if (pScrn->widthmm > 0) {
+ pScrn->xDpi =
+ (int)((double)pScrn->virtualX * MMPERINCH / pScrn->widthmm);
+ }
+ if (pScrn->heightmm > 0) {
+ pScrn->yDpi =
+ (int)((double)pScrn->virtualY * MMPERINCH / pScrn->heightmm);
+ }
+ if (pScrn->xDpi > 0 && pScrn->yDpi <= 0)
+ pScrn->yDpi = pScrn->xDpi;
+ if (pScrn->yDpi > 0 && pScrn->xDpi <= 0)
+ pScrn->xDpi = pScrn->yDpi;
+ xf86DrvMsg(pScrn->scrnIndex, from, "Display dimensions: (%d, %d) mm\n",
+ pScrn->widthmm, pScrn->heightmm);
+
+ /* Warn if config and probe disagree about display size */
+ if ( ddcWidthmm && ddcHeightmm ) {
+ if (pScrn->widthmm > 0) {
+ widthErr = abs(ddcWidthmm - pScrn->widthmm);
+ } else {
+ widthErr = 0;
+ }
+ if (pScrn->heightmm > 0) {
+ heightErr = abs(ddcHeightmm - pScrn->heightmm);
+ } else {
+ heightErr = 0;
+ }
+ if (widthErr>10 || heightErr>10) {
+ /* Should include config file name for monitor here */
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Probed monitor is %dx%d mm, using Displaysize %dx%d mm\n",
+ ddcWidthmm,ddcHeightmm, pScrn->widthmm,pScrn->heightmm);
+ }
+ }
+ } else if ( ddcWidthmm && ddcHeightmm ) {
+ from = X_PROBED;
+ xf86DrvMsg(pScrn->scrnIndex, from, "Display dimensions: (%d, %d) mm\n",
+ ddcWidthmm, ddcHeightmm );
+ pScrn->widthmm = ddcWidthmm;
+ pScrn->heightmm = ddcHeightmm;
+ if (pScrn->widthmm > 0) {
+ pScrn->xDpi =
+ (int)((double)pScrn->virtualX * MMPERINCH / pScrn->widthmm);
+ }
+ if (pScrn->heightmm > 0) {
+ pScrn->yDpi =
+ (int)((double)pScrn->virtualY * MMPERINCH / pScrn->heightmm);
+ }
+ if (pScrn->xDpi > 0 && pScrn->yDpi <= 0)
+ pScrn->yDpi = pScrn->xDpi;
+ if (pScrn->yDpi > 0 && pScrn->xDpi <= 0)
+ pScrn->xDpi = pScrn->yDpi;
+ } else {
+ if (x > 0)
+ pScrn->xDpi = x;
+ else
+ pScrn->xDpi = DEFAULT_DPI;
+ if (y > 0)
+ pScrn->yDpi = y;
+ else
+ pScrn->yDpi = DEFAULT_DPI;
+ }
+ xf86DrvMsg(pScrn->scrnIndex, from, "DPI set to (%d, %d)\n",
+ pScrn->xDpi, pScrn->yDpi);
+}
+
+#undef MMPERINCH
+
+
+void
+xf86SetBlackWhitePixels(ScreenPtr pScreen)
+{
+ if (xf86FlipPixels) {
+ pScreen->whitePixel = 0;
+ pScreen->blackPixel = 1;
+ } else {
+ pScreen->whitePixel = 1;
+ pScreen->blackPixel = 0;
+ }
+}
+
+/*
+ * xf86SetRootClip --
+ * Enable or disable rendering to the screen by
+ * setting the root clip list and revalidating
+ * all of the windows
+ */
+
+static void
+xf86SetRootClip (ScreenPtr pScreen, Bool enable)
+{
+ WindowPtr pWin = WindowTable[pScreen->myNum];
+ WindowPtr pChild;
+ Bool WasViewable = (Bool)(pWin->viewable);
+ Bool anyMarked = FALSE;
+ RegionPtr pOldClip = NULL, bsExposed;
+#ifdef DO_SAVE_UNDERS
+ Bool dosave = FALSE;
+#endif
+ WindowPtr pLayerWin;
+ BoxRec box;
+
+ if (WasViewable)
+ {
+ for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib)
+ {
+ (void) (*pScreen->MarkOverlappedWindows)(pChild,
+ pChild,
+ &pLayerWin);
+ }
+ (*pScreen->MarkWindow) (pWin);
+ anyMarked = TRUE;
+ if (pWin->valdata)
+ {
+ if (HasBorder (pWin))
+ {
+ RegionPtr borderVisible;
+
+ borderVisible = REGION_CREATE(pScreen, NullBox, 1);
+ REGION_SUBTRACT(pScreen, borderVisible,
+ &pWin->borderClip, &pWin->winSize);
+ pWin->valdata->before.borderVisible = borderVisible;
+ }
+ pWin->valdata->before.resized = TRUE;
+ }
+ }
+
+ /*
+ * Use REGION_BREAK to avoid optimizations in ValidateTree
+ * that assume the root borderClip can't change well, normally
+ * it doesn't...)
+ */
+ if (enable)
+ {
+ box.x1 = 0;
+ box.y1 = 0;
+ box.x2 = pScreen->width;
+ box.y2 = pScreen->height;
+ REGION_INIT (pScreen, &pWin->winSize, &box, 1);
+ REGION_INIT (pScreen, &pWin->borderSize, &box, 1);
+ if (WasViewable)
+ REGION_RESET(pScreen, &pWin->borderClip, &box);
+ pWin->drawable.width = pScreen->width;
+ pWin->drawable.height = pScreen->height;
+ REGION_BREAK (pWin->drawable.pScreen, &pWin->clipList);
+ }
+ else
+ {
+ REGION_EMPTY(pScreen, &pWin->borderClip);
+ REGION_BREAK (pWin->drawable.pScreen, &pWin->clipList);
+ }
+
+ ResizeChildrenWinSize (pWin, 0, 0, 0, 0);
+
+ if (WasViewable)
+ {
+ if (pWin->backStorage)
+ {
+ pOldClip = REGION_CREATE(pScreen, NullBox, 1);
+ REGION_COPY(pScreen, pOldClip, &pWin->clipList);
+ }
+
+ if (pWin->firstChild)
+ {
+ anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin->firstChild,
+ pWin->firstChild,
+ (WindowPtr *)NULL);
+ }
+ else
+ {
+ (*pScreen->MarkWindow) (pWin);
+ anyMarked = TRUE;
+ }
+
+#ifdef DO_SAVE_UNDERS
+ if (DO_SAVE_UNDERS(pWin))
+ {
+ dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pLayerWin);
+ }
+#endif /* DO_SAVE_UNDERS */
+
+ if (anyMarked)
+ (*pScreen->ValidateTree)(pWin, NullWindow, VTOther);
+ }
+
+ if (pWin->backStorage &&
+ ((pWin->backingStore == Always) || WasViewable))
+ {
+ if (!WasViewable)
+ pOldClip = &pWin->clipList; /* a convenient empty region */
+ bsExposed = (*pScreen->TranslateBackingStore)
+ (pWin, 0, 0, pOldClip,
+ pWin->drawable.x, pWin->drawable.y);
+ if (WasViewable)
+ REGION_DESTROY(pScreen, pOldClip);
+ if (bsExposed)
+ {
+ RegionPtr valExposed = NullRegion;
+
+ if (pWin->valdata)
+ valExposed = &pWin->valdata->after.exposed;
+ (*pScreen->WindowExposures) (pWin, valExposed, bsExposed);
+ if (valExposed)
+ REGION_EMPTY(pScreen, valExposed);
+ REGION_DESTROY(pScreen, bsExposed);
+ }
+ }
+ if (WasViewable)
+ {
+ if (anyMarked)
+ (*pScreen->HandleExposures)(pWin);
+#ifdef DO_SAVE_UNDERS
+ if (dosave)
+ (*pScreen->PostChangeSaveUnder)(pLayerWin, pLayerWin);
+#endif /* DO_SAVE_UNDERS */
+ if (anyMarked && pScreen->PostValidateTree)
+ (*pScreen->PostValidateTree)(pWin, NullWindow, VTOther);
+ }
+ if (pWin->realized)
+ WindowsRestructured ();
+ FlushAllOutput ();
+}
+
+/*
+ * Function to enable/disable access to the frame buffer
+ *
+ * This is used when VT switching and when entering/leaving DGA direct mode.
+ *
+ * This has been rewritten again to eliminate the saved pixmap. The
+ * devPrivate field in the screen pixmap is set to NULL to catch code
+ * accidentally referencing the frame buffer while the X server is not
+ * supposed to touch it.
+ *
+ * Here, we exchange the pixmap private data, rather than the pixmaps
+ * themselves to avoid having to find and change any references to the screen
+ * pixmap such as GC's, window privates etc. This also means that this code
+ * does not need to know exactly how the pixmap pixels are accessed. Further,
+ * this exchange is >not< done through the screen's ModifyPixmapHeader()
+ * vector. This means the called frame buffer code layers can determine
+ * whether they are switched in or out by keeping track of the root pixmap's
+ * private data, and therefore don't need to access pScrnInfo->vtSema.
+ */
+void
+xf86EnableDisableFBAccess(int scrnIndex, Bool enable)
+{
+ ScrnInfoPtr pScrnInfo = xf86Screens[scrnIndex];
+ ScreenPtr pScreen = pScrnInfo->pScreen;
+ PixmapPtr pspix;
+
+ pspix = (*pScreen->GetScreenPixmap) (pScreen);
+ if (enable)
+ {
+ /*
+ * Restore the screen pixmap devPrivate field
+ */
+ pspix->devPrivate = pScrnInfo->pixmapPrivate;
+ /*
+ * Restore all of the clip lists on the screen
+ */
+ if (!xf86Resetting)
+ xf86SetRootClip (pScreen, TRUE);
+
+ }
+ else
+ {
+ /*
+ * Empty all of the clip lists on the screen
+ */
+ xf86SetRootClip (pScreen, FALSE);
+ /*
+ * save the screen pixmap devPrivate field and
+ * replace it with NULL so accidental references
+ * to the frame buffer are caught
+ */
+ pScrnInfo->pixmapPrivate = pspix->devPrivate;
+ pspix->devPrivate.ptr = NULL;
+ }
+}
+
+/* Buffer to hold log data written before the log file is opened */
+static char *saveBuffer = NULL;
+static int size = 0, unused = 0, pos = 0;
+
+/* These functions do the actual writes. */
+static void
+VWrite(int verb, const char *f, va_list args)
+{
+ static char buffer[1024];
+ int len = 0;
+
+ /*
+ * Since a va_list can only be processed once, write the string to a
+ * buffer, and then write the buffer out to the appropriate output
+ * stream(s).
+ */
+ if (verb < 0 || xf86LogVerbose >= verb || xf86Verbose >= verb) {
+ vsnprintf(buffer, sizeof(buffer), f, args);
+ len = strlen(buffer);
+ }
+ if ((verb < 0 || xf86Verbose >= verb) && len > 0)
+ fwrite(buffer, len, 1, stderr);
+ if ((verb < 0 || xf86LogVerbose >= verb) && len > 0) {
+ if (logfile) {
+ fwrite(buffer, len, 1, logfile);
+ if (xf86Info.log) {
+ fflush(logfile);
+ if (xf86Info.log == LogSync)
+ fsync(fileno(logfile));
+ }
+ } else {
+ /*
+ * Note, this code is used before OsInit() has been called, so
+ * xalloc and friends can't be used.
+ */
+ if (len > unused) {
+ size += 1024;
+ unused += 1024;
+ saveBuffer = realloc(saveBuffer, size);
+ if (!saveBuffer)
+ FatalError("realloc() failed while saving log messages\n");
+ }
+ unused -= len;
+ memcpy(saveBuffer + pos, buffer, len);
+ pos += len;
+ }
+ }
+}
+
+static void
+Write(int verb, const char *f, ...)
+{
+ va_list args;
+
+ va_start(args, f);
+ VWrite(verb, f, args);
+ va_end(args);
+}
+
+/* Print driver messages in the standard format */
+
+void
+xf86VDrvMsgVerb(int scrnIndex, MessageType type, int verb, const char *format,
+ va_list args)
+{
+ char *s = X_UNKNOWN_STRING;
+
+ /* Ignore verbosity for X_ERROR */
+ if (xf86Verbose >= verb || xf86LogVerbose >= verb || type == X_ERROR) {
+ switch (type) {
+ case X_PROBED:
+ s = X_PROBE_STRING;
+ break;
+ case X_CONFIG:
+ s = X_CONFIG_STRING;
+ break;
+ case X_DEFAULT:
+ s = X_DEFAULT_STRING;
+ break;
+ case X_CMDLINE:
+ s = X_CMDLINE_STRING;
+ break;
+ case X_NOTICE:
+ s = X_NOTICE_STRING;
+ break;
+ case X_ERROR:
+ s = X_ERROR_STRING;
+ if (verb > 0)
+ verb = 0;
+ break;
+ case X_WARNING:
+ s = X_WARNING_STRING;
+ break;
+ case X_INFO:
+ s = X_INFO_STRING;
+ break;
+ case X_NOT_IMPLEMENTED:
+ s = X_NOT_IMPLEMENTED_STRING;
+ break;
+ case X_NONE:
+ s = NULL;
+ break;
+ }
+
+ if (s != NULL)
+ Write(verb, "%s ", s);
+ if (scrnIndex >= 0 && scrnIndex < xf86NumScreens)
+ Write(verb, "%s(%d): ", xf86Screens[scrnIndex]->name, scrnIndex);
+ VWrite(verb, format, args);
+#if 0
+ if (type == X_ERROR && xf86Verbose < xf86LogVerbose) {
+ fprintf(stderr, X_ERROR_STRING " Please check the log file \"%s\""
+ " >before<\n\treporting a problem.\n", xf86LogFile);
+ }
+#endif
+ }
+}
+
+/* Print driver messages, with verbose level specified directly */
+void
+xf86DrvMsgVerb(int scrnIndex, MessageType type, int verb, const char *format,
+ ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ xf86VDrvMsgVerb(scrnIndex, type, verb, format, ap);
+ va_end(ap);
+}
+
+/* Print driver messages, with verbose level of 1 (default) */
+void
+xf86DrvMsg(int scrnIndex, MessageType type, const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ xf86VDrvMsgVerb(scrnIndex, type, 1, format, ap);
+ va_end(ap);
+}
+
+/* Print non-driver messages with verbose level specified directly */
+void
+xf86MsgVerb(MessageType type, int verb, const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ xf86VDrvMsgVerb(-1, type, verb, format, ap);
+ va_end(ap);
+}
+
+/* Print non-driver messages with verbose level of 1 (default) */
+void
+xf86Msg(MessageType type, const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ xf86VDrvMsgVerb(-1, type, 1, format, ap);
+ va_end(ap);
+}
+
+/* Just like ErrorF, but with the verbose level checked */
+void
+xf86ErrorFVerb(int verb, const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ if (xf86Verbose >= verb || xf86LogVerbose >= verb)
+ VWrite(verb, format, ap);
+ va_end(ap);
+}
+
+/* Like xf86ErrorFVerb, but with an implied verbose level of 1 */
+void
+xf86ErrorF(const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ if (xf86Verbose >= 1 || xf86LogVerbose >= 1)
+ VWrite(1, format, ap);
+ va_end(ap);
+}
+
+void
+OsVendorVErrorF(const char *f, va_list args)
+{
+ VWrite(-1, f, args);
+}
+
+void
+xf86LogInit()
+{
+ char *lf;
+
+#define LOGSUFFIX ".log"
+#define LOGOLDSUFFIX ".old"
+
+ /* Get the log file name */
+ if (xf86LogFileFrom == X_DEFAULT) {
+ /* Append the display number and ".log" */
+ lf = malloc(strlen(xf86LogFile) + strlen(display) +
+ strlen(LOGSUFFIX) + 1);
+ if (!lf)
+ FatalError("Cannot allocate space for the log file name\n");
+ sprintf(lf, "%s%s" LOGSUFFIX, xf86LogFile, display);
+ xf86LogFile = lf;
+ }
+ {
+ struct stat buf;
+ if (!stat(xf86LogFile,&buf) && S_ISREG(buf.st_mode)) {
+ char *oldlog = (char *)malloc(strlen(xf86LogFile)
+ + strlen(LOGOLDSUFFIX));
+ if (!oldlog)
+ FatalError("Cannot allocate space for the log file name\n");
+ sprintf(oldlog, "%s" LOGOLDSUFFIX, xf86LogFile);
+ if (rename(xf86LogFile,oldlog) == -1)
+ FatalError("Cannot move old logfile \"%s\"\n",oldlog);
+ free(oldlog);
+ }
+ }
+
+ if ((logfile = fopen(xf86LogFile, "w")) == NULL)
+ FatalError("Cannot open log file \"%s\"\n", xf86LogFile);
+ xf86LogFileWasOpened = TRUE;
+ setvbuf(logfile, NULL, _IONBF, 0);
+#ifdef DDXOSVERRORF
+ if (!OsVendorVErrorFProc)
+ OsVendorVErrorFProc = OsVendorVErrorF;
+#endif
+
+ /* Flush saved log information */
+ if (saveBuffer && size > 0) {
+ fwrite(saveBuffer, pos, 1, logfile);
+ if (xf86Info.log) {
+ fflush(logfile);
+ if (xf86Info.log == LogFlush)
+ fsync(fileno(logfile));
+ }
+ free(saveBuffer); /* Note, must be free(), not xfree() */
+ saveBuffer = 0;
+ size = 0;
+ }
+
+#undef LOGSUFFIX
+}
+
+void
+xf86CloseLog()
+{
+ if (logfile) {
+ fclose(logfile);
+ logfile = NULL;
+ }
+}
+
+
+/*
+ * Drivers can use these for using their own SymTabRecs.
+ */
+
+const char *
+xf86TokenToString(SymTabPtr table, int token)
+{
+ int i;
+
+ for (i = 0; table[i].token >= 0 && table[i].token != token; i++)
+ ;
+
+ if (table[i].token < 0)
+ return NULL;
+ else
+ return(table[i].name);
+}
+
+int
+xf86StringToToken(SymTabPtr table, const char *string)
+{
+ int i;
+
+ if (string == NULL)
+ return -1;
+
+ for (i = 0; table[i].token >= 0 && xf86NameCmp(string, table[i].name); i++)
+ ;
+
+ return(table[i].token);
+}
+
+/*
+ * helper to display the clocks found on a card
+ */
+void
+xf86ShowClocks(ScrnInfoPtr scrp, MessageType from)
+{
+ int j;
+
+ xf86DrvMsg(scrp->scrnIndex, from, "Pixel clocks available:");
+ for (j=0; j < scrp->numClocks; j++) {
+ if ((j % 4) == 0) {
+ xf86ErrorF("\n");
+ xf86DrvMsg(scrp->scrnIndex, from, "pixel clocks:");
+ }
+ xf86ErrorF(" %7.3f", (double)scrp->clock[j] / 1000.0);
+ }
+ xf86ErrorF("\n");
+}
+
+
+/*
+ * This prints out the driver identify message, including the names of
+ * the supported chipsets.
+ *
+ * XXX This makes assumptions about the line width, etc. Maybe we could
+ * use a more general "pretty print" function for messages.
+ */
+void
+xf86PrintChipsets(const char *drvname, const char *drvmsg, SymTabPtr chips)
+{
+ int len, i;
+
+ len = 6 + strlen(drvname) + 2 + strlen(drvmsg) + 2;
+ xf86Msg(X_INFO, "%s: %s:", drvname, drvmsg);
+ for (i = 0; chips[i].name != NULL; i++) {
+ if (i != 0) {
+ xf86ErrorF(",");
+ len++;
+ }
+ if (len + 2 + strlen(chips[i].name) < 78) {
+ xf86ErrorF(" ");
+ len++;
+ } else {
+ xf86ErrorF("\n\t");
+ len = 8;
+ }
+ xf86ErrorF("%s", chips[i].name);
+ len += strlen(chips[i].name);
+ }
+ xf86ErrorF("\n");
+}
+
+
+#define MAXDRIVERS 64 /* A >hack<, to be sure ... */
+
+
+int
+xf86MatchDevice(const char *drivername, GDevPtr **sectlist)
+{
+ GDevPtr gdp, *pgdp = NULL;
+ confScreenPtr screensecptr;
+ int i,j;
+
+ if (sectlist)
+ *sectlist = NULL;
+
+ if (xf86DoProbe) return 1;
+
+ if (xf86DoConfigure && xf86DoConfigurePass1) return 1;
+
+ /*
+ * This is a very important function that matches the device sections
+ * as they show up in the config file with the drivers that the server
+ * loads at run time.
+ *
+ * ChipProbe can call
+ * int xf86MatchDevice(char * drivername, GDevPtr ** sectlist)
+ * with its driver name. The function allocates an array of GDevPtr and
+ * returns this via sectlist and returns the number of elements in
+ * this list as return value. 0 means none found, -1 means fatal error.
+ *
+ * It can figure out which of the Device sections to use for which card
+ * (using things like the Card statement, etc). For single headed servers
+ * there will of course be just one such Device section.
+ */
+ i = 0;
+
+ /*
+ * first we need to loop over all the Screens sections to get to all
+ * 'active' device sections
+ */
+ for (j=0; xf86ConfigLayout.screens[j].screen != NULL; j++) {
+ screensecptr = xf86ConfigLayout.screens[j].screen;
+ if ((screensecptr->device->driver != NULL)
+ && (xf86NameCmp( screensecptr->device->driver,drivername) == 0)
+ && (! screensecptr->device->claimed)) {
+ /*
+ * we have a matching driver that wasn't claimed, yet
+ */
+ pgdp = xnfrealloc(pgdp, (i + 2) * sizeof(GDevPtr));
+ pgdp[i++] = screensecptr->device;
+ }
+ }
+
+ /* Then handle the inactive devices */
+ j = 0;
+ while (xf86ConfigLayout.inactives[j].identifier) {
+ gdp = &xf86ConfigLayout.inactives[j];
+ if (gdp->driver && !gdp->claimed &&
+ !xf86NameCmp(gdp->driver,drivername)) {
+ /* we have a matching driver that wasn't claimed yet */
+ pgdp = xnfrealloc(pgdp, (i + 2) * sizeof(GDevPtr));
+ pgdp[i++] = gdp;
+ }
+ j++;
+ }
+
+ /*
+ * make the array NULL terminated and return its address
+ */
+ if (i)
+ pgdp[i] = NULL;
+
+ if (sectlist)
+ *sectlist = pgdp;
+ else
+ xfree(pgdp);
+ return i;
+}
+
+struct Inst {
+ pciVideoPtr pci;
+ GDevPtr dev;
+ Bool foundHW; /* PCIid in list of supported chipsets */
+ Bool claimed; /* BusID matches with a device section */
+ int chip;
+ int screen;
+};
+
+int
+xf86MatchPciInstances(const char *driverName, int vendorID,
+ SymTabPtr chipsets, PciChipsets *PCIchipsets,
+ GDevPtr *devList, int numDevs, DriverPtr drvp,
+ int **foundEntities)
+{
+ int i,j;
+ MessageType from;
+ pciVideoPtr pPci, *ppPci;
+ struct Inst {
+ pciVideoPtr pci;
+ GDevPtr dev;
+ Bool foundHW; /* PCIid in list of supported chipsets */
+ Bool claimed; /* BusID matches with a device section */
+ int chip;
+ int screen;
+ } *instances = NULL;
+ int numClaimedInstances = 0;
+ int allocatedInstances = 0;
+ int numFound = 0;
+ SymTabRec *c;
+ PciChipsets *id;
+ GDevPtr devBus = NULL;
+ GDevPtr dev = NULL;
+ int *retEntities = NULL;
+
+ *foundEntities = NULL;
+
+ if (vendorID == 0) {
+ for (ppPci = xf86PciVideoInfo; *ppPci != NULL; ppPci++) {
+ Bool foundVendor = FALSE;
+ for (id = PCIchipsets; id->PCIid != -1; id++) {
+ if ( (((id->PCIid & 0xFFFF0000) >> 16) == (*ppPci)->vendor)) {
+ if (!foundVendor) {
+ ++allocatedInstances;
+ instances = xnfrealloc(instances,
+ allocatedInstances * sizeof(struct Inst));
+ instances[allocatedInstances - 1].pci = *ppPci;
+ instances[allocatedInstances - 1].dev = NULL;
+ instances[allocatedInstances - 1].claimed = FALSE;
+ instances[allocatedInstances - 1].foundHW = FALSE;
+ instances[allocatedInstances - 1].screen = 0;
+ foundVendor = TRUE;
+ }
+ if ((id->PCIid & 0x0000FFFF) == (*ppPci)->chipType) {
+ instances[allocatedInstances - 1].foundHW = TRUE;
+ instances[allocatedInstances - 1].chip = id->numChipset;
+ numFound++;
+ }
+ }
+ }
+ }
+ } else if (vendorID == PCI_VENDOR_GENERIC) {
+ for (ppPci = xf86PciVideoInfo; *ppPci != NULL; ppPci++) {
+ for (id = PCIchipsets; id->PCIid != -1; id++) {
+ if (id->PCIid == xf86CheckPciGAType(*ppPci)) {
+ ++allocatedInstances;
+ instances = xnfrealloc(instances,
+ allocatedInstances * sizeof(struct Inst));
+ instances[allocatedInstances - 1].pci = *ppPci;
+ instances[allocatedInstances - 1].dev = NULL;
+ instances[allocatedInstances - 1].claimed = FALSE;
+ instances[allocatedInstances - 1].foundHW = TRUE;
+ instances[allocatedInstances - 1].chip = id->numChipset;
+ instances[allocatedInstances - 1].screen = 0;
+ numFound++;
+ }
+ }
+ }
+ } else {
+ /* Find PCI devices that match the given vendor ID */
+ for (ppPci = xf86PciVideoInfo; (ppPci != NULL)
+ && (*ppPci != NULL); ppPci++) {
+ if ((*ppPci)->vendor == vendorID) {
+ ++allocatedInstances;
+ instances = xnfrealloc(instances,
+ allocatedInstances * sizeof(struct Inst));
+ instances[allocatedInstances - 1].pci = *ppPci;
+ instances[allocatedInstances - 1].dev = NULL;
+ instances[allocatedInstances - 1].claimed = FALSE;
+ instances[allocatedInstances - 1].foundHW = FALSE;
+ instances[allocatedInstances - 1].screen = 0;
+
+ /* Check if the chip type is listed in the chipsets table */
+ for (id = PCIchipsets; id->PCIid != -1; id++) {
+ if (id->PCIid == (*ppPci)->chipType) {
+ instances[allocatedInstances - 1].chip
+ = id->numChipset;
+ instances[allocatedInstances - 1].foundHW = TRUE;
+ numFound++;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ /*
+ * This may be debatable, but if no PCI devices with a matching vendor
+ * type is found, return zero now. It is probably not desirable to
+ * allow the config file to override this.
+ */
+ if (allocatedInstances <= 0) {
+ xfree(instances);
+ return 0;
+ }
+
+ if (xf86DoProbe) {
+ xfree(instances);
+ return numFound;
+ }
+
+ if (xf86DoConfigure && xf86DoConfigurePass1) {
+ GDevPtr pGDev;
+ int actualcards = 0;
+ for (i = 0; i < allocatedInstances; i++) {
+ pPci = instances[i].pci;
+ if (instances[i].foundHW) {
+ if (!xf86CheckPciSlot(pPci->bus, pPci->device, pPci->func))
+ continue;
+ actualcards++;
+ pGDev = xf86AddDeviceToConfigure(drvp->driverName,
+ instances[i].pci, -1);
+ if (pGDev) {
+ /*
+ * XF86Match???Instances() treat chipID and chipRev as
+ * overrides, so clobber them here.
+ */
+ pGDev->chipID = pGDev->chipRev = -1;
+ }
+ }
+ }
+ xfree(instances);
+ return actualcards;
+ }
+
+#ifdef DEBUG
+ ErrorF("%s instances found: %d\n", driverName, allocatedInstances);
+#endif
+
+ /*
+ * Check for devices that need duplicated instances. This is required
+ * when there is more than one screen per entity.
+ *
+ * XXX This currently doesn't work for cases where the BusID isn't
+ * specified explicitly in the config file.
+ */
+
+ for (j = 0; j < numDevs; j++) {
+ if (devList[j]->screen > 0 && devList[j]->busID
+ && *devList[j]->busID) {
+ for (i = 0; i < allocatedInstances; i++) {
+ pPci = instances[i].pci;
+ if (xf86ComparePciBusString(devList[j]->busID, pPci->bus,
+ pPci->device,
+ pPci->func)) {
+ allocatedInstances++;
+ instances = xnfrealloc(instances,
+ allocatedInstances *
+ sizeof(struct Inst));
+ instances[allocatedInstances - 1] = instances[i];
+ instances[allocatedInstances - 1].screen =
+ devList[j]->screen;
+ numFound++;
+ break;
+ }
+ }
+ }
+ }
+
+ for (i = 0; i < allocatedInstances; i++) {
+ pPci = instances[i].pci;
+ devBus = NULL;
+ dev = NULL;
+ for (j = 0; j < numDevs; j++) {
+ if (devList[j]->busID && *devList[j]->busID) {
+ if (xf86ComparePciBusString(devList[j]->busID, pPci->bus,
+ pPci->device,
+ pPci->func) &&
+ devList[j]->screen == instances[i].screen) {
+
+ if (devBus)
+ xf86MsgVerb(X_WARNING,0,
+ "%s: More than one matching Device section for "
+ "instances\n\t(BusID: %s) found: %s\n",
+ driverName, devList[j]->busID,
+ devList[j]->identifier);
+ else
+ devBus = devList[j];
+ }
+ } else {
+ /*
+ * if device section without BusID is found
+ * only assign to it to the primary device.
+ */
+ if (xf86IsPrimaryPci(pPci)) {
+ xf86Msg(X_PROBED, "Assigning device section with no busID"
+ " to primary device\n");
+ if (dev || devBus)
+ xf86MsgVerb(X_WARNING, 0,
+ "%s: More than one matching Device section "
+ "found: %s\n", devList[j]->identifier);
+ else
+ dev = devList[j];
+ }
+ }
+ }
+ if (devBus) dev = devBus; /* busID preferred */
+ if (!dev) {
+ if (xf86CheckPciSlot(pPci->bus, pPci->device, pPci->func)) {
+ xf86MsgVerb(X_WARNING, 0, "%s: No matching Device section "
+ "for instance (BusID PCI:%i:%i:%i) found\n",
+ driverName, pPci->bus, pPci->device, pPci->func);
+ }
+ } else {
+ numClaimedInstances++;
+ instances[i].claimed = TRUE;
+ instances[i].dev = dev;
+ }
+ }
+#ifdef DEBUG
+ ErrorF("%s instances found: %d\n", driverName, numClaimedInstances);
+#endif
+ /*
+ * Now check that a chipset or chipID override in the device section
+ * is valid. Chipset has precedence over chipID.
+ * If chipset is not valid ignore BusSlot completely.
+ */
+ for (i = 0; i < allocatedInstances && numClaimedInstances > 0; i++) {
+ if (!instances[i].claimed) {
+ continue;
+ }
+ from = X_PROBED;
+ if (instances[i].dev->chipset) {
+ for (c = chipsets; c->token >= 0; c++) {
+ if (xf86NameCmp(c->name, instances[i].dev->chipset) == 0)
+ break;
+ }
+ if (c->token == -1) {
+ instances[i].claimed = FALSE;
+ numClaimedInstances--;
+ xf86MsgVerb(X_WARNING, 0, "%s: Chipset \"%s\" in Device "
+ "section \"%s\" isn't valid for this driver\n",
+ driverName, instances[i].dev->chipset,
+ instances[i].dev->identifier);
+ } else {
+ instances[i].chip = c->token;
+
+ for (id = PCIchipsets; id->numChipset >= 0; id++) {
+ if (id->numChipset == instances[i].chip)
+ break;
+ }
+ if(id->numChipset >=0){
+ xf86Msg(X_CONFIG,"Chipset override: %s\n",
+ instances[i].dev->chipset);
+ from = X_CONFIG;
+ } else {
+ instances[i].claimed = FALSE;
+ numClaimedInstances--;
+ xf86MsgVerb(X_WARNING, 0, "%s: Chipset \"%s\" in Device "
+ "section \"%s\" isn't a valid PCI chipset\n",
+ driverName, instances[i].dev->chipset,
+ instances[i].dev->identifier);
+ }
+ }
+ } else if (instances[i].dev->chipID > 0) {
+ for (id = PCIchipsets; id->numChipset >= 0; id++) {
+ if (id->PCIid == instances[i].dev->chipID)
+ break;
+ }
+ if (id->numChipset == -1) {
+ instances[i].claimed = FALSE;
+ numClaimedInstances--;
+ xf86MsgVerb(X_WARNING, 0, "%s: ChipID 0x%04X in Device "
+ "section \"%s\" isn't valid for this driver\n",
+ driverName, instances[i].dev->chipID,
+ instances[i].dev->identifier);
+ } else {
+ instances[i].chip = id->numChipset;
+
+ xf86Msg( X_CONFIG,"ChipID override: 0x%04X\n",
+ instances[i].dev->chipID);
+ from = X_CONFIG;
+ }
+ } else if (!instances[i].foundHW) {
+ /*
+ * This means that there was no override and the PCI chipType
+ * doesn't match one that is supported
+ */
+ instances[i].claimed = FALSE;
+ numClaimedInstances--;
+ }
+ if (instances[i].claimed == TRUE){
+ for (c = chipsets; c->token >= 0; c++) {
+ if (c->token == instances[i].chip)
+ break;
+ }
+ xf86Msg(from,"Chipset %s found\n",
+ c->name);
+ }
+ }
+
+ /*
+ * Of the claimed instances, check that another driver hasn't already
+ * claimed its slot.
+ */
+ numFound = 0;
+ for (i = 0; i < allocatedInstances && numClaimedInstances > 0; i++) {
+
+ if (!instances[i].claimed)
+ continue;
+ pPci = instances[i].pci;
+
+
+ /*
+ * Allow the same entity to be used more than once for devices with
+ * multiple screens per entity. This assumes implicitly that there
+ * will be a screen == 0 instance.
+ *
+ * XXX Need to make sure that two different drivers don't claim
+ * the same screen > 0 instance.
+ */
+ if (instances[i].screen == 0 &&
+ !xf86CheckPciSlot(pPci->bus, pPci->device, pPci->func))
+ continue;
+
+#ifdef DEBUG
+ ErrorF("%s: card at %d:%d:%d is claimed by a Device section\n",
+ driverName, pPci->bus, pPci->device, pPci->func);
+#endif
+
+ /* Allocate an entry in the lists to be returned */
+ numFound++;
+ retEntities = xnfrealloc(retEntities, numFound * sizeof(int));
+ retEntities[numFound - 1]
+ = xf86ClaimPciSlot(pPci->bus, pPci->device,
+ pPci->func,drvp, instances[i].chip,
+ instances[i].dev,instances[i].dev->active ?
+ TRUE : FALSE);
+ if (retEntities[numFound - 1] == -1 && instances[i].screen > 0) {
+ for (j = 0; j < xf86NumEntities; j++) {
+ EntityPtr pEnt = xf86Entities[j];
+ if (pEnt->busType != BUS_PCI)
+ continue;
+ if (pEnt->pciBusId.bus == pPci->bus &&
+ pEnt->pciBusId.device == pPci->device &&
+ pEnt->pciBusId.func == pPci->func) {
+ retEntities[numFound - 1] = j;
+ xf86AddDevToEntity(j, instances[i].dev);
+ break;
+ }
+ }
+ }
+ }
+ xfree(instances);
+ if (numFound > 0) {
+ *foundEntities = retEntities;
+ }
+
+ return numFound;
+}
+
+int
+xf86MatchIsaInstances(const char *driverName, SymTabPtr chipsets,
+ IsaChipsets *ISAchipsets, DriverPtr drvp,
+ FindIsaDevProc FindIsaDevice, GDevPtr *devList,
+ int numDevs, int **foundEntities)
+{
+ SymTabRec *c;
+ IsaChipsets *Chips;
+ int i;
+ int numFound = 0;
+ int foundChip = -1;
+ int *retEntities = NULL;
+
+ *foundEntities = NULL;
+
+#if defined(__sparc__) || defined(__powerpc__)
+ FindIsaDevice = NULL; /* Temporary */
+#endif
+
+ if (xf86DoProbe || (xf86DoConfigure && xf86DoConfigurePass1)) {
+ if (FindIsaDevice &&
+ ((foundChip = (*FindIsaDevice)(NULL)) != -1)) {
+ xf86AddDeviceToConfigure(drvp->driverName, NULL, foundChip);
+ return 1;
+ }
+ return 0;
+ }
+
+ for (i = 0; i < numDevs; i++) {
+ MessageType from = X_CONFIG;
+ GDevPtr dev = NULL;
+ GDevPtr devBus = NULL;
+
+ if (devList[i]->busID && *devList[i]->busID) {
+ if (xf86ParseIsaBusString(devList[i]->busID)) {
+ if (devBus) xf86MsgVerb(X_WARNING,0,
+ "%s: More than one matching Device "
+ "section for ISA-Bus found: %s\n",
+ driverName,devList[i]->identifier);
+ else devBus = devList[i];
+ }
+ } else {
+ if (xf86IsPrimaryIsa()) {
+ if (dev) xf86MsgVerb(X_WARNING,0,
+ "%s: More than one matching "
+ "Device section found: %s\n",
+ driverName,devList[i]->identifier);
+ else dev = devList[i];
+ }
+ }
+ if (devBus) dev = devBus;
+ if (dev) {
+ if (dev->chipset) {
+ for (c = chipsets; c->token >= 0; c++) {
+ if (xf86NameCmp(c->name, dev->chipset) == 0)
+ break;
+ }
+ if (c->token == -1) {
+ xf86MsgVerb(X_WARNING, 0, "%s: Chipset \"%s\" in Device "
+ "section \"%s\" isn't valid for this driver\n",
+ driverName, dev->chipset,
+ dev->identifier);
+ } else
+ foundChip = c->token;
+ } else {
+ if (FindIsaDevice) foundChip = (*FindIsaDevice)(dev);
+ /* Probe it */
+ from = X_PROBED;
+ }
+ }
+
+ /* Check if the chip type is listed in the chipset table - for sanity*/
+
+ if (foundChip >= 0){
+ for (Chips = ISAchipsets; Chips->numChipset >= 0; Chips++) {
+ if (Chips->numChipset == foundChip)
+ break;
+ }
+ if (Chips->numChipset == -1){
+ foundChip = -1;
+ xf86MsgVerb(X_WARNING,0,
+ "%s: Driver detected unknown ISA-Bus Chipset\n",
+ driverName);
+ }
+ }
+ if (foundChip != -1) {
+ numFound++;
+ retEntities = xnfrealloc(retEntities,numFound * sizeof(int));
+ retEntities[numFound - 1] =
+ xf86ClaimIsaSlot(drvp,foundChip,dev, dev->active ? TRUE : FALSE);
+ for (c = chipsets; c->token >= 0; c++) {
+ if (c->token == foundChip)
+ break;
+ }
+ xf86Msg(from, "Chipset %s found\n", c->name);
+ }
+ }
+ *foundEntities = retEntities;
+
+ return numFound;
+}
+
+/*
+ * xf86GetClocks -- get the dot-clocks via a BIG BAD hack ...
+ */
+void
+xf86GetClocks(ScrnInfoPtr pScrn, int num, Bool (*ClockFunc)(ScrnInfoPtr, int),
+ void (*ProtectRegs)(ScrnInfoPtr, Bool),
+ void (*BlankScreen)(ScrnInfoPtr, Bool), IOADDRESS vertsyncreg,
+ int maskval, int knownclkindex, int knownclkvalue)
+{
+ register int status = vertsyncreg;
+ unsigned long i, cnt, rcnt, sync;
+
+ /* First save registers that get written on */
+ (*ClockFunc)(pScrn, CLK_REG_SAVE);
+
+ xf86SetPriority(TRUE);
+
+ if (num > MAXCLOCKS)
+ num = MAXCLOCKS;
+
+ for (i = 0; i < num; i++)
+ {
+ if (ProtectRegs)
+ (*ProtectRegs)(pScrn, TRUE);
+ if (!(*ClockFunc)(pScrn, i))
+ {
+ pScrn->clock[i] = -1;
+ continue;
+ }
+ if (ProtectRegs)
+ (*ProtectRegs)(pScrn, FALSE);
+ if (BlankScreen)
+ (*BlankScreen)(pScrn, FALSE);
+
+ usleep(50000); /* let VCO stabilise */
+
+ cnt = 0;
+ sync = 200000;
+
+ /* XXX How critical is this? */
+ if (!xf86DisableInterrupts())
+ {
+ (*ClockFunc)(pScrn, CLK_REG_RESTORE);
+ ErrorF("Failed to disable interrupts during clock probe. If\n");
+ ErrorF("your OS does not support disabling interrupts, then you\n");
+ FatalError("must specify a Clocks line in the XF86Config file.\n");
+ }
+ while ((inb(status) & maskval) == 0x00)
+ if (sync-- == 0) goto finish;
+ /* Something appears to be happening, so reset sync count */
+ sync = 200000;
+ while ((inb(status) & maskval) == maskval)
+ if (sync-- == 0) goto finish;
+ /* Something appears to be happening, so reset sync count */
+ sync = 200000;
+ while ((inb(status) & maskval) == 0x00)
+ if (sync-- == 0) goto finish;
+
+ for (rcnt = 0; rcnt < 5; rcnt++)
+ {
+ while (!(inb(status) & maskval))
+ cnt++;
+ while ((inb(status) & maskval))
+ cnt++;
+ }
+
+finish:
+ xf86EnableInterrupts();
+
+ pScrn->clock[i] = cnt ? cnt : -1;
+ if (BlankScreen)
+ (*BlankScreen)(pScrn, TRUE);
+ }
+
+ xf86SetPriority(FALSE);
+
+ for (i = 0; i < num; i++)
+ {
+ if (i != knownclkindex)
+ {
+ if (pScrn->clock[i] == -1)
+ {
+ pScrn->clock[i] = 0;
+ }
+ else
+ {
+ pScrn->clock[i] = (int)(0.5 +
+ (((float)knownclkvalue) * pScrn->clock[knownclkindex]) /
+ (pScrn->clock[i]));
+ /* Round to nearest 10KHz */
+ pScrn->clock[i] += 5;
+ pScrn->clock[i] /= 10;
+ pScrn->clock[i] *= 10;
+ }
+ }
+ }
+
+ pScrn->clock[knownclkindex] = knownclkvalue;
+ pScrn->numClocks = num;
+
+ /* Restore registers that were written on */
+ (*ClockFunc)(pScrn, CLK_REG_RESTORE);
+}
+
+void
+xf86SetPriority(Bool up)
+{
+ static int saved_nice;
+
+ if (up) {
+#ifdef HAS_SETPRIORITY
+ saved_nice = getpriority(PRIO_PROCESS, 0);
+ setpriority(PRIO_PROCESS, 0, -20);
+#endif
+#if defined(SYSV) || defined(SVR4) || defined(linux)
+ saved_nice = nice(0);
+ nice(-20 - saved_nice);
+#endif
+ } else {
+#ifdef HAS_SETPRIORITY
+ setpriority(PRIO_PROCESS, 0, saved_nice);
+#endif
+#if defined(SYSV) || defined(SVR4) || defined(linux)
+ nice(20 + saved_nice);
+#endif
+ }
+}
+
+const char *
+xf86GetVisualName(int visual)
+{
+ if (visual < 0 || visual > DirectColor)
+ return NULL;
+
+ return xf86VisualNames[visual];
+}
+
+
+int
+xf86GetVerbosity()
+{
+ return max(xf86Verbose, xf86LogVerbose);
+}
+
+
+Pix24Flags
+xf86GetPix24()
+{
+ return xf86Info.pixmap24;
+}
+
+
+int
+xf86GetDepth()
+{
+ return xf86Depth;
+}
+
+
+rgb
+xf86GetWeight()
+{
+ return xf86Weight;
+}
+
+
+Gamma
+xf86GetGamma()
+{
+ return xf86Gamma;
+}
+
+
+Bool
+xf86GetFlipPixels()
+{
+ return xf86FlipPixels;
+}
+
+
+const char *
+xf86GetServerName()
+{
+ return xf86ServerName;
+}
+
+
+Bool
+xf86ServerIsExiting()
+{
+ return (dispatchException & DE_TERMINATE) == DE_TERMINATE;
+}
+
+
+Bool
+xf86ServerIsResetting()
+{
+ return xf86Resetting;
+}
+
+
+Bool
+xf86ServerIsInitialising()
+{
+ return xf86Initialising;
+}
+
+
+Bool
+xf86ServerIsOnlyDetecting(void)
+{
+ return xf86DoProbe || xf86DoConfigure;
+}
+
+
+Bool
+xf86ServerIsOnlyProbing(void)
+{
+ return xf86ProbeOnly;
+}
+
+
+Bool
+xf86CaughtSignal()
+{
+ return xf86Info.caughtSignal;
+}
+
+
+Bool
+xf86GetVidModeAllowNonLocal()
+{
+ return xf86Info.vidModeAllowNonLocal;
+}
+
+
+Bool
+xf86GetVidModeEnabled()
+{
+ return xf86Info.vidModeEnabled;
+}
+
+Bool
+xf86GetModInDevAllowNonLocal()
+{
+ return xf86Info.miscModInDevAllowNonLocal;
+}
+
+
+Bool
+xf86GetModInDevEnabled()
+{
+ return xf86Info.miscModInDevEnabled;
+}
+
+
+Bool
+xf86GetAllowMouseOpenFail()
+{
+ return xf86Info.allowMouseOpenFail;
+}
+
+
+Bool
+xf86IsPc98()
+{
+#if defined(i386) || defined(__i386__)
+ return xf86Info.pc98;
+#else
+ return FALSE;
+#endif
+}
+
+void
+xf86DisableRandR()
+{
+ xf86Info.disableRandR = TRUE;
+ xf86Info.randRFrom = X_PROBED;
+}
+
+CARD32
+xf86GetVersion()
+{
+ return XF86_VERSION_CURRENT;
+}
+
+CARD32
+xf86GetModuleVersion(pointer module)
+{
+#ifdef XFree86LOADER
+ return (CARD32)LoaderGetModuleVersion(module);
+#else
+ return 0;
+#endif
+}
+
+pointer
+xf86LoadDrvSubModule(DriverPtr drv, const char *name)
+{
+#ifdef XFree86LOADER
+ pointer ret;
+ int errmaj = 0, errmin = 0;
+
+ ret = LoadSubModule(drv->module, name, NULL, NULL, NULL, NULL,
+ &errmaj, &errmin);
+ if (!ret)
+ LoaderErrorMsg(NULL, name, errmaj, errmin);
+ return ret;
+#else
+ return (pointer)1;
+#endif
+}
+
+pointer
+xf86LoadSubModule(ScrnInfoPtr pScrn, const char *name)
+{
+#ifdef XFree86LOADER
+ pointer ret;
+ int errmaj = 0, errmin = 0;
+
+ ret = LoadSubModule(pScrn->module, name, NULL, NULL, NULL, NULL,
+ &errmaj, &errmin);
+ if (!ret)
+ LoaderErrorMsg(pScrn->name, name, errmaj, errmin);
+ return ret;
+#else
+ return (pointer)1;
+#endif
+}
+
+/*
+ * xf86LoadOneModule loads a single module.
+ */
+pointer
+xf86LoadOneModule(char *name, pointer opt)
+{
+#ifdef XFree86LOADER
+ int errmaj, errmin;
+#endif
+ char *Name;
+ pointer mod;
+
+ if (!name)
+ return NULL;
+
+#ifndef NORMALISE_MODULE_NAME
+ Name = xstrdup(name);
+#else
+ /* Normalise the module name */
+ Name = xf86NormalizeName(name);
+#endif
+
+ /* Skip empty names */
+ if (Name == NULL)
+ return NULL;
+ if (*Name == '\0') {
+ xfree(Name);
+ return NULL;
+ }
+
+#ifdef XFree86LOADER
+ mod = LoadModule(Name, NULL, NULL, NULL, opt, NULL, &errmaj, &errmin);
+ if (!mod)
+ LoaderErrorMsg(NULL, Name, errmaj, errmin);
+#else
+ mod = (pointer)1;
+#endif
+ xfree(Name);
+ return mod;
+}
+
+void
+xf86UnloadSubModule(pointer mod)
+{
+ /*
+ * This is disabled for now. The loader isn't smart enough yet to undo
+ * relocations.
+ */
+#if defined(XFree86LOADER) && 0
+ UnloadSubModule(mod);
+#endif
+}
+
+Bool
+xf86LoaderCheckSymbol(const char *name)
+{
+#ifdef XFree86LOADER
+ return LoaderSymbol(name) != NULL;
+#else
+ return TRUE;
+#endif
+}
+
+void
+xf86LoaderReqSymLists(const char **list0, ...)
+{
+#ifdef XFree86LOADER
+ va_list ap;
+
+ va_start(ap, list0);
+ LoaderVReqSymLists(list0, ap);
+ va_end(ap);
+#endif
+}
+
+void
+xf86LoaderReqSymbols(const char *sym0, ...)
+{
+#ifdef XFree86LOADER
+ va_list ap;
+
+ va_start(ap, sym0);
+ LoaderVReqSymbols(sym0, ap);
+ va_end(ap);
+#endif
+}
+
+void
+xf86LoaderRefSymLists(const char **list0, ...)
+{
+#ifdef XFree86LOADER
+ va_list ap;
+
+ va_start(ap, list0);
+ LoaderVRefSymLists(list0, ap);
+ va_end(ap);
+#endif
+}
+
+void
+xf86LoaderRefSymbols(const char *sym0, ...)
+{
+#ifdef XFree86LOADER
+ va_list ap;
+
+ va_start(ap, sym0);
+ LoaderVRefSymbols(sym0, ap);
+ va_end(ap);
+#endif
+}
+
+
+typedef enum {
+ OPTION_BACKING_STORE
+} BSOpts;
+
+static const OptionInfoRec BSOptions[] = {
+ { OPTION_BACKING_STORE, "BackingStore", OPTV_BOOLEAN, {0}, FALSE },
+ { -1, NULL, OPTV_NONE, {0}, FALSE }
+};
+
+void
+xf86SetBackingStore(ScreenPtr pScreen)
+{
+ Bool useBS = FALSE;
+ MessageType from = X_DEFAULT;
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ OptionInfoPtr options;
+
+ options = xnfalloc(sizeof(BSOptions));
+ (void)memcpy(options, BSOptions, sizeof(BSOptions));
+ xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options);
+
+ /* check for commandline option here */
+ if (xf86bsEnableFlag) {
+ from = X_CMDLINE;
+ useBS = TRUE;
+ } else if (xf86bsDisableFlag) {
+ from = X_CMDLINE;
+ useBS = FALSE;
+ } else {
+ if (xf86GetOptValBool(options, OPTION_BACKING_STORE, &useBS))
+ from = X_CONFIG;
+ }
+ xfree(options);
+ pScreen->backingStoreSupport = useBS ? Always : NotUseful;
+ if (serverGeneration == 1)
+ xf86DrvMsg(pScreen->myNum, from, "Backing store %s\n",
+ useBS ? "enabled" : "disabled");
+}
+
+
+typedef enum {
+ OPTION_SILKEN_MOUSE
+} SMOpts;
+
+static const OptionInfoRec SMOptions[] = {
+ { OPTION_SILKEN_MOUSE, "SilkenMouse", OPTV_BOOLEAN, {0}, FALSE },
+ { -1, NULL, OPTV_NONE, {0}, FALSE }
+};
+
+void
+xf86SetSilkenMouse (ScreenPtr pScreen)
+{
+ Bool useSM = TRUE;
+ MessageType from = X_DEFAULT;
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ OptionInfoPtr options;
+
+ options = xnfalloc(sizeof(SMOptions));
+ (void)memcpy(options, SMOptions, sizeof(SMOptions));
+ xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options);
+
+ /* check for commandline option here */
+ /* disable if screen shares resources */
+ if (((pScrn->racMemFlags & RAC_CURSOR) &&
+ !xf86NoSharedResources(pScrn->scrnIndex,MEM)) ||
+ ((pScrn->racIoFlags & RAC_CURSOR) &&
+ !xf86NoSharedResources(pScrn->scrnIndex,IO))) {
+ useSM = FALSE;
+ from = X_PROBED;
+ } else if (xf86silkenMouseDisableFlag) {
+ from = X_CMDLINE;
+ useSM = FALSE;
+ } else {
+ if (xf86GetOptValBool(options, OPTION_SILKEN_MOUSE, &useSM))
+ from = X_CONFIG;
+ }
+ xfree(options);
+ /*
+ * XXX quick hack to report correctly for OSs that can't do SilkenMouse
+ * yet. Should handle this differently so that alternate async methods
+ * like Xqueue work correctly with this too.
+ */
+ pScrn->silkenMouse = useSM && xf86SIGIOSupported();
+ if (serverGeneration == 1)
+ xf86DrvMsg(pScreen->myNum, from, "Silken mouse %s\n",
+ pScrn->silkenMouse ? "enabled" : "disabled");
+}
+
+/* Wrote this function for the PM2 Xv driver, preliminary. */
+
+pointer
+xf86FindXvOptions(int scrnIndex, int adaptor_index, char *port_name,
+ char **adaptor_name, pointer *adaptor_options)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ confXvAdaptorPtr adaptor;
+ int i;
+
+ if (adaptor_index >= pScrn->confScreen->numxvadaptors) {
+ if (adaptor_name) *adaptor_name = NULL;
+ if (adaptor_options) *adaptor_options = NULL;
+ return NULL;
+ }
+
+ adaptor = &pScrn->confScreen->xvadaptors[adaptor_index];
+ if (adaptor_name) *adaptor_name = adaptor->identifier;
+ if (adaptor_options) *adaptor_options = adaptor->options;
+
+ for (i = 0; i < adaptor->numports; i++)
+ if (!xf86NameCmp(adaptor->ports[i].identifier, port_name))
+ return adaptor->ports[i].options;
+
+ return NULL;
+}
+
+/* Rather than duplicate loader's get OS function, just include it directly */
+#define LoaderGetOS xf86GetOS
+#include "loader/os.c"
+
+/* new RAC */
+/*
+ * xf86ConfigIsa/PciEntity() -- These helper functions assign an
+ * active entity to a screen, registers its fixed resources, assign
+ * special enter/leave functions and their private scratch area to
+ * this entity, take the dog for a walk...
+ */
+ScrnInfoPtr
+xf86ConfigIsaEntity(ScrnInfoPtr pScrn, int scrnFlag, int entityIndex,
+ IsaChipsets *i_chip, resList res, EntityProc init,
+ EntityProc enter, EntityProc leave, pointer private)
+{
+ IsaChipsets *i_id;
+ EntityInfoPtr pEnt = xf86GetEntityInfo(entityIndex);
+ if (!pEnt) return pScrn;
+
+ if (!(pEnt->location.type == BUS_ISA)) {
+ xfree(pEnt);
+ return pScrn;
+ }
+
+ if (!pEnt->active) {
+ xf86ConfigIsaEntityInactive(pEnt, i_chip, res, init, enter,
+ leave, private);
+ return pScrn;
+ }
+
+ if (!pScrn)
+ pScrn = xf86AllocateScreen(pEnt->driver,scrnFlag);
+ xf86AddEntityToScreen(pScrn,entityIndex);
+
+ if (i_chip) {
+ for (i_id = i_chip; i_id->numChipset != -1; i_id++) {
+ if (pEnt->chipset == i_id->numChipset) break;
+ }
+ xf86ClaimFixedResources(i_id->resList,entityIndex);
+ }
+ xfree(pEnt);
+ xf86ClaimFixedResources(res,entityIndex);
+ xf86SetEntityFuncs(entityIndex,init,enter,leave,private);
+
+ return pScrn;
+}
+
+ScrnInfoPtr
+xf86ConfigPciEntity(ScrnInfoPtr pScrn, int scrnFlag, int entityIndex,
+ PciChipsets *p_chip, resList res, EntityProc init,
+ EntityProc enter, EntityProc leave, pointer private)
+{
+ PciChipsets *p_id;
+ EntityInfoPtr pEnt = xf86GetEntityInfo(entityIndex);
+ if (!pEnt) return pScrn;
+
+ if (!(pEnt->location.type == BUS_PCI)
+ || !xf86GetPciInfoForEntity(entityIndex)) {
+ xfree(pEnt);
+ return pScrn;
+ }
+ if (!pEnt->active) {
+ xf86ConfigPciEntityInactive(pEnt, p_chip, res, init, enter,
+ leave, private);
+ return pScrn;
+ }
+
+ if (!pScrn)
+ pScrn = xf86AllocateScreen(pEnt->driver,scrnFlag);
+ if (xf86IsEntitySharable(entityIndex)) {
+ xf86SetEntityShared(entityIndex);
+ }
+ xf86AddEntityToScreen(pScrn,entityIndex);
+ if (xf86IsEntityShared(entityIndex)) {
+ return pScrn;
+ }
+ if (p_chip) {
+ for (p_id = p_chip; p_id->numChipset != -1; p_id++) {
+ if (pEnt->chipset == p_id->numChipset) break;
+ }
+ xf86ClaimFixedResources(p_id->resList,entityIndex);
+ }
+ xfree(pEnt);
+
+ xf86ClaimFixedResources(res,entityIndex);
+ xf86SetEntityFuncs(entityIndex,init,enter,leave,private);
+
+ return pScrn;
+}
+
+ScrnInfoPtr
+xf86ConfigFbEntity(ScrnInfoPtr pScrn, int scrnFlag, int entityIndex,
+ EntityProc init, EntityProc enter, EntityProc leave,
+ pointer private)
+{
+ EntityInfoPtr pEnt = xf86GetEntityInfo(entityIndex);
+ if (!pEnt) return pScrn;
+
+ if (!(pEnt->location.type == BUS_NONE)) {
+ xfree(pEnt);
+ return pScrn;
+ }
+
+ if (!pEnt->active) {
+ xf86ConfigFbEntityInactive(pEnt, init, enter, leave, private);
+ return pScrn;
+ }
+
+ if (!pScrn)
+ pScrn = xf86AllocateScreen(pEnt->driver,scrnFlag);
+ xf86AddEntityToScreen(pScrn,entityIndex);
+
+ xf86SetEntityFuncs(entityIndex,init,enter,leave,private);
+
+ return pScrn;
+}
+
+/*
+ *
+ * OBSOLETE ! xf86ConfigActiveIsaEntity() and xf86ConfigActivePciEntity()
+ * are obsolete functions. They the are likely to be removed
+ * Don't use!
+ */
+Bool
+xf86ConfigActiveIsaEntity(ScrnInfoPtr pScrn, int entityIndex,
+ IsaChipsets *i_chip, resList res, EntityProc init,
+ EntityProc enter, EntityProc leave, pointer private)
+{
+ IsaChipsets *i_id;
+ EntityInfoPtr pEnt = xf86GetEntityInfo(entityIndex);
+ if (!pEnt) return FALSE;
+
+ if (!pEnt->active || !(pEnt->location.type == BUS_ISA)) {
+ xfree(pEnt);
+ return FALSE;
+ }
+
+ xf86AddEntityToScreen(pScrn,entityIndex);
+
+ if (i_chip) {
+ for (i_id = i_chip; i_id->numChipset != -1; i_id++) {
+ if (pEnt->chipset == i_id->numChipset) break;
+ }
+ xf86ClaimFixedResources(i_id->resList,entityIndex);
+ }
+ xfree(pEnt);
+ xf86ClaimFixedResources(res,entityIndex);
+ if (!xf86SetEntityFuncs(entityIndex,init,enter,leave,private))
+ return FALSE;
+
+ return TRUE;
+}
+
+Bool
+xf86ConfigActivePciEntity(ScrnInfoPtr pScrn, int entityIndex,
+ PciChipsets *p_chip, resList res, EntityProc init,
+ EntityProc enter, EntityProc leave, pointer private)
+{
+ PciChipsets *p_id;
+ EntityInfoPtr pEnt = xf86GetEntityInfo(entityIndex);
+ if (!pEnt) return FALSE;
+
+ if (!pEnt->active || !(pEnt->location.type == BUS_PCI)) {
+ xfree(pEnt);
+ return FALSE;
+ }
+ xf86AddEntityToScreen(pScrn,entityIndex);
+
+ if (p_chip) {
+ for (p_id = p_chip; p_id->numChipset != -1; p_id++) {
+ if (pEnt->chipset == p_id->numChipset) break;
+ }
+ xf86ClaimFixedResources(p_id->resList,entityIndex);
+ }
+ xfree(pEnt);
+
+ xf86ClaimFixedResources(res,entityIndex);
+ if (!xf86SetEntityFuncs(entityIndex,init,enter,leave,private))
+ return FALSE;
+
+ return TRUE;
+}
+
+/*
+ * xf86ConfigPci/IsaEntityInactive() -- These functions can be used
+ * to configure an inactive entity as well as to reconfigure an
+ * previously active entity inactive. If the entity has been
+ * assigned to a screen before it will be removed. If p_pci(p_isa) is
+ * non-NULL all static resources listed there will be registered.
+ */
+void
+xf86ConfigPciEntityInactive(EntityInfoPtr pEnt, PciChipsets *p_chip,
+ resList res, EntityProc init, EntityProc enter,
+ EntityProc leave, pointer private)
+{
+ PciChipsets *p_id;
+ ScrnInfoPtr pScrn;
+
+ if ((pScrn = xf86FindScreenForEntity(pEnt->index)))
+ xf86RemoveEntityFromScreen(pScrn,pEnt->index);
+ else if (p_chip) {
+ for (p_id = p_chip; p_id->numChipset != -1; p_id++) {
+ if (pEnt->chipset == p_id->numChipset) break;
+ }
+ xf86ClaimFixedResources(p_id->resList,pEnt->index);
+ }
+ xf86ClaimFixedResources(res,pEnt->index);
+ /* shared resources are only needed when entity is active: remove */
+ xf86DeallocateResourcesForEntity(pEnt->index, ResShared);
+ xf86SetEntityFuncs(pEnt->index,init,enter,leave,private);
+}
+
+void
+xf86ConfigIsaEntityInactive(EntityInfoPtr pEnt, IsaChipsets *i_chip,
+ resList res, EntityProc init, EntityProc enter,
+ EntityProc leave, pointer private)
+{
+ IsaChipsets *i_id;
+ ScrnInfoPtr pScrn;
+
+ if ((pScrn = xf86FindScreenForEntity(pEnt->index)))
+ xf86RemoveEntityFromScreen(pScrn,pEnt->index);
+ else if (i_chip) {
+ for (i_id = i_chip; i_id->numChipset != -1; i_id++) {
+ if (pEnt->chipset == i_id->numChipset) break;
+ }
+ xf86ClaimFixedResources(i_id->resList,pEnt->index);
+ }
+ xf86ClaimFixedResources(res,pEnt->index);
+ /* shared resources are only needed when entity is active: remove */
+ xf86DeallocateResourcesForEntity(pEnt->index, ResShared);
+ xf86SetEntityFuncs(pEnt->index,init,enter,leave,private);
+}
+
+void
+xf86ConfigFbEntityInactive(EntityInfoPtr pEnt, EntityProc init,
+ EntityProc enter, EntityProc leave, pointer private)
+{
+ ScrnInfoPtr pScrn;
+
+ if ((pScrn = xf86FindScreenForEntity(pEnt->index)))
+ xf86RemoveEntityFromScreen(pScrn,pEnt->index);
+ xf86SetEntityFuncs(pEnt->index,init,enter,leave,private);
+}
+
+Bool
+xf86IsScreenPrimary(int scrnIndex)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ int i;
+
+ for (i=0 ; i < pScrn->numEntities; i++) {
+ if (xf86IsEntityPrimary(i))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+int
+xf86RegisterRootWindowProperty(int ScrnIndex, Atom property, Atom type,
+ int format, unsigned long len, pointer value )
+{
+ PropertyPtr pNewProp, pRegProp;
+ int i;
+
+#ifdef DEBUG
+ ErrorF("xf86RegisterRootWindowProperty(%d, %d, %d, %d, %d, %p)\n",
+ ScrnIndex, property, type, format, len, value);
+#endif
+
+ if (ScrnIndex<0 || ScrnIndex>=xf86NumScreens) {
+ return(BadMatch);
+ }
+
+ if ( (pNewProp = (PropertyPtr)xalloc(sizeof(PropertyRec)))==NULL ) {
+ return(BadAlloc);
+ }
+
+ pNewProp->propertyName = property;
+ pNewProp->type = type;
+ pNewProp->format = format;
+ pNewProp->size = len;
+ pNewProp->data = value;
+ /* We will put this property at the end of the list so that
+ * the changes are made in the order they were requested.
+ */
+ pNewProp->next = NULL;
+
+#ifdef DEBUG
+ ErrorF("new property filled\n");
+#endif
+
+ if (NULL==xf86RegisteredPropertiesTable) {
+#ifdef DEBUG
+ ErrorF("creating xf86RegisteredPropertiesTable[] size %d\n",
+ xf86NumScreens);
+#endif
+ if ( NULL==(xf86RegisteredPropertiesTable=(PropertyPtr*)xnfcalloc(sizeof(PropertyPtr),xf86NumScreens) )) {
+ return(BadAlloc);
+ }
+ for (i=0; i<xf86NumScreens; i++) {
+ xf86RegisteredPropertiesTable[i] = NULL;
+ }
+ }
+
+#ifdef DEBUG
+ ErrorF("xf86RegisteredPropertiesTable %p\n",
+ xf86RegisteredPropertiesTable);
+ ErrorF("xf86RegisteredPropertiesTable[%d] %p\n",
+ ScrnIndex, xf86RegisteredPropertiesTable[ScrnIndex]);
+#endif
+
+ if ( xf86RegisteredPropertiesTable[ScrnIndex] == NULL) {
+ xf86RegisteredPropertiesTable[ScrnIndex] = pNewProp;
+ } else {
+ pRegProp = xf86RegisteredPropertiesTable[ScrnIndex];
+ while (pRegProp->next != NULL) {
+#ifdef DEBUG
+ ErrorF("- next %p\n", pRegProp);
+#endif
+ pRegProp = pRegProp->next;
+ }
+ pRegProp->next = pNewProp;
+ }
+#ifdef DEBUG
+ ErrorF("xf86RegisterRootWindowProperty succeeded\n");
+#endif
+ return(Success);
+}
+
+Bool
+xf86IsUnblank(int mode)
+{
+ switch(mode) {
+ case SCREEN_SAVER_OFF:
+ case SCREEN_SAVER_FORCER:
+ return TRUE;
+ case SCREEN_SAVER_ON:
+ case SCREEN_SAVER_CYCLE:
+ return FALSE;
+ default:
+ xf86MsgVerb(X_WARNING, 0, "Unexpected save screen mode: %d\n", mode);
+ return TRUE;
+ }
+}
diff --git a/hw/xfree86/common/xf86InPriv.h b/hw/xfree86/common/xf86InPriv.h
new file mode 100644
index 000000000..5cd66d882
--- /dev/null
+++ b/hw/xfree86/common/xf86InPriv.h
@@ -0,0 +1,17 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86InPriv.h,v 1.4 1999/05/17 13:17:14 dawes Exp $ */
+
+#ifndef _xf86InPriv_h
+#define _xf86InPriv_h
+
+/* xf86Globals.c */
+#ifdef XFree86LOADER
+extern InputDriverPtr *xf86InputDriverList;
+#else
+extern InputDriverPtr xf86InputDriverList[];
+#endif
+extern int xf86NumInputDrivers;
+
+/* xf86Xinput.c */
+void xf86ActivateDevice(InputInfoPtr pInfo);
+
+#endif /* _xf86InPriv_h */
diff --git a/hw/xfree86/common/xf86MiscExt.c b/hw/xfree86/common/xf86MiscExt.c
new file mode 100644
index 000000000..f04a0b8d8
--- /dev/null
+++ b/hw/xfree86/common/xf86MiscExt.c
@@ -0,0 +1,612 @@
+/*
+ * Copyright (c) 1999 by The XFree86 Project, Inc.
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86MiscExt.c,v 1.11 2002/11/20 04:04:57 dawes Exp $ */
+
+/*
+ * This file contains the Pointer/Keyboard functions needed by the
+ * XFree86-Misc extension.
+ */
+
+#include "X.h"
+#include "os.h"
+#include "xf86.h"
+#include "xf86Priv.h"
+
+#ifdef XF86MISC
+#define _XF86MISC_SERVER_
+#include "xf86misc.h"
+#include "xf86miscproc.h"
+#endif
+
+#define XF86_OS_PRIVS
+#include "xf86_OSlib.h"
+
+#ifdef XINPUT
+#include "XI.h"
+#include "XIproto.h"
+#include "xf86Xinput.h"
+#else
+#include "inputstr.h"
+#endif
+
+#include "xf86OSmouse.h"
+#include "../input/mouse/mouse.h"
+
+#ifdef DEBUG
+# define DEBUG_P(x) ErrorF(x"\n");
+#else
+# define DEBUG_P(x) /**/
+#endif
+
+#ifdef XF86MISC
+
+typedef struct {
+ int type;
+ int baudrate;
+ int samplerate;
+ int resolution;
+ int buttons;
+ Bool em3buttons;
+ int em3timeout;
+ Bool chordmiddle;
+ int flags;
+ char* device;
+ pointer private;
+} mseParamsRec, *mseParamsPtr;
+
+typedef struct {
+ int type;
+ int rate;
+ int delay;
+ int serverNumLock; /* obsolete */
+} kbdParamsRec, *kbdParamsPtr;
+
+typedef enum {
+ TO_MISC,
+ FROM_MISC
+} MseProtoMapDirection;
+
+static void MiscExtClientStateCallback(pointer, pointer, pointer);
+
+/*
+ Sigh...
+
+ The extension should probably be changed to use protocol
+ names instead of ID numbers
+*/
+struct mouse_map {
+ int mtype;
+ MouseProtocolID proto;
+};
+
+static int
+MapMseProto(int proto, MseProtoMapDirection mapping)
+{
+ int i;
+
+ static struct mouse_map m_map[] =
+ {
+ { MTYPE_MICROSOFT, PROT_MS },
+ { MTYPE_MOUSESYS, PROT_MSC },
+ { MTYPE_MMSERIES, PROT_MM },
+ { MTYPE_LOGITECH, PROT_LOGI },
+ { MTYPE_LOGIMAN, PROT_LOGIMAN },
+ { MTYPE_MMHIT, PROT_MMHIT },
+ { MTYPE_GLIDEPOINT, PROT_GLIDE },
+ { MTYPE_IMSERIAL, PROT_IMSERIAL },
+ { MTYPE_THINKING, PROT_THINKING },
+ { MTYPE_ACECAD, PROT_ACECAD },
+ { MTYPE_PS_2, PROT_PS2 },
+ { MTYPE_IMPS2, PROT_IMPS2 },
+ { MTYPE_EXPPS2, PROT_EXPPS2 },
+ { MTYPE_THINKINGPS2, PROT_THINKPS2 },
+ { MTYPE_MMANPLUSPS2, PROT_MMPS2 },
+ { MTYPE_GLIDEPOINTPS2, PROT_GLIDEPS2 },
+ { MTYPE_NETPS2, PROT_NETPS2 },
+ { MTYPE_NETSCROLLPS2, PROT_NETSCPS2 },
+ { MTYPE_BUSMOUSE, PROT_BM },
+ { MTYPE_AUTOMOUSE, PROT_AUTO },
+ { MTYPE_SYSMOUSE, PROT_SYSMOUSE },
+ { MTYPE_UNKNOWN, PROT_UNKNOWN }
+ };
+
+ if (mapping == TO_MISC) {
+ for (i = 0; m_map[i].proto != PROT_UNKNOWN; i++)
+ if (proto == m_map[i].proto) return m_map[i].mtype;
+ return MTYPE_UNKNOWN;
+ } else {
+ for (i = 0; m_map[i].mtype != MTYPE_UNKNOWN; i++)
+ if (proto == m_map[i].mtype) return m_map[i].proto;
+ return PROT_UNKNOWN;
+ }
+}
+
+Bool
+MiscExtGetMouseSettings(pointer *mouse, char **devname)
+{
+ mseParamsPtr mseptr;
+
+ DEBUG_P("MiscExtGetMouseSettings");
+
+ mseptr = MiscExtCreateStruct(MISC_POINTER);
+ if (!mseptr)
+ return FALSE;
+
+ {
+ InputInfoPtr pInfo = mseptr->private;
+ MouseDevPtr pMse;
+
+ *devname = xf86FindOptionValue(pInfo->options, "Device");
+ pMse = pInfo->private;
+
+ mseptr->type = MapMseProto(pMse->protocolID, TO_MISC);
+ mseptr->baudrate = pMse->baudRate;
+ mseptr->samplerate = pMse->sampleRate;
+ mseptr->resolution = pMse->resolution;
+ mseptr->buttons = pMse->buttons;
+ mseptr->em3buttons = pMse->emulate3Buttons;
+ mseptr->em3timeout = pMse->emulate3Timeout;
+ mseptr->chordmiddle = pMse->chordMiddle;
+ mseptr->flags = pMse->mouseFlags;
+ }
+ *mouse = mseptr;
+ return TRUE;
+}
+
+int
+MiscExtGetMouseValue(pointer mouse, MiscExtMseValType valtype)
+{
+ mseParamsPtr mse = mouse;
+
+ DEBUG_P("MiscExtGetMouseValue");
+
+ switch (valtype) {
+ case MISC_MSE_PROTO: return mse->type;
+ case MISC_MSE_BAUDRATE: return mse->baudrate;
+ case MISC_MSE_SAMPLERATE: return mse->samplerate;
+ case MISC_MSE_RESOLUTION: return mse->resolution;
+ case MISC_MSE_BUTTONS: return mse->buttons;
+ case MISC_MSE_EM3BUTTONS: return mse->em3buttons;
+ case MISC_MSE_EM3TIMEOUT: return mse->em3timeout;
+ case MISC_MSE_CHORDMIDDLE: return mse->chordmiddle;
+ case MISC_MSE_FLAGS: return mse->flags;
+ }
+ return 0;
+}
+
+Bool
+MiscExtSetMouseValue(pointer mouse, MiscExtMseValType valtype, int value)
+{
+ mseParamsPtr mse = mouse;
+
+ DEBUG_P("MiscExtSetMouseValue");
+
+ switch (valtype) {
+ case MISC_MSE_PROTO:
+ mse->type = value;
+ return TRUE;
+ case MISC_MSE_BAUDRATE:
+ mse->baudrate = value;
+ return TRUE;
+ case MISC_MSE_SAMPLERATE:
+ mse->samplerate = value;
+ return TRUE;
+ case MISC_MSE_RESOLUTION:
+ mse->resolution = value;
+ return TRUE;
+ case MISC_MSE_BUTTONS:
+ mse->buttons = value;
+ return TRUE;
+ case MISC_MSE_EM3BUTTONS:
+ mse->em3buttons = value;
+ return TRUE;
+ case MISC_MSE_EM3TIMEOUT:
+ mse->em3timeout = value;
+ return TRUE;
+ case MISC_MSE_CHORDMIDDLE:
+ mse->chordmiddle = value;
+ return TRUE;
+ case MISC_MSE_FLAGS:
+ mse->flags = value;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+Bool
+MiscExtSetMouseDevice(pointer mouse, char* device)
+{
+ mseParamsPtr mse = mouse;
+
+ mse->device = device;
+
+ return TRUE;
+}
+
+Bool
+MiscExtGetKbdSettings(pointer *kbd)
+{
+ kbdParamsPtr kbdptr;
+
+ DEBUG_P("MiscExtGetKbdSettings");
+
+ kbdptr = MiscExtCreateStruct(MISC_KEYBOARD);
+ if (!kbdptr)
+ return FALSE;
+ kbdptr->type = xf86Info.kbdType;
+ kbdptr->rate = xf86Info.kbdRate;
+ kbdptr->delay = xf86Info.kbdDelay;
+ *kbd = kbdptr;
+ return TRUE;
+}
+
+int
+MiscExtGetKbdValue(pointer keyboard, MiscExtKbdValType valtype)
+{
+ kbdParamsPtr kbd = keyboard;
+
+ DEBUG_P("MiscExtGetKbdValue");
+ switch (valtype) {
+ case MISC_KBD_TYPE: return kbd->type;
+ case MISC_KBD_RATE: return kbd->rate;
+ case MISC_KBD_DELAY: return kbd->delay;
+ case MISC_KBD_SERVNUMLOCK: return 0;
+ }
+ return 0;
+}
+
+Bool
+MiscExtSetKbdValue(pointer keyboard, MiscExtKbdValType valtype, int value)
+{
+ kbdParamsPtr kbd = keyboard;
+
+ DEBUG_P("MiscExtSetKbdValue");
+ switch (valtype) {
+ case MISC_KBD_TYPE:
+ kbd->type = value;
+ return TRUE;
+ case MISC_KBD_RATE:
+ kbd->rate = value;
+ return TRUE;
+ case MISC_KBD_DELAY:
+ kbd->delay = value;
+ return TRUE;
+ case MISC_KBD_SERVNUMLOCK:
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static void
+MiscExtClientStateCallback(pointer callbacks, pointer data, pointer args)
+{
+ NewClientInfoRec *clientinfo = (NewClientInfoRec*)args;
+
+ if (clientinfo->client == xf86Info.grabInfo.override &&
+ clientinfo->client->clientState == ClientStateGone) {
+ xf86Info.grabInfo.override = NULL;
+ xf86Info.grabInfo.disabled = 0;
+ DeleteCallback(&ClientStateCallback,
+ (CallbackProcPtr)MiscExtClientStateCallback, NULL);
+ }
+}
+
+#define MiscExtGrabStateSuccess 0 /* No errors */
+#define MiscExtGrabStateLocked 1 /* A client already requested that
+ * grabs cannot be removed/killed */
+#define MiscExtGrabStateAlready 2 /* Request for enabling/disabling
+ * grab removeal/kill already done */
+int
+MiscExtSetGrabKeysState(ClientPtr client, int state)
+{
+ DEBUG_P("MiscExtSetGrabKeysState");
+
+ if (xf86Info.grabInfo.override == NULL ||
+ xf86Info.grabInfo.override == client) {
+ if (state == 0 && xf86Info.grabInfo.disabled == 0) {
+ xf86Info.grabInfo.disabled = 1;
+ AddCallback(&ClientStateCallback,
+ (CallbackProcPtr)MiscExtClientStateCallback, NULL);
+ xf86Info.grabInfo.override = client;
+ }
+ else if (state == 1 && xf86Info.grabInfo.disabled == 1) {
+ xf86Info.grabInfo.disabled = 0;
+ DeleteCallback(&ClientStateCallback,
+ (CallbackProcPtr)MiscExtClientStateCallback, NULL);
+ xf86Info.grabInfo.override = NULL;
+ }
+ else
+ return MiscExtGrabStateAlready;
+
+ return MiscExtGrabStateSuccess;
+ }
+
+ return MiscExtGrabStateLocked;
+}
+
+pointer
+MiscExtCreateStruct(MiscExtStructType mse_or_kbd)
+{
+ DEBUG_P("MiscExtCreateStruct");
+
+ switch (mse_or_kbd) {
+ case MISC_POINTER:
+ {
+ mseParamsPtr mseptr;
+ InputInfoPtr pInfo = xf86InputDevs;
+
+ while (pInfo) {
+ if (xf86IsCorePointer(pInfo->dev))
+ break;
+ pInfo = pInfo->next;
+ }
+ if (!pInfo)
+ return NULL;
+
+ mseptr = xcalloc(sizeof(mseParamsRec),1);
+ if (mseptr)
+ mseptr->private = pInfo;
+ return mseptr;
+ }
+ case MISC_KEYBOARD:
+ return xcalloc(sizeof(kbdParamsRec),1);
+ }
+ return 0;
+}
+
+void
+MiscExtDestroyStruct(pointer structure, MiscExtStructType mse_or_kbd)
+{
+ DEBUG_P("MiscExtDestroyStruct");
+
+ switch (mse_or_kbd) {
+ case MISC_POINTER:
+ case MISC_KEYBOARD:
+ xfree(structure);
+ }
+}
+
+static Bool
+MiscExtAuthorizeDevice(InputInfoPtr pInfo, char *device)
+{
+ Bool authorized = FALSE;
+ char *elem;
+ struct stat dev, dev_list;
+ const char *olddev = xf86FindOptionValue(pInfo->options, "Device");
+
+ if (stat(device,&dev))
+ return FALSE;
+
+ if (!S_ISCHR(dev.st_mode))
+ return FALSE;
+
+ if (!stat(olddev,&dev_list)) {
+ if (dev_list.st_dev == dev.st_dev
+ && dev_list.st_ino == dev.st_ino) {
+ authorized = TRUE;
+ }
+ }
+
+ if (!authorized) {
+ char *path;
+
+ if (!xf86InputDeviceList
+ || (path = strdup(xf86InputDeviceList)) == NULL)
+ return FALSE;
+
+ elem = strtok(path,",");
+
+ while (elem) {
+
+ if (!stat(elem,&dev_list)) {
+ if (dev_list.st_dev == dev.st_dev
+ && dev_list.st_ino == dev.st_ino) {
+ authorized = TRUE;
+ break;
+
+ }
+ }
+ elem = strtok(NULL,",");
+ }
+ xfree(path);
+ }
+#if 0
+ ErrorF("AUTHORIZED: %s\n",authorized?"Yes":"No");
+#endif
+ return (authorized);
+}
+
+MiscExtReturn
+MiscExtApply(pointer structure, MiscExtStructType mse_or_kbd)
+{
+ DEBUG_P("MiscExtApply");
+
+ if (mse_or_kbd == MISC_POINTER) {
+ Bool protoChanged = FALSE;
+ int oldflags;
+ Bool reopen = FALSE;
+ mseParamsPtr mse = structure;
+ InputInfoPtr pInfo;
+ MouseDevPtr pMse;
+#ifdef XFree86LOADER
+ pointer xf86MouseProtocolIDToName
+ = LoaderSymbol("xf86MouseProtocolIDToName");
+ if (!xf86MouseProtocolIDToName)
+ return MISC_RET_NOMODULE;
+#endif
+ if (mse->type < MTYPE_MICROSOFT
+ || ( mse->type > MTYPE_EXPPS2
+ && (mse->type!=MTYPE_OSMOUSE && mse->type!=MTYPE_XQUEUE)))
+ return MISC_RET_BADMSEPROTO;
+#ifdef OSMOUSE_ONLY
+ if (mse->type != MTYPE_OSMOUSE)
+ return MISC_RET_BADMSEPROTO;
+#else
+ if (mse->type == MTYPE_XQUEUE)
+ return MISC_RET_BADMSEPROTO;
+ if (mse->type == MTYPE_OSMOUSE)
+ return MISC_RET_BADMSEPROTO;
+#endif /* OSMOUSE_ONLY */
+
+ if (mse->em3timeout < 0)
+ return MISC_RET_BADVAL;
+
+ if (mse->type == MTYPE_LOGIMAN
+ && !(mse->baudrate == 0
+ || mse->baudrate == 1200
+ || mse->baudrate == 9600))
+ return MISC_RET_BADBAUDRATE;
+ if (mse->type == MTYPE_LOGIMAN && mse->samplerate)
+ return MISC_RET_BADCOMBO;
+
+ if (mse->flags & MF_REOPEN) {
+ reopen = TRUE;
+ mse->flags &= ~MF_REOPEN;
+ }
+ if (mse->type != MTYPE_OSMOUSE
+ && mse->type != MTYPE_XQUEUE
+ && mse->type != MTYPE_PS_2
+ && mse->type != MTYPE_BUSMOUSE
+ && mse->type != MTYPE_IMPS2
+ && mse->type != MTYPE_THINKINGPS2
+ && mse->type != MTYPE_MMANPLUSPS2
+ && mse->type != MTYPE_GLIDEPOINTPS2
+ && mse->type != MTYPE_NETPS2
+ && mse->type != MTYPE_NETSCROLLPS2
+ && mse->type != MTYPE_SYSMOUSE)
+ {
+ if (mse->baudrate % 1200 != 0
+ || (mse->baudrate != 0 && mse->baudrate < 1200)
+ || mse->baudrate > 9600)
+ return MISC_RET_BADBAUDRATE;
+ }
+ if ((mse->flags & (MF_CLEAR_DTR|MF_CLEAR_RTS))
+ && (mse->type != MTYPE_MOUSESYS))
+ return MISC_RET_BADFLAGS;
+
+ if (mse->type != MTYPE_OSMOUSE
+ && mse->type != MTYPE_XQUEUE
+ && mse->type != MTYPE_BUSMOUSE)
+ {
+ if (mse->samplerate < 0)
+ return MISC_RET_BADVAL;
+ }
+
+ if (mse->resolution < 0)
+ return MISC_RET_BADVAL;
+ if (mse->chordmiddle)
+ {
+ if (mse->em3buttons || !(mse->type == MTYPE_MICROSOFT
+ || mse->type == MTYPE_LOGIMAN) )
+ return MISC_RET_BADCOMBO;
+ }
+
+ /* XXX - This still needs work */
+
+ pInfo = mse->private;
+ pMse = pInfo->private;
+ oldflags = pMse->mouseFlags;
+
+ protoChanged = pMse->protocolID != MapMseProto(mse->type, FROM_MISC);
+ if (protoChanged
+ || pMse->baudRate != mse->baudrate
+ || pMse->sampleRate != mse->samplerate
+ || pMse->resolution != mse->resolution
+ || pMse->mouseFlags != mse->flags)
+ reopen = TRUE;
+
+ if (mse->device)
+ reopen = TRUE;
+
+ if (reopen)
+ (pMse->device->deviceProc)(pMse->device, DEVICE_CLOSE);
+
+ pMse->protocolID = MapMseProto(mse->type, FROM_MISC);
+ pMse->baudRate = mse->baudrate;
+ pMse->sampleRate = mse->samplerate;
+ pMse->resolution = mse->resolution;
+ pMse->buttons = mse->buttons;
+ pMse->emulate3Buttons = mse->em3buttons;
+ pMse->emulate3Timeout = mse->em3timeout;
+ pMse->chordMiddle = mse->chordmiddle;
+ pMse->mouseFlags = mse->flags;
+
+#ifdef XFree86LOADER
+ pMse->protocol = ((const char *(*)(MouseProtocolID))
+ xf86MouseProtocolIDToName)(pMse->protocolID);
+#else
+ pMse->protocol = xf86MouseProtocolIDToName(pMse->protocolID);
+#endif
+
+ if (mse->device) {
+ if (MiscExtAuthorizeDevice(pInfo, mse->device)) {
+ xf86ReplaceStrOption(pInfo->options, "Device", mse->device);
+ } else {
+ return MISC_RET_BADVAL;
+ }
+ }
+
+ if (reopen) {
+ /* Only if protocol is changed explicitely disable auto detect */
+ if (protoChanged)
+ pMse->autoProbe = FALSE;
+ (pMse->device->deviceProc)(pMse->device, DEVICE_ON);
+ }
+ /* Set pInfo->options too */
+
+ if ((oldflags & MF_CLEAR_DTR) != (pMse->mouseFlags & MF_CLEAR_DTR))
+ xf86ReplaceBoolOption(pInfo->options, "ClearDTR",
+ pMse->mouseFlags | MF_CLEAR_DTR);
+ if ((oldflags & MF_CLEAR_RTS) != (pMse->mouseFlags & MF_CLEAR_RTS))
+ xf86ReplaceBoolOption(pInfo->options, "ClearRTS",
+ pMse->mouseFlags | MF_CLEAR_RTS);
+ }
+ if (mse_or_kbd == MISC_KEYBOARD) {
+ kbdParamsPtr kbd = structure;
+
+ if (kbd->rate < 0)
+ return MISC_RET_BADVAL;
+ if (kbd->delay < 0)
+ return MISC_RET_BADVAL;
+ if (kbd->type < KTYPE_UNKNOWN || kbd->type > KTYPE_XQUEUE)
+ return MISC_RET_BADKBDTYPE;
+
+ if (xf86Info.kbdRate!=kbd->rate || xf86Info.kbdDelay!=kbd->delay) {
+ char rad;
+
+ xf86Info.kbdRate = kbd->rate;
+ xf86Info.kbdDelay = kbd->delay;
+ if (xf86Info.kbdDelay <= 375) rad = 0x00;
+ else if (xf86Info.kbdDelay <= 625) rad = 0x20;
+ else if (xf86Info.kbdDelay <= 875) rad = 0x40;
+ else rad = 0x60;
+
+ if (xf86Info.kbdRate <= 2) rad |= 0x1F;
+ else if (xf86Info.kbdRate >= 30) rad |= 0x00;
+ else rad |= ((58/xf86Info.kbdRate)-2);
+
+ xf86SetKbdRepeat(rad);
+ }
+#if 0 /* Not done yet */
+ xf86Info.kbdType = kbd->kbdtype;
+#endif
+ }
+ return MISC_RET_SUCCESS;
+}
+
+Bool
+MiscExtGetFilePaths(const char **configfile, const char **modulepath,
+ const char **logfile)
+{
+ DEBUG_P("MiscExtGetFilePaths");
+
+ *configfile = xf86ConfigFile;
+ *modulepath = xf86ModulePath;
+ *logfile = xf86LogFile;
+
+ return TRUE;
+}
+
+#endif /* XF86MISC */
+
diff --git a/hw/xfree86/common/xf86Mode.c b/hw/xfree86/common/xf86Mode.c
new file mode 100644
index 000000000..ba73921e4
--- /dev/null
+++ b/hw/xfree86/common/xf86Mode.c
@@ -0,0 +1,1999 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86Mode.c,v 1.63.2.1 2003/04/08 20:51:27 tsi Exp $ */
+
+/*
+ * Copyright (c) 1997,1998 by The XFree86 Project, Inc.
+ *
+ * Authors: Dirk Hohndel <hohndel@XFree86.Org>
+ * David Dawes <dawes@XFree86.Org>
+ *
+ * This file includes helper functions for mode related things.
+ */
+
+#include "X.h"
+#include "os.h"
+#include "servermd.h"
+#include "mibank.h"
+#include "xf86.h"
+#include "xf86Priv.h"
+#include "xf86DDC.h"
+
+/*
+ * xf86GetNearestClock --
+ * Find closest clock to given frequency (in kHz). This assumes the
+ * number of clocks is greater than zero.
+ */
+int
+xf86GetNearestClock(ScrnInfoPtr scrp, int freq, Bool allowDiv2,
+ int DivFactor, int MulFactor, int *divider)
+{
+ int nearestClock = 0, nearestDiv = 1;
+ int minimumGap = abs(freq - scrp->clock[0]);
+ int i, j, k, gap;
+
+ if (allowDiv2)
+ k = 2;
+ else
+ k = 1;
+
+ /* Must set this here in case the best match is scrp->clock[0] */
+ if (divider != NULL)
+ *divider = 0;
+
+ for (i = 0; i < scrp->numClocks; i++) {
+ for (j = 1; j <= k; j++) {
+ gap = abs((freq * j) - ((scrp->clock[i] * DivFactor) / MulFactor));
+ if ((gap < minimumGap) ||
+ ((gap == minimumGap) && (j < nearestDiv))) {
+ minimumGap = gap;
+ nearestClock = i;
+ nearestDiv = j;
+ if (divider != NULL)
+ *divider = (j - 1) * V_CLKDIV2;
+ }
+ }
+ }
+ return nearestClock;
+}
+
+/*
+ * xf86ModeStatusToString
+ *
+ * Convert a ModeStatus value to a printable message
+ */
+
+const char *
+xf86ModeStatusToString(ModeStatus status)
+{
+ switch (status) {
+ case MODE_OK:
+ return "Mode OK";
+ case MODE_HSYNC:
+ return "hsync out of range";
+ case MODE_VSYNC:
+ return "vrefresh out of range";
+ case MODE_H_ILLEGAL:
+ return "illegal horizontal timings";
+ case MODE_V_ILLEGAL:
+ return "illegal vertical timings";
+ case MODE_BAD_WIDTH:
+ return "width requires unsupported line pitch";
+ case MODE_NOMODE:
+ return "no mode of this name";
+ case MODE_NO_INTERLACE:
+ return "interlace mode not supported";
+ case MODE_NO_DBLESCAN:
+ return "doublescan mode not supported";
+ case MODE_NO_VSCAN:
+ return "multiscan mode not supported";
+ case MODE_MEM:
+ return "insufficient memory for mode";
+ case MODE_VIRTUAL_X:
+ return "width too large for virtual size";
+ case MODE_VIRTUAL_Y:
+ return "height too large for virtual size";
+ case MODE_MEM_VIRT:
+ return "insufficient memory given virtual size";
+ case MODE_NOCLOCK:
+ return "no clock available for mode";
+ case MODE_CLOCK_HIGH:
+ return "mode clock too high";
+ case MODE_CLOCK_LOW:
+ return "mode clock too low";
+ case MODE_CLOCK_RANGE:
+ return "bad mode clock/interlace/doublescan";
+ case MODE_BAD_HVALUE:
+ return "horizontal timing out of range";
+ case MODE_BAD_VVALUE:
+ return "vertical timing out of range";
+ case MODE_BAD_VSCAN:
+ return "VScan value out of range";
+ case MODE_HSYNC_NARROW:
+ return "horizontal sync too narrow";
+ case MODE_HSYNC_WIDE:
+ return "horizontal sync too wide";
+ case MODE_HBLANK_NARROW:
+ return "horizontal blanking too narrow";
+ case MODE_HBLANK_WIDE:
+ return "horizontal blanking too wide";
+ case MODE_VSYNC_NARROW:
+ return "vertical sync too narrow";
+ case MODE_VSYNC_WIDE:
+ return "vertical sync too wide";
+ case MODE_VBLANK_NARROW:
+ return "vertical blanking too narrow";
+ case MODE_VBLANK_WIDE:
+ return "vertical blanking too wide";
+ case MODE_PANEL:
+ return "exceeds panel dimensions";
+ case MODE_INTERLACE_WIDTH:
+ return "width too large for interlaced mode";
+ case MODE_ONE_WIDTH:
+ return "all modes must have the same width";
+ case MODE_ONE_HEIGHT:
+ return "all modes must have the same height";
+ case MODE_ONE_SIZE:
+ return "all modes must have the same resolution";
+ case MODE_BAD:
+ return "unknown reason";
+ case MODE_ERROR:
+ return "internal error";
+ default:
+ return "unknown";
+ }
+}
+
+/*
+ * xf86ShowClockRanges() -- Print the clock ranges allowed
+ * and the clock values scaled by ClockMulFactor and ClockDivFactor
+ */
+void
+xf86ShowClockRanges(ScrnInfoPtr scrp, ClockRangePtr clockRanges)
+{
+ ClockRangePtr cp;
+ int MulFactor = 1;
+ int DivFactor = 1;
+ int i, j;
+ int scaledClock;
+
+ for (cp = clockRanges; cp != NULL; cp = cp->next) {
+ DivFactor = max(1, cp->ClockDivFactor);
+ MulFactor = max(1, cp->ClockMulFactor);
+ if (scrp->progClock) {
+ if (cp->minClock) {
+ if (cp->maxClock) {
+ xf86DrvMsg(scrp->scrnIndex, X_INFO,
+ "Clock range: %6.2f to %6.2f MHz\n",
+ (double)cp->minClock / 1000.0,
+ (double)cp->maxClock / 1000.0);
+ } else {
+ xf86DrvMsg(scrp->scrnIndex, X_INFO,
+ "Minimum clock: %6.2f MHz\n",
+ (double)cp->minClock / 1000.0);
+ }
+ } else {
+ if (cp->maxClock) {
+ xf86DrvMsg(scrp->scrnIndex, X_INFO,
+ "Maximum clock: %6.2f MHz\n",
+ (double)cp->maxClock / 1000.0);
+ }
+ }
+ } else if (DivFactor > 1 || MulFactor > 1) {
+ j = 0;
+ for (i = 0; i < scrp->numClocks; i++) {
+ scaledClock = (scrp->clock[i] * DivFactor) / MulFactor;
+ if (scaledClock >= cp->minClock && scaledClock <= cp->maxClock) {
+ if ((j % 8) == 0) {
+ if (j > 0)
+ xf86ErrorF("\n");
+ xf86DrvMsg(scrp->scrnIndex, X_INFO, "scaled clocks:");
+ }
+ xf86ErrorF(" %6.2f", (double)scaledClock / 1000.0);
+ j++;
+ }
+ }
+ xf86ErrorF("\n");
+ }
+ }
+}
+
+
+/*
+ * xf86FindClockRangeForMode() [... like the name says ...]
+ */
+static ClockRangePtr
+xf86FindClockRangeForMode(ClockRangePtr clockRanges, DisplayModePtr p)
+{
+ ClockRangePtr cp;
+
+ for (cp = clockRanges; ; cp = cp->next)
+ if (!cp ||
+ ((p->Clock >= cp->minClock) &&
+ (p->Clock <= cp->maxClock) &&
+ (cp->interlaceAllowed || !(p->Flags & V_INTERLACE)) &&
+ (cp->doubleScanAllowed ||
+ ((p->VScan <= 1) && !(p->Flags & V_DBLSCAN)))))
+ return cp;
+}
+
+
+/*
+ * xf86HandleBuiltinMode() - handles built-in modes
+ */
+static ModeStatus
+xf86HandleBuiltinMode(ScrnInfoPtr scrp,
+ DisplayModePtr p,
+ DisplayModePtr modep,
+ ClockRangePtr clockRanges,
+ Bool allowDiv2)
+{
+ ClockRangePtr cp;
+ int extraFlags = 0;
+ int MulFactor = 1;
+ int DivFactor = 1;
+ int clockIndex;
+
+ /* Reject previously rejected modes */
+ if (p->status != MODE_OK)
+ return p->status;
+
+ /* Reject previously considered modes */
+ if (p->prev)
+ return MODE_NOMODE;
+
+ if ((p->type & M_T_CLOCK_C) == M_T_CLOCK_C) {
+ /* Check clock is in range */
+ cp = xf86FindClockRangeForMode(clockRanges, p);
+ if (cp == NULL){
+ modep->type = p->type;
+ p->status = MODE_CLOCK_RANGE;
+ return MODE_CLOCK_RANGE;
+ }
+ DivFactor = cp->ClockDivFactor;
+ MulFactor = cp->ClockMulFactor;
+ if (!scrp->progClock) {
+ clockIndex = xf86GetNearestClock(scrp, p->Clock, allowDiv2,
+ cp->ClockDivFactor,
+ cp->ClockMulFactor, &extraFlags);
+ modep->Clock = (scrp->clock[clockIndex] * DivFactor)
+ / MulFactor;
+ modep->ClockIndex = clockIndex;
+ modep->SynthClock = scrp->clock[clockIndex];
+ if (extraFlags & V_CLKDIV2) {
+ modep->Clock /= 2;
+ modep->SynthClock /= 2;
+ }
+ } else {
+ modep->Clock = p->Clock;
+ modep->ClockIndex = -1;
+ modep->SynthClock = (modep->Clock * MulFactor)
+ / DivFactor;
+ }
+ modep->PrivFlags = cp->PrivFlags;
+ } else {
+ if(!scrp->progClock) {
+ modep->Clock = p->Clock;
+ modep->ClockIndex = p->ClockIndex;
+ modep->SynthClock = p->SynthClock;
+ } else {
+ modep->Clock = p->Clock;
+ modep->ClockIndex = -1;
+ modep->SynthClock = p->SynthClock;
+ }
+ modep->PrivFlags = p->PrivFlags;
+ }
+ modep->type = p->type;
+ modep->HDisplay = p->HDisplay;
+ modep->HSyncStart = p->HSyncStart;
+ modep->HSyncEnd = p->HSyncEnd;
+ modep->HTotal = p->HTotal;
+ modep->HSkew = p->HSkew;
+ modep->VDisplay = p->VDisplay;
+ modep->VSyncStart = p->VSyncStart;
+ modep->VSyncEnd = p->VSyncEnd;
+ modep->VTotal = p->VTotal;
+ modep->VScan = p->VScan;
+ modep->Flags = p->Flags | extraFlags;
+ modep->CrtcHDisplay = p->CrtcHDisplay;
+ modep->CrtcHBlankStart = p->CrtcHBlankStart;
+ modep->CrtcHSyncStart = p->CrtcHSyncStart;
+ modep->CrtcHSyncEnd = p->CrtcHSyncEnd;
+ modep->CrtcHBlankEnd = p->CrtcHBlankEnd;
+ modep->CrtcHTotal = p->CrtcHTotal;
+ modep->CrtcHSkew = p->CrtcHSkew;
+ modep->CrtcVDisplay = p->CrtcVDisplay;
+ modep->CrtcVBlankStart = p->CrtcVBlankStart;
+ modep->CrtcVSyncStart = p->CrtcVSyncStart;
+ modep->CrtcVSyncEnd = p->CrtcVSyncEnd;
+ modep->CrtcVBlankEnd = p->CrtcVBlankEnd;
+ modep->CrtcVTotal = p->CrtcVTotal;
+ modep->CrtcHAdjusted = p->CrtcHAdjusted;
+ modep->CrtcVAdjusted = p->CrtcVAdjusted;
+ modep->HSync = p->HSync;
+ modep->VRefresh = p->VRefresh;
+ modep->Private = p->Private;
+ modep->PrivSize = p->PrivSize;
+
+ p->prev = modep;
+
+ return MODE_OK;
+}
+
+/*
+ * xf86LookupMode
+ *
+ * This function returns a mode from the given list which matches the
+ * given name. When multiple modes with the same name are available,
+ * the method of picking the matching mode is determined by the
+ * strategy selected.
+ *
+ * This function takes the following parameters:
+ * scrp ScrnInfoPtr
+ * modep pointer to the returned mode, which must have the name
+ * field filled in.
+ * clockRanges a list of clock ranges. This is optional when all the
+ * modes are built-in modes.
+ * strategy how to decide which mode to use from multiple modes with
+ * the same name
+ *
+ * In addition, the following fields from the ScrnInfoRec are used:
+ * modePool the list of monitor modes compatible with the driver
+ * clocks a list of discrete clocks
+ * numClocks number of discrete clocks
+ * progClock clock is programmable
+ *
+ * If a mode was found, its values are filled in to the area pointed to
+ * by modep, If a mode was not found the return value indicates the
+ * reason.
+ */
+
+ModeStatus
+xf86LookupMode(ScrnInfoPtr scrp, DisplayModePtr modep,
+ ClockRangePtr clockRanges, LookupModeFlags strategy)
+{
+ DisplayModePtr p, bestMode = NULL;
+ ClockRangePtr cp;
+ int i, k, gap, minimumGap = CLOCK_TOLERANCE + 1;
+ double refresh, bestRefresh = 0.0;
+ Bool found = FALSE;
+ int extraFlags = 0;
+ int clockIndex = -1;
+ int MulFactor = 1;
+ int DivFactor = 1;
+ int ModePrivFlags = 0;
+ ModeStatus status = MODE_NOMODE;
+ Bool allowDiv2 = (strategy & LOOKUP_CLKDIV2) != 0;
+ Bool haveBuiltin;
+
+ strategy &= ~(LOOKUP_CLKDIV2 | LOOKUP_OPTIONAL_TOLERANCES);
+
+ /* Some sanity checking */
+ if (scrp == NULL || scrp->modePool == NULL ||
+ (!scrp->progClock && scrp->numClocks == 0)) {
+ ErrorF("xf86LookupMode: called with invalid scrnInfoRec\n");
+ return MODE_ERROR;
+ }
+ if (modep == NULL || modep->name == NULL) {
+ ErrorF("xf86LookupMode: called with invalid modep\n");
+ return MODE_ERROR;
+ }
+ for (cp = clockRanges; cp != NULL; cp = cp->next) {
+ /* DivFactor and MulFactor must be > 0 */
+ cp->ClockDivFactor = max(1, cp->ClockDivFactor);
+ cp->ClockMulFactor = max(1, cp->ClockMulFactor);
+ }
+
+ haveBuiltin = FALSE;
+ /* Scan the mode pool for matching names */
+ for (p = scrp->modePool; p != NULL; p = p->next) {
+ if (strcmp(p->name, modep->name) == 0) {
+ /*
+ * Requested mode is a built-in mode. Don't let the user
+ * override it.
+ * Since built-in modes always come before user specified
+ * modes it will always be found first.
+ */
+ if (p->type & M_T_BUILTIN) {
+ haveBuiltin = TRUE;
+ }
+
+ if (haveBuiltin && !(p->type & M_T_BUILTIN))
+ continue;
+
+ /* Skip over previously rejected modes */
+ if (p->status != MODE_OK) {
+ if (!found)
+ status = p->status;
+ continue;
+ }
+
+ /* Skip over previously considered modes */
+ if (p->prev)
+ continue;
+
+ if (p->type & M_T_BUILTIN) {
+ return xf86HandleBuiltinMode(scrp, p,modep, clockRanges,
+ allowDiv2);
+ }
+
+ /* Check clock is in range */
+ cp = xf86FindClockRangeForMode(clockRanges, p);
+ if (cp == NULL) {
+ /*
+ * XXX Could do more here to provide a more detailed
+ * reason for not finding a mode.
+ */
+ p->status = MODE_CLOCK_RANGE;
+ if (!found)
+ status = MODE_CLOCK_RANGE;
+ continue;
+ }
+
+ /*
+ * If programmable clock and strategy is not LOOKUP_BEST_REFRESH,
+ * the required mode has been found, otherwise record the refresh
+ * and continue looking.
+ */
+ if (scrp->progClock) {
+ found = TRUE;
+ if (strategy != LOOKUP_BEST_REFRESH) {
+ bestMode = p;
+ DivFactor = cp->ClockDivFactor;
+ MulFactor = cp->ClockMulFactor;
+ ModePrivFlags = cp->PrivFlags;
+ break;
+ }
+ if (p->VRefresh > 0.0)
+ refresh = p->VRefresh;
+ else {
+ refresh = p->Clock * 1000.0 / p->HTotal / p->VTotal;
+ if (p->Flags & V_INTERLACE)
+ refresh *= 2.0;
+ if (p->Flags & V_DBLSCAN)
+ refresh /= 2.0;
+ if (p->VScan > 1)
+ refresh /= p->VScan;
+ }
+ if (p->Flags & V_INTERLACE)
+ refresh /= INTERLACE_REFRESH_WEIGHT;
+ if (refresh > bestRefresh) {
+ bestMode = p;
+ DivFactor = cp->ClockDivFactor;
+ MulFactor = cp->ClockMulFactor;
+ ModePrivFlags = cp->PrivFlags;
+ bestRefresh = refresh;
+ }
+ continue;
+ }
+
+ /*
+ * Clock is in range, so if it is not a programmable clock, find
+ * a matching clock.
+ */
+
+ i = xf86GetNearestClock(scrp, p->Clock, allowDiv2,
+ cp->ClockDivFactor, cp->ClockMulFactor, &k);
+ /*
+ * If the clock is too far from the requested clock, this
+ * mode is no good.
+ */
+ if (k & V_CLKDIV2)
+ gap = abs((p->Clock * 2) -
+ ((scrp->clock[i] * cp->ClockDivFactor) / cp->ClockMulFactor));
+ else
+ gap = abs(p->Clock -
+ ((scrp->clock[i] * cp->ClockDivFactor) / cp->ClockMulFactor));
+ if (gap > minimumGap) {
+ p->status = MODE_NOCLOCK;
+ if (!found)
+ status = MODE_NOCLOCK;
+ continue;
+ }
+ found = TRUE;
+
+ if (strategy == LOOKUP_BEST_REFRESH) {
+ if (p->VRefresh > 0.0)
+ refresh = p->VRefresh;
+ else {
+ refresh = p->Clock * 1000.0 / p->HTotal / p->VTotal;
+ if (p->Flags & V_INTERLACE)
+ refresh *= 2.0;
+ if (p->Flags & V_DBLSCAN)
+ refresh /= 2.0;
+ if (p->VScan > 1)
+ refresh /= p->VScan;
+ }
+ if (p->Flags & V_INTERLACE)
+ refresh /= INTERLACE_REFRESH_WEIGHT;
+ if (refresh > bestRefresh) {
+ bestMode = p;
+ DivFactor = cp->ClockDivFactor;
+ MulFactor = cp->ClockMulFactor;
+ ModePrivFlags = cp->PrivFlags;
+ extraFlags = k;
+ clockIndex = i;
+ bestRefresh = refresh;
+ }
+ continue;
+ }
+ if (strategy == LOOKUP_CLOSEST_CLOCK) {
+ if (gap < minimumGap) {
+ bestMode = p;
+ DivFactor = cp->ClockDivFactor;
+ MulFactor = cp->ClockMulFactor;
+ ModePrivFlags = cp->PrivFlags;
+ extraFlags = k;
+ clockIndex = i;
+ minimumGap = gap;
+ }
+ continue;
+ }
+ /*
+ * If strategy is neither LOOKUP_BEST_REFRESH or
+ * LOOKUP_CLOSEST_CLOCK the required mode has been found.
+ */
+ bestMode = p;
+ DivFactor = cp->ClockDivFactor;
+ MulFactor = cp->ClockMulFactor;
+ ModePrivFlags = cp->PrivFlags;
+ extraFlags = k;
+ clockIndex = i;
+ break;
+ }
+ }
+ if (!found || bestMode == NULL)
+ return status;
+
+ /* Fill in the mode parameters */
+ if (scrp->progClock) {
+ modep->Clock = bestMode->Clock;
+ modep->ClockIndex = -1;
+ modep->SynthClock = (modep->Clock * MulFactor) / DivFactor;
+ } else {
+ modep->Clock = (scrp->clock[clockIndex] * DivFactor) / MulFactor;
+ modep->ClockIndex = clockIndex;
+ modep->SynthClock = scrp->clock[clockIndex];
+ if (extraFlags & V_CLKDIV2) {
+ modep->Clock /= 2;
+ modep->SynthClock /= 2;
+ }
+ }
+ modep->type = bestMode->type;
+ modep->PrivFlags = ModePrivFlags;
+ modep->HDisplay = bestMode->HDisplay;
+ modep->HSyncStart = bestMode->HSyncStart;
+ modep->HSyncEnd = bestMode->HSyncEnd;
+ modep->HTotal = bestMode->HTotal;
+ modep->HSkew = bestMode->HSkew;
+ modep->VDisplay = bestMode->VDisplay;
+ modep->VSyncStart = bestMode->VSyncStart;
+ modep->VSyncEnd = bestMode->VSyncEnd;
+ modep->VTotal = bestMode->VTotal;
+ modep->VScan = bestMode->VScan;
+ modep->Flags = bestMode->Flags | extraFlags;
+ modep->CrtcHDisplay = bestMode->CrtcHDisplay;
+ modep->CrtcHBlankStart = bestMode->CrtcHBlankStart;
+ modep->CrtcHSyncStart = bestMode->CrtcHSyncStart;
+ modep->CrtcHSyncEnd = bestMode->CrtcHSyncEnd;
+ modep->CrtcHBlankEnd = bestMode->CrtcHBlankEnd;
+ modep->CrtcHTotal = bestMode->CrtcHTotal;
+ modep->CrtcHSkew = bestMode->CrtcHSkew;
+ modep->CrtcVDisplay = bestMode->CrtcVDisplay;
+ modep->CrtcVBlankStart = bestMode->CrtcVBlankStart;
+ modep->CrtcVSyncStart = bestMode->CrtcVSyncStart;
+ modep->CrtcVSyncEnd = bestMode->CrtcVSyncEnd;
+ modep->CrtcVBlankEnd = bestMode->CrtcVBlankEnd;
+ modep->CrtcVTotal = bestMode->CrtcVTotal;
+ modep->CrtcHAdjusted = bestMode->CrtcHAdjusted;
+ modep->CrtcVAdjusted = bestMode->CrtcVAdjusted;
+ modep->HSync = bestMode->HSync;
+ modep->VRefresh = bestMode->VRefresh;
+ modep->Private = bestMode->Private;
+ modep->PrivSize = bestMode->PrivSize;
+
+ bestMode->prev = modep;
+
+ return MODE_OK;
+}
+
+
+/*
+ * xf86SetModeCrtc
+ *
+ * Initialises the Crtc parameters for a mode. The initialisation includes
+ * adjustments for interlaced and double scan modes.
+ */
+static void
+xf86SetModeCrtc(DisplayModePtr p, int adjustFlags)
+{
+ if ((p == NULL) || ((p->type & M_T_CRTC_C) == M_T_BUILTIN))
+ return;
+
+ p->CrtcHDisplay = p->HDisplay;
+ p->CrtcHSyncStart = p->HSyncStart;
+ p->CrtcHSyncEnd = p->HSyncEnd;
+ p->CrtcHTotal = p->HTotal;
+ p->CrtcHSkew = p->HSkew;
+ p->CrtcVDisplay = p->VDisplay;
+ p->CrtcVSyncStart = p->VSyncStart;
+ p->CrtcVSyncEnd = p->VSyncEnd;
+ p->CrtcVTotal = p->VTotal;
+ if ((p->Flags & V_INTERLACE) && (adjustFlags & INTERLACE_HALVE_V))
+ {
+ p->CrtcVDisplay /= 2;
+ p->CrtcVSyncStart /= 2;
+ p->CrtcVSyncEnd /= 2;
+ p->CrtcVTotal /= 2;
+ }
+ if (p->Flags & V_DBLSCAN) {
+ p->CrtcVDisplay *= 2;
+ p->CrtcVSyncStart *= 2;
+ p->CrtcVSyncEnd *= 2;
+ p->CrtcVTotal *= 2;
+ }
+ if (p->VScan > 1) {
+ p->CrtcVDisplay *= p->VScan;
+ p->CrtcVSyncStart *= p->VScan;
+ p->CrtcVSyncEnd *= p->VScan;
+ p->CrtcVTotal *= p->VScan;
+ }
+ p->CrtcHAdjusted = FALSE;
+ p->CrtcVAdjusted = FALSE;
+
+ /*
+ * XXX
+ *
+ * The following is taken from VGA, but applies to other cores as well.
+ */
+ p->CrtcVBlankStart = min(p->CrtcVSyncStart, p->CrtcVDisplay);
+ p->CrtcVBlankEnd = max(p->CrtcVSyncEnd, p->CrtcVTotal);
+ if ((p->CrtcVBlankEnd - p->CrtcVBlankStart) >= 127) {
+ /*
+ * V Blanking size must be < 127.
+ * Moving blank start forward is safer than moving blank end
+ * back, since monitors clamp just AFTER the sync pulse (or in
+ * the sync pulse), but never before.
+ */
+ p->CrtcVBlankStart = p->CrtcVBlankEnd - 127;
+ }
+ p->CrtcHBlankStart = min(p->CrtcHSyncStart, p->CrtcHDisplay);
+ p->CrtcHBlankEnd = max(p->CrtcHSyncEnd, p->CrtcHTotal);
+ if ((p->CrtcHBlankEnd - p->CrtcHBlankStart) >= 63 * 8) {
+ /*
+ * H Blanking size must be < 63*8. Same remark as above.
+ */
+ p->CrtcHBlankStart = p->CrtcHBlankEnd - 63 * 8;
+ }
+}
+
+/*
+ * xf86CheckModeForMonitor
+ *
+ * This function takes a mode and monitor description, and determines
+ * if the mode is valid for the monitor.
+ */
+ModeStatus
+xf86CheckModeForMonitor(DisplayModePtr mode, MonPtr monitor)
+{
+ int i;
+ float hsync, vrefresh;
+
+ /* Sanity checks */
+ if (mode == NULL || monitor == NULL) {
+ ErrorF("xf86CheckModeForMonitor: called with invalid parameters\n");
+ return MODE_ERROR;
+ }
+
+#ifdef DEBUG
+ ErrorF("xf86CheckModeForMonitor(%p %s, %p %s)\n",
+ mode, mode->name, monitor, monitor->id);
+#endif
+
+ if (monitor->DDC) {
+ xf86MonPtr DDC = (xf86MonPtr)(monitor->DDC);
+ struct detailed_monitor_section* detMon;
+ struct monitor_ranges *mon_range;
+ int i;
+
+ mon_range = NULL;
+ for (i = 0; i < 4; i++) {
+ detMon = &DDC->det_mon[i];
+ if(detMon->type == DS_RANGES) {
+ mon_range = &detMon->section.ranges;
+ }
+ }
+ if (mon_range) {
+ /* mode->Clock in kHz, DDC in MHz */
+ if (mon_range->max_clock < 2550 &&
+ mode->Clock / 1000.0 > mon_range->max_clock) {
+ xf86Msg(X_WARNING,
+ "(%s,%s) mode clock %gMHz exceeds DDC maximum %dMHz\n",
+ mode->name, monitor->id,
+ mode->Clock/1000.0, mon_range->max_clock);
+ }
+ }
+ }
+
+ /* Some basic mode validity checks */
+ if (0 >= mode->HDisplay || mode->HDisplay > mode->HSyncStart ||
+ mode->HSyncStart >= mode->HSyncEnd || mode->HSyncEnd >= mode->HTotal)
+ return MODE_H_ILLEGAL;
+
+ if (0 >= mode->VDisplay || mode->VDisplay > mode->VSyncStart ||
+ mode->VSyncStart >= mode->VSyncEnd || mode->VSyncEnd >= mode->VTotal)
+ return MODE_V_ILLEGAL;
+
+ if (monitor->nHsync > 0) {
+ /* Check hsync against the allowed ranges */
+ hsync = (float)mode->Clock / (float)mode->HTotal;
+ for (i = 0; i < monitor->nHsync; i++)
+ if ((hsync > monitor->hsync[i].lo * (1.0 - SYNC_TOLERANCE)) &&
+ (hsync < monitor->hsync[i].hi * (1.0 + SYNC_TOLERANCE)))
+ break;
+
+ /* Now see whether we ran out of sync ranges without finding a match */
+ if (i == monitor->nHsync)
+ return MODE_HSYNC;
+ }
+
+ if (monitor->nVrefresh > 0) {
+ /* Check vrefresh against the allowed ranges */
+ vrefresh = mode->Clock * 1000.0 / (mode->HTotal * mode->VTotal);
+ if (mode->Flags & V_INTERLACE)
+ vrefresh *= 2.0;
+ if (mode->Flags & V_DBLSCAN)
+ vrefresh /= 2.0;
+ if (mode->VScan > 1)
+ vrefresh /= (float)(mode->VScan);
+ for (i = 0; i < monitor->nVrefresh; i++)
+ if ((vrefresh > monitor->vrefresh[i].lo * (1.0 - SYNC_TOLERANCE)) &&
+ (vrefresh < monitor->vrefresh[i].hi * (1.0 + SYNC_TOLERANCE)))
+ break;
+
+ /* Now see whether we ran out of refresh ranges without finding a match */
+ if (i == monitor->nVrefresh)
+ return MODE_VSYNC;
+ }
+
+ /* Force interlaced modes to have an odd VTotal */
+ if (mode->Flags & V_INTERLACE)
+ mode->CrtcVTotal = mode->VTotal |= 1;
+
+ return MODE_OK;
+}
+
+/*
+ * xf86CheckModeSize
+ *
+ * An internal routine to check if a mode fits in video memory. This tries to
+ * avoid overflows that would otherwise occur when video memory size is greater
+ * than 256MB.
+ */
+static Bool
+xf86CheckModeSize(ScrnInfoPtr scrp, int w, int x, int y)
+{
+ int bpp = scrp->fbFormat.bitsPerPixel,
+ pad = scrp->fbFormat.scanlinePad;
+ int lineWidth, lastWidth;
+
+ if (scrp->depth == 4)
+ pad *= 4; /* 4 planes */
+
+ /* Sanity check */
+ if ((w < 0) || (x < 0) || (y <= 0))
+ return FALSE;
+
+ lineWidth = (((w * bpp) + pad - 1) / pad) * pad;
+ lastWidth = x * bpp;
+
+ /*
+ * At this point, we need to compare
+ *
+ * (lineWidth * (y - 1)) + lastWidth
+ *
+ * against
+ *
+ * scrp->videoRam * (1024 * 8)
+ *
+ * These are bit quantities. To avoid overflows, do the comparison in
+ * terms of BITMAP_SCANLINE_PAD units. This assumes BITMAP_SCANLINE_PAD
+ * is a power of 2. We currently use 32, which limits us to a video
+ * memory size of 8GB.
+ */
+
+ lineWidth = (lineWidth + (BITMAP_SCANLINE_PAD - 1)) / BITMAP_SCANLINE_PAD;
+ lastWidth = (lastWidth + (BITMAP_SCANLINE_PAD - 1)) / BITMAP_SCANLINE_PAD;
+
+ if ((lineWidth * (y - 1) + lastWidth) >
+ (scrp->videoRam * ((1024 * 8) / BITMAP_SCANLINE_PAD)))
+ return FALSE;
+
+ return TRUE;
+}
+
+/*
+ * xf86InitialCheckModeForDriver
+ *
+ * This function checks if a mode satisfies a driver's initial requirements:
+ * - mode size fits within the available pixel area (memory)
+ * - width lies within the range of supported line pitches
+ * - mode size fits within virtual size (if fixed)
+ * - horizontal timings are in range
+ *
+ * This function takes the following parameters:
+ * scrp ScrnInfoPtr
+ * mode mode to check
+ * maxPitch (optional) maximum line pitch
+ * virtualX (optional) virtual width requested
+ * virtualY (optional) virtual height requested
+ *
+ * In addition, the following fields from the ScrnInfoRec are used:
+ * monitor pointer to structure for monitor section
+ * fbFormat pixel format for the framebuffer
+ * videoRam video memory size (in kB)
+ * maxHValue maximum horizontal timing value
+ * maxVValue maximum vertical timing value
+ */
+
+ModeStatus
+xf86InitialCheckModeForDriver(ScrnInfoPtr scrp, DisplayModePtr mode,
+ ClockRangePtr clockRanges,
+ LookupModeFlags strategy,
+ int maxPitch, int virtualX, int virtualY)
+{
+ MonPtr monitor;
+ ClockRangePtr cp;
+ ModeStatus status;
+ Bool allowDiv2 = (strategy & LOOKUP_CLKDIV2) != 0;
+ int i, needDiv2;
+
+ /* Sanity checks */
+ if (!scrp || !mode /*|| !clockRanges*/) {
+ ErrorF("xf86InitialCheckModeForDriver: "
+ "called with invalid parameters\n");
+ return MODE_ERROR;
+ }
+
+#ifdef DEBUG
+ ErrorF("xf86InitialCheckModeForDriver(%p, %p %s, %p, 0x%x, %d, %d, %d)\n",
+ scrp, mode, mode->name , clockRanges, strategy, maxPitch, virtualX, virtualY);
+#endif
+
+ /* Some basic mode validity checks */
+ if (0 >= mode->HDisplay || mode->HDisplay > mode->HSyncStart ||
+ mode->HSyncStart >= mode->HSyncEnd || mode->HSyncEnd >= mode->HTotal)
+ return MODE_H_ILLEGAL;
+
+ if (0 >= mode->VDisplay || mode->VDisplay > mode->VSyncStart ||
+ mode->VSyncStart >= mode->VSyncEnd || mode->VSyncEnd >= mode->VTotal)
+ return MODE_V_ILLEGAL;
+
+ if (!xf86CheckModeSize(scrp, mode->HDisplay, mode->HDisplay,
+ mode->VDisplay))
+ return MODE_MEM;
+
+ if (maxPitch > 0 && mode->HDisplay > maxPitch)
+ return MODE_BAD_WIDTH;
+
+ if (virtualX > 0 && mode->HDisplay > virtualX)
+ return MODE_VIRTUAL_X;
+
+ if (virtualY > 0 && mode->VDisplay > virtualY)
+ return MODE_VIRTUAL_Y;
+
+ if (scrp->maxHValue > 0 && mode->HTotal > scrp->maxHValue)
+ return MODE_BAD_HVALUE;
+
+ if (scrp->maxVValue > 0 && mode->VTotal > scrp->maxVValue)
+ return MODE_BAD_VVALUE;
+
+ /*
+ * The use of the DisplayModeRec's Crtc* and SynthClock elements below is
+ * provisional, in that they are later reused by the driver at mode-set
+ * time. Here, they are temporarily enlisted to contain the mode timings
+ * as seen by the CRT or panel (rather than the CRTC). The driver's
+ * ValidMode() is allowed to modify these so it can deal with such things
+ * as mode stretching and/or centering. The driver should >NOT< modify the
+ * user-supplied values as these are reported back when mode validation is
+ * said and done.
+ */
+ xf86SetModeCrtc(mode, INTERLACE_HALVE_V);
+
+ cp = xf86FindClockRangeForMode(clockRanges, mode);
+ if (!cp)
+ return MODE_CLOCK_RANGE;
+
+ if (cp->ClockMulFactor < 1)
+ cp->ClockMulFactor = 1;
+ if (cp->ClockDivFactor < 1)
+ cp->ClockDivFactor = 1;
+
+ /*
+ * XXX The effect of clock dividers and multipliers on the monitor's
+ * pixel clock needs to be verified.
+ */
+ if (scrp->progClock) {
+ mode->SynthClock = mode->Clock;
+ } else {
+ i = xf86GetNearestClock(scrp, mode->Clock, allowDiv2,
+ cp->ClockDivFactor, cp->ClockMulFactor,
+ &needDiv2);
+ mode->SynthClock = (scrp->clock[i] * cp->ClockDivFactor) /
+ cp->ClockMulFactor;
+ if (needDiv2 & V_CLKDIV2)
+ mode->SynthClock /= 2;
+ }
+
+ if (scrp->ValidMode) {
+ status = (*scrp->ValidMode)(scrp->scrnIndex, mode, FALSE,
+ MODECHECK_INITIAL);
+ if (status != MODE_OK)
+ return status;
+ }
+
+ if (!(monitor = scrp->monitor)) {
+ ErrorF("xf86InitialCheckModeForDriver: "
+ "called with invalid monitor\n");
+ return MODE_ERROR;
+ }
+
+ if (mode->HSync <= 0.0)
+ mode->HSync = (float)mode->SynthClock / (float)mode->CrtcHTotal;
+ if (monitor->nHsync > 0) {
+ /* Check hsync against the allowed ranges */
+ for (i = 0; i < monitor->nHsync; i++)
+ if ((mode->HSync > monitor->hsync[i].lo * (1.0 - SYNC_TOLERANCE)) &&
+ (mode->HSync < monitor->hsync[i].hi * (1.0 + SYNC_TOLERANCE)))
+ break;
+
+ /* Now see whether we ran out of sync ranges without finding a match */
+ if (i == monitor->nHsync)
+ return MODE_HSYNC;
+ }
+
+ if (mode->VRefresh <= 0.0)
+ mode->VRefresh = (mode->SynthClock * 1000.0) /
+ (mode->CrtcHTotal * mode->CrtcVTotal);
+ if (monitor->nVrefresh > 0) {
+ /* Check vrefresh against the allowed ranges */
+ for (i = 0; i < monitor->nVrefresh; i++)
+ if ((mode->VRefresh >
+ monitor->vrefresh[i].lo * (1.0 - SYNC_TOLERANCE)) &&
+ (mode->VRefresh <
+ monitor->vrefresh[i].hi * (1.0 + SYNC_TOLERANCE)))
+ break;
+
+ /* Now see whether we ran out of refresh ranges without finding a match */
+ if (i == monitor->nVrefresh)
+ return MODE_VSYNC;
+ }
+
+ /* Force interlaced modes to have an odd VTotal */
+ if (mode->Flags & V_INTERLACE)
+ mode->CrtcVTotal |= 1;
+
+ /* Assume it is OK */
+ return MODE_OK;
+}
+
+/*
+ * xf86CheckModeForDriver
+ *
+ * This function is for checking modes while the server is running (for
+ * use mainly by the VidMode extension).
+ *
+ * This function checks if a mode satisfies a driver's requirements:
+ * - width lies within the line pitch
+ * - mode size fits within virtual size
+ * - horizontal/vertical timings are in range
+ *
+ * This function takes the following parameters:
+ * scrp ScrnInfoPtr
+ * mode mode to check
+ * flags not (currently) used
+ *
+ * In addition, the following fields from the ScrnInfoRec are used:
+ * maxHValue maximum horizontal timing value
+ * maxVValue maximum vertical timing value
+ * virtualX virtual width
+ * virtualY virtual height
+ * clockRanges allowable clock ranges
+ */
+
+ModeStatus
+xf86CheckModeForDriver(ScrnInfoPtr scrp, DisplayModePtr mode, int flags)
+{
+ ClockRangesPtr cp;
+ int i, k, gap, minimumGap = CLOCK_TOLERANCE + 1;
+ int extraFlags = 0;
+ int clockIndex = -1;
+ int MulFactor = 1;
+ int DivFactor = 1;
+ int ModePrivFlags = 0;
+ Bool allowDiv2;
+ ModeStatus status = MODE_NOMODE;
+
+ /* Some sanity checking */
+ if (scrp == NULL || (!scrp->progClock && scrp->numClocks == 0)) {
+ ErrorF("xf86CheckModeForDriver: called with invalid scrnInfoRec\n");
+ return MODE_ERROR;
+ }
+ if (mode == NULL) {
+ ErrorF("xf86CheckModeForDriver: called with invalid modep\n");
+ return MODE_ERROR;
+ }
+
+ /* Check the mode size */
+ if (mode->HDisplay > scrp->virtualX)
+ return MODE_VIRTUAL_X;
+
+ if (mode->VDisplay > scrp->virtualY)
+ return MODE_VIRTUAL_Y;
+
+ if (scrp->maxHValue > 0 && mode->HTotal > scrp->maxHValue)
+ return MODE_BAD_HVALUE;
+
+ if (scrp->maxVValue > 0 && mode->VTotal > scrp->maxVValue)
+ return MODE_BAD_VVALUE;
+
+ for (cp = scrp->clockRanges; cp != NULL; cp = cp->next) {
+ /* DivFactor and MulFactor must be > 0 */
+ cp->ClockDivFactor = max(1, cp->ClockDivFactor);
+ cp->ClockMulFactor = max(1, cp->ClockMulFactor);
+ }
+
+ if (scrp->progClock) {
+ /* Check clock is in range */
+ for (cp = scrp->clockRanges; cp != NULL; cp = cp->next) {
+ if ((cp->minClock <= mode->Clock) &&
+ (cp->maxClock >= mode->Clock) &&
+ (cp->interlaceAllowed || !(mode->Flags & V_INTERLACE)) &&
+ (cp->doubleScanAllowed ||
+ ((!(mode->Flags & V_DBLSCAN)) && (mode->VScan <= 1))))
+ break;
+ }
+ if (cp == NULL) {
+ return MODE_CLOCK_RANGE;
+ }
+ /*
+ * If programmable clock the required mode has been found
+ */
+ DivFactor = cp->ClockDivFactor;
+ MulFactor = cp->ClockMulFactor;
+ ModePrivFlags = cp->PrivFlags;
+ } else {
+ status = MODE_CLOCK_RANGE;
+ /* Check clock is in range */
+ for (cp = scrp->clockRanges; cp != NULL; cp = cp->next) {
+ if ((cp->minClock <= mode->Clock) &&
+ (cp->maxClock >= mode->Clock) &&
+ (cp->interlaceAllowed || !(mode->Flags & V_INTERLACE)) &&
+ (cp->doubleScanAllowed ||
+ ((!(mode->Flags & V_DBLSCAN)) && (mode->VScan <= 1)))) {
+
+ /*
+ * Clock is in range, so if it is not a programmable clock,
+ * find a matching clock.
+ */
+
+ allowDiv2 = (cp->strategy & LOOKUP_CLKDIV2) != 0;
+ i = xf86GetNearestClock(scrp, mode->Clock, allowDiv2,
+ cp->ClockDivFactor, cp->ClockMulFactor, &k);
+ /*
+ * If the clock is too far from the requested clock, this
+ * mode is no good.
+ */
+ if (k & V_CLKDIV2)
+ gap = abs((mode->Clock * 2) -
+ ((scrp->clock[i] * cp->ClockDivFactor) /
+ cp->ClockMulFactor));
+ else
+ gap = abs(mode->Clock -
+ ((scrp->clock[i] * cp->ClockDivFactor) /
+ cp->ClockMulFactor));
+ if (gap > minimumGap) {
+ status = MODE_NOCLOCK;
+ continue;
+ }
+
+ DivFactor = cp->ClockDivFactor;
+ MulFactor = cp->ClockMulFactor;
+ ModePrivFlags = cp->PrivFlags;
+ extraFlags = k;
+ clockIndex = i;
+ break;
+ }
+ }
+ if (cp == NULL)
+ return status;
+ }
+
+ /* Fill in the mode parameters */
+ if (scrp->progClock) {
+ mode->ClockIndex = -1;
+ mode->SynthClock = (mode->Clock * MulFactor) / DivFactor;
+ } else {
+ mode->Clock = (scrp->clock[clockIndex] * DivFactor) / MulFactor;
+ mode->ClockIndex = clockIndex;
+ mode->SynthClock = scrp->clock[clockIndex];
+ if (extraFlags & V_CLKDIV2) {
+ mode->Clock /= 2;
+ mode->SynthClock /= 2;
+ }
+ }
+ mode->PrivFlags = ModePrivFlags;
+
+ return MODE_OK;
+}
+
+/*
+ * xf86ValidateModes
+ *
+ * This function takes a set of mode names, modes and limiting conditions,
+ * and selects a set of modes and parameters based on those conditions.
+ *
+ * This function takes the following parameters:
+ * scrp ScrnInfoPtr
+ * availModes the list of modes available for the monitor
+ * modeNames (optional) list of mode names that the screen is requesting
+ * clockRanges a list of clock ranges
+ * linePitches (optional) a list of line pitches
+ * minPitch (optional) minimum line pitch (in pixels)
+ * maxPitch (optional) maximum line pitch (in pixels)
+ * pitchInc (mandatory) pitch increment (in bits)
+ * minHeight (optional) minimum virtual height (in pixels)
+ * maxHeight (optional) maximum virtual height (in pixels)
+ * virtualX (optional) virtual width requested (in pixels)
+ * virtualY (optional) virtual height requested (in pixels)
+ * apertureSize size of video aperture (in bytes)
+ * strategy how to decide which mode to use from multiple modes with
+ * the same name
+ *
+ * In addition, the following fields from the ScrnInfoRec are used:
+ * clocks a list of discrete clocks
+ * numClocks number of discrete clocks
+ * progClock clock is programmable
+ * monitor pointer to structure for monitor section
+ * fbFormat format of the framebuffer
+ * videoRam video memory size
+ * maxHValue maximum horizontal timing value
+ * maxVValue maximum vertical timing value
+ * xInc horizontal timing increment (defaults to 8 pixels)
+ *
+ * The function fills in the following ScrnInfoRec fields:
+ * modePool A subset of the modes available to the monitor which
+ * are compatible with the driver.
+ * modes one mode entry for each of the requested modes, with the
+ * status field filled in to indicate if the mode has been
+ * accepted or not.
+ * virtualX the resulting virtual width
+ * virtualY the resulting virtual height
+ * displayWidth the resulting line pitch
+ *
+ * The function's return value is the number of matching modes found, or -1
+ * if an unrecoverable error was encountered.
+ */
+
+int
+xf86ValidateModes(ScrnInfoPtr scrp, DisplayModePtr availModes,
+ char **modeNames, ClockRangePtr clockRanges,
+ int *linePitches, int minPitch, int maxPitch, int pitchInc,
+ int minHeight, int maxHeight, int virtualX, int virtualY,
+ int apertureSize, LookupModeFlags strategy)
+{
+ DisplayModePtr p, q, r, new, last, *endp;
+ int i, numModes = 0;
+ ModeStatus status;
+ int linePitch = -1, virtX = 0, virtY = 0;
+ int newLinePitch, newVirtX, newVirtY;
+ int modeSize; /* in pixels */
+ Bool validateAllDefaultModes;
+ Bool userModes = FALSE;
+ int saveType;
+ PixmapFormatRec *BankFormat;
+ ClockRangePtr cp;
+ ClockRangesPtr storeClockRanges;
+ struct monitor_ranges *mon_range = NULL;
+
+#ifdef DEBUG
+ ErrorF("xf86ValidateModes(%p, %p, %p, %p,\n\t\t %p, %d, %d, %d, %d, %d, %d, %d, %d, 0x%x)\n",
+ scrp, availModes, modeNames, clockRanges,
+ linePitches, minPitch, maxPitch, pitchInc,
+ minHeight, maxHeight, virtualX, virtualY,
+ apertureSize, strategy
+ );
+#endif
+
+ /* Some sanity checking */
+ if (scrp == NULL || scrp->name == NULL || !scrp->monitor ||
+ (!scrp->progClock && scrp->numClocks == 0)) {
+ ErrorF("xf86ValidateModes: called with invalid scrnInfoRec\n");
+ return -1;
+ }
+ if (linePitches != NULL && linePitches[0] <= 0) {
+ ErrorF("xf86ValidateModes: called with invalid linePitches\n");
+ return -1;
+ }
+ if (pitchInc <= 0) {
+ ErrorF("xf86ValidateModes: called with invalid pitchInc\n");
+ return -1;
+ }
+ if ((virtualX > 0) != (virtualY > 0)) {
+ ErrorF("xf86ValidateModes: called with invalid virtual resolution\n");
+ return -1;
+ }
+
+ /* Probe monitor so that we can enforce/warn about its limits */
+ if (scrp->monitor->DDC) {
+ MonPtr monitor = scrp->monitor;
+ xf86MonPtr DDC = (xf86MonPtr)(scrp->monitor->DDC);
+ struct detailed_monitor_section* detMon;
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ detMon = &DDC->det_mon[i];
+ if(detMon->type == DS_RANGES) {
+ mon_range = &detMon->section.ranges;
+ }
+ }
+ if (mon_range) {
+
+#ifdef DEBUG
+ ErrorF("DDC - Max clock %d, Hsync %d-%d kHz - Vrefresh %d-%d Hz\n",
+ mon_range->max_clock, mon_range->min_h, mon_range->max_h,
+ mon_range->min_v, mon_range->max_v );
+#endif
+
+#define DDC_SYNC_TOLERANCE SYNC_TOLERANCE
+ if (monitor->nHsync > 0) {
+ for (i = 0; i < monitor->nHsync; i++) {
+ if ((1.0 - DDC_SYNC_TOLERANCE) * mon_range->min_h >
+ monitor->hsync[i].lo ||
+ (1.0 + DDC_SYNC_TOLERANCE) * mon_range->max_h <
+ monitor->hsync[i].hi) {
+ xf86DrvMsg(scrp->scrnIndex, X_WARNING,
+ "config file hsync range %g-%gkHz not within DDC "
+ "hsync range %d-%dkHz\n",
+ monitor->hsync[i].lo, monitor->hsync[i].hi,
+ mon_range->min_h, mon_range->max_h);
+ }
+ }
+ }
+
+ if (monitor->nVrefresh > 0) {
+ for (i=0; i<monitor->nVrefresh; i++) {
+ if ((1.0 - DDC_SYNC_TOLERANCE) * mon_range->min_v >
+ monitor->vrefresh[0].lo ||
+ (1.0 + DDC_SYNC_TOLERANCE) * mon_range->max_v <
+ monitor->vrefresh[0].hi) {
+ xf86DrvMsg(scrp->scrnIndex, X_WARNING,
+ "config file vrefresh range %g-%gHz not within DDC "
+ "vrefresh range %d-%dHz\n",
+ monitor->vrefresh[i].lo, monitor->vrefresh[i].hi,
+ mon_range->min_v, mon_range->max_v);
+ }
+ }
+ }
+ } /* if (mon_range) */
+ }
+
+ /*
+ * If requested by the driver, allow missing hsync and/or vrefresh ranges
+ * in the monitor section.
+ */
+ if (strategy & LOOKUP_OPTIONAL_TOLERANCES) {
+ strategy &= ~LOOKUP_OPTIONAL_TOLERANCES;
+ } else {
+ if (scrp->monitor->nHsync <= 0) {
+ if (mon_range) {
+ scrp->monitor->hsync[0].lo = mon_range->min_h;
+ scrp->monitor->hsync[0].hi = mon_range->max_h;
+ } else {
+ scrp->monitor->hsync[0].lo = 28;
+ scrp->monitor->hsync[0].hi = 33;
+ }
+ xf86DrvMsg(scrp->scrnIndex, X_WARNING,
+ "%s: Using default hsync range of %.2f-%.2fkHz\n",
+ scrp->monitor->id,
+ scrp->monitor->hsync[0].lo, scrp->monitor->hsync[0].hi);
+ scrp->monitor->nHsync = 1;
+ } else {
+ for (i = 0; i < scrp->monitor->nHsync; i++)
+ if (scrp->monitor->hsync[i].lo == scrp->monitor->hsync[i].hi)
+ xf86DrvMsg(scrp->scrnIndex, X_INFO,
+ "%s: Using hsync value of %.2f kHz\n",
+ scrp->monitor->id,
+ scrp->monitor->hsync[i].lo);
+ else
+ xf86DrvMsg(scrp->scrnIndex, X_INFO,
+ "%s: Using hsync range of %.2f-%.2f kHz\n",
+ scrp->monitor->id,
+ scrp->monitor->hsync[i].lo,
+ scrp->monitor->hsync[i].hi);
+ }
+ if (scrp->monitor->nVrefresh <= 0) {
+ if (mon_range) {
+ scrp->monitor->vrefresh[0].lo = mon_range->min_v;
+ scrp->monitor->vrefresh[0].hi = mon_range->max_v;
+ } else {
+ scrp->monitor->vrefresh[0].lo = 43;
+ scrp->monitor->vrefresh[0].hi = 72;
+ }
+ xf86DrvMsg(scrp->scrnIndex, X_WARNING,
+ "%s: using default vrefresh range of %.2f-%.2fHz\n",
+ scrp->monitor->id,
+ scrp->monitor->vrefresh[0].lo,
+ scrp->monitor->vrefresh[0].hi);
+ scrp->monitor->nVrefresh = 1;
+ } else {
+ for (i = 0; i < scrp->monitor->nVrefresh; i++)
+ if (scrp->monitor->vrefresh[i].lo == scrp->monitor->vrefresh[i].hi)
+ xf86DrvMsg(scrp->scrnIndex, X_INFO,
+ "%s: Using vrefresh value of %.2f Hz\n",
+ scrp->monitor->id,
+ scrp->monitor->vrefresh[i].lo);
+ else
+ xf86DrvMsg(scrp->scrnIndex, X_INFO,
+ "%s: Using vrefresh range of %.2f-%.2f Hz\n",
+ scrp->monitor->id,
+ scrp->monitor->vrefresh[i].lo,
+ scrp->monitor->vrefresh[i].hi);
+ }
+ }
+
+ /*
+ * Store the clockRanges for later use by the VidMode extension. Must
+ * also store the strategy, since ClockDiv2 flag is stored there.
+ */
+ storeClockRanges = scrp->clockRanges;
+ while (storeClockRanges != NULL) {
+ storeClockRanges = storeClockRanges->next;
+ }
+ for (cp = clockRanges; cp != NULL; cp = cp->next,
+ storeClockRanges = storeClockRanges->next) {
+ storeClockRanges = xnfalloc(sizeof(ClockRanges));
+ if (scrp->clockRanges == NULL)
+ scrp->clockRanges = storeClockRanges;
+ memcpy(storeClockRanges, cp, sizeof(ClockRange));
+ storeClockRanges->strategy = strategy;
+ }
+
+ /* Determine which pixmap format to pass to miScanLineWidth() */
+ if (scrp->depth > 4)
+ BankFormat = &scrp->fbFormat;
+ else
+ BankFormat = xf86GetPixFormat(scrp, 1); /* >not< scrp->depth! */
+
+ if (scrp->xInc <= 0)
+ scrp->xInc = 8; /* Suitable for VGA and others */
+
+#define _VIRTUALX(x) ((((x) + scrp->xInc - 1) / scrp->xInc) * scrp->xInc)
+
+ /*
+ * Determine maxPitch if it wasn't given explicitly. Note linePitches
+ * always takes precedence if is non-NULL. In that case the minPitch and
+ * maxPitch values passed are ignored.
+ */
+ if (linePitches) {
+ minPitch = maxPitch = linePitches[0];
+ for (i = 1; linePitches[i] > 0; i++) {
+ if (linePitches[i] > maxPitch)
+ maxPitch = linePitches[i];
+ if (linePitches[i] < minPitch)
+ minPitch = linePitches[i];
+ }
+ }
+
+ /* Initial check of virtual size against other constraints */
+ scrp->virtualFrom = X_PROBED;
+ /*
+ * Initialise virtX and virtY if the values are fixed.
+ */
+ if (virtualY > 0) {
+ if (maxHeight > 0 && virtualY > maxHeight) {
+ xf86DrvMsg(scrp->scrnIndex, X_ERROR,
+ "Virtual height (%d) is too large for the hardware "
+ "(max %d)\n", virtualY, maxHeight);
+ return -1;
+ }
+
+ if (minHeight > 0 && virtualY < minHeight) {
+ xf86DrvMsg(scrp->scrnIndex, X_ERROR,
+ "Virtual height (%d) is too small for the hardware "
+ "(min %d)\n", virtualY, minHeight);
+ return -1;
+ }
+
+ virtualX = _VIRTUALX(virtualX);
+ if (linePitches != NULL) {
+ for (i = 0; linePitches[i] != 0; i++) {
+ if ((linePitches[i] >= virtualX) &&
+ (linePitches[i] ==
+ miScanLineWidth(virtualX, virtualY, linePitches[i],
+ apertureSize, BankFormat, pitchInc))) {
+ linePitch = linePitches[i];
+ break;
+ }
+ }
+ } else {
+ linePitch = miScanLineWidth(virtualX, virtualY, minPitch,
+ apertureSize, BankFormat, pitchInc);
+ }
+
+ if ((linePitch < minPitch) || (linePitch > maxPitch)) {
+ xf86DrvMsg(scrp->scrnIndex, X_ERROR,
+ "Virtual width (%d) is too large for the hardware "
+ "(max %d)\n", virtualX, maxPitch);
+ return -1;
+ }
+
+ if (!xf86CheckModeSize(scrp, linePitch, virtualX, virtualY)) {
+ xf86DrvMsg(scrp->scrnIndex, X_ERROR,
+ "Virtual size (%dx%d) (pitch %d) exceeds video memory\n",
+ virtualX, virtualY, linePitch);
+ return -1;
+ }
+
+ virtX = virtualX;
+ virtY = virtualY;
+ scrp->virtualFrom = X_CONFIG;
+ }
+
+ /* Print clock ranges and scaled clocks */
+ xf86ShowClockRanges(scrp, clockRanges);
+
+ /*
+ * If scrp->modePool hasn't been setup yet, set it up now. This allows the
+ * modes that the driver definitely can't use to be weeded out early. Note
+ * that a modePool mode's prev field is used to hold a pointer to the
+ * member of the scrp->modes list for which a match was considered.
+ */
+ if (scrp->modePool == NULL) {
+ q = NULL;
+ for (p = availModes; p != NULL; p = p->next) {
+ status = xf86InitialCheckModeForDriver(scrp, p, clockRanges,
+ strategy, maxPitch,
+ virtualX, virtualY);
+
+ if (status == MODE_OK)
+ status = xf86CheckModeForMonitor(p, scrp->monitor);
+
+ if (status == MODE_OK) {
+ new = xnfalloc(sizeof(DisplayModeRec));
+ *new = *p;
+ new->next = NULL;
+ if (!q) {
+ scrp->modePool = new;
+ } else {
+ q->next = new;
+ }
+ new->prev = NULL;
+ q = new;
+ q->name = xnfstrdup(p->name);
+ q->status = MODE_OK;
+ } else {
+ if (p->type & M_T_BUILTIN)
+ xf86DrvMsg(scrp->scrnIndex, X_INFO,
+ "Not using built-in mode \"%s\" (%s)\n",
+ p->name, xf86ModeStatusToString(status));
+ else if (p->type & M_T_DEFAULT)
+ xf86DrvMsg(scrp->scrnIndex, X_INFO,
+ "Not using default mode \"%s\" (%s)\n", p->name,
+ xf86ModeStatusToString(status));
+ else
+ xf86DrvMsg(scrp->scrnIndex, X_INFO,
+ "Not using mode \"%s\" (%s)\n", p->name,
+ xf86ModeStatusToString(status));
+ }
+ }
+
+ if (scrp->modePool == NULL) {
+ xf86DrvMsg(scrp->scrnIndex, X_WARNING, "Mode pool is empty\n");
+ return 0;
+ }
+ } else {
+ for (p = scrp->modePool; p != NULL; p = p->next) {
+ p->prev = NULL;
+ p->status = MODE_OK;
+ }
+ }
+
+ /*
+ * Allocate one entry in scrp->modes for each named mode.
+ */
+ while (scrp->modes)
+ xf86DeleteMode(&scrp->modes, scrp->modes);
+ endp = &scrp->modes;
+ last = NULL;
+ if (modeNames != NULL) {
+ for (i = 0; modeNames[i] != NULL; i++) {
+ userModes = TRUE;
+ new = xnfcalloc(1, sizeof(DisplayModeRec));
+ new->prev = last;
+ new->type = M_T_USERDEF;
+ new->name = xnfalloc(strlen(modeNames[i]) + 1);
+ strcpy(new->name, modeNames[i]);
+ if (new->prev)
+ new->prev->next = new;
+ *endp = last = new;
+ endp = &new->next;
+ }
+ }
+
+ /* Lookup each mode */
+ validateAllDefaultModes = TRUE;
+ for (p = scrp->modes; ; p = p->next) {
+ Bool repeat;
+
+ /*
+ * If the supplied mode names don't produce a valid mode, scan through
+ * unconsidered modePool members until one survives validation. This
+ * is done in decreasing order by mode pixel area.
+ */
+
+ if (p == NULL) {
+ if ((numModes > 0) && !validateAllDefaultModes)
+ break;
+
+ validateAllDefaultModes = TRUE;
+ r = NULL;
+ modeSize = 0;
+ for (q = scrp->modePool; q != NULL; q = q->next) {
+ if ((q->prev == NULL) && (q->status == MODE_OK)) {
+ /*
+ * Deal with the case where this mode wasn't considered
+ * because of a builtin mode of the same name.
+ */
+ for (p = scrp->modes; p != NULL; p = p->next) {
+ if ((p->status != MODE_OK) &&
+ !strcmp(p->name, q->name))
+ break;
+ }
+
+ if (p != NULL)
+ q->prev = p;
+ else {
+ /*
+ * A quick check to not allow default modes with
+ * horizontal timing parameters that CRTs may have
+ * problems with.
+ */
+ if ((q->type & M_T_DEFAULT) &&
+ ((double)q->HTotal / (double)q->HDisplay) < 1.15)
+ continue;
+
+ if (modeSize < (q->HDisplay * q->VDisplay)) {
+ r = q;
+ modeSize = q->HDisplay * q->VDisplay;
+ }
+ }
+ }
+ }
+
+ if (r == NULL)
+ break;
+
+ p = xnfcalloc(1, sizeof(DisplayModeRec));
+ p->prev = last;
+ p->name = xnfalloc(strlen(r->name) + 1);
+ if (!userModes)
+ p->type = M_T_USERDEF;
+ strcpy(p->name, r->name);
+ if (p->prev)
+ p->prev->next = p;
+ *endp = last = p;
+ endp = &p->next;
+ }
+
+ repeat = FALSE;
+ lookupNext:
+ if (repeat && ((status = p->status) != MODE_OK)) {
+ if (p->type & M_T_BUILTIN)
+ xf86DrvMsg(scrp->scrnIndex, X_INFO,
+ "Not using built-in mode \"%s\" (%s)\n",
+ p->name, xf86ModeStatusToString(status));
+ else if (p->type & M_T_DEFAULT)
+ xf86DrvMsg(scrp->scrnIndex, X_INFO,
+ "Not using default mode \"%s\" (%s)\n", p->name,
+ xf86ModeStatusToString(status));
+ else
+ xf86DrvMsg(scrp->scrnIndex, X_INFO,
+ "Not using mode \"%s\" (%s)\n", p->name,
+ xf86ModeStatusToString(status));
+ }
+ saveType = p->type;
+ status = xf86LookupMode(scrp, p, clockRanges, strategy);
+ if (repeat && status == MODE_NOMODE) {
+ continue;
+ }
+ if (status != MODE_OK) {
+ if (p->type & M_T_BUILTIN)
+ xf86DrvMsg(scrp->scrnIndex, X_INFO,
+ "Not using built-in mode \"%s\" (%s)\n",
+ p->name, xf86ModeStatusToString(status));
+ else if (p->type & M_T_DEFAULT)
+ xf86DrvMsg(scrp->scrnIndex, X_INFO,
+ "Not using default mode \"%s\" (%s)\n", p->name,
+ xf86ModeStatusToString(status));
+ else
+ xf86DrvMsg(scrp->scrnIndex, X_INFO,
+ "Not using mode \"%s\" (%s)\n", p->name,
+ xf86ModeStatusToString(status));
+ }
+ if (status == MODE_ERROR) {
+ ErrorF("xf86ValidateModes: "
+ "unexpected result from xf86LookupMode()\n");
+ return -1;
+ }
+ if (status != MODE_OK) {
+ if (p->status == MODE_OK)
+ p->status = status;
+ continue;
+ }
+ p->type |= saveType;
+ repeat = TRUE;
+
+ newLinePitch = linePitch;
+ newVirtX = virtX;
+ newVirtY = virtY;
+
+ /*
+ * Don't let non-user defined modes increase the virtual size
+ */
+ if (!(p->type & M_T_USERDEF) && (numModes > 0)) {
+ if (p->HDisplay > virtX) {
+ p->status = MODE_VIRTUAL_X;
+ goto lookupNext;
+ }
+ if (p->VDisplay > virtY) {
+ p->status = MODE_VIRTUAL_Y;
+ goto lookupNext;
+ }
+ }
+ /*
+ * Adjust virtual width and height if the mode is too large for the
+ * current values and if they are not fixed.
+ */
+ if (virtualX <= 0 && p->HDisplay > newVirtX)
+ newVirtX = _VIRTUALX(p->HDisplay);
+ if (virtualY <= 0 && p->VDisplay > newVirtY) {
+ if (maxHeight > 0 && p->VDisplay > maxHeight) {
+ p->status = MODE_VIRTUAL_Y; /* ? */
+ goto lookupNext;
+ }
+ newVirtY = p->VDisplay;
+ }
+
+ /*
+ * If virtual resolution is to be increased, revalidate it.
+ */
+ if ((virtX != newVirtX) || (virtY != newVirtY)) {
+ if (linePitches != NULL) {
+ newLinePitch = -1;
+ for (i = 0; linePitches[i] != 0; i++) {
+ if ((linePitches[i] >= newVirtX) &&
+ (linePitches[i] >= linePitch) &&
+ (linePitches[i] ==
+ miScanLineWidth(newVirtX, newVirtY, linePitches[i],
+ apertureSize, BankFormat, pitchInc))) {
+ newLinePitch = linePitches[i];
+ break;
+ }
+ }
+ } else {
+ if (linePitch < minPitch)
+ linePitch = minPitch;
+ newLinePitch = miScanLineWidth(newVirtX, newVirtY, linePitch,
+ apertureSize, BankFormat,
+ pitchInc);
+ }
+ if ((newLinePitch < minPitch) || (newLinePitch > maxPitch)) {
+ p->status = MODE_BAD_WIDTH;
+ goto lookupNext;
+ }
+
+ /*
+ * Check that the pixel area required by the new virtual height
+ * and line pitch isn't too large.
+ */
+ if (!xf86CheckModeSize(scrp, newLinePitch, newVirtX, newVirtY)) {
+ p->status = MODE_MEM_VIRT;
+ goto lookupNext;
+ }
+ }
+
+ if (scrp->ValidMode) {
+ /*
+ * Give the driver a final say, passing it the proposed virtual
+ * geometry.
+ */
+ scrp->virtualX = newVirtX;
+ scrp->virtualY = newVirtY;
+ scrp->displayWidth = newLinePitch;
+ p->status = (scrp->ValidMode)(scrp->scrnIndex, p, FALSE,
+ MODECHECK_FINAL);
+
+ if (p->status != MODE_OK) {
+ goto lookupNext;
+ }
+ }
+
+ /* Mode has passed all the tests */
+ virtX = newVirtX;
+ virtY = newVirtY;
+ linePitch = newLinePitch;
+ p->status = MODE_OK;
+ numModes++;
+ }
+
+#undef _VIRTUALX
+
+ /* Update the ScrnInfoRec parameters */
+
+ scrp->virtualX = virtX;
+ scrp->virtualY = virtY;
+ scrp->displayWidth = linePitch;
+
+ if (numModes <= 0)
+ return 0;
+
+ /* Make the mode list into a circular list by joining up the ends */
+ p = scrp->modes;
+ while (p->next != NULL)
+ p = p->next;
+ /* p is now the last mode on the list */
+ p->next = scrp->modes;
+ scrp->modes->prev = p;
+
+ if (minHeight > 0 && virtY < minHeight) {
+ xf86DrvMsg(scrp->scrnIndex, X_ERROR,
+ "Virtual height (%d) is too small for the hardware "
+ "(min %d)\n", virtY, minHeight);
+ return -1;
+ }
+
+ return numModes;
+}
+
+/*
+ * xf86DeleteMode
+ *
+ * This function removes a mode from a list of modes.
+ *
+ * There are different types of mode lists:
+ *
+ * - singly linked linear lists, ending in NULL
+ * - doubly linked linear lists, starting and ending in NULL
+ * - doubly linked circular lists
+ *
+ */
+
+void
+xf86DeleteMode(DisplayModePtr *modeList, DisplayModePtr mode)
+{
+ /* Catch the easy/insane cases */
+ if (modeList == NULL || *modeList == NULL || mode == NULL)
+ return;
+
+ /* If the mode is at the start of the list, move the start of the list */
+ if (*modeList == mode)
+ *modeList = mode->next;
+
+ /* If mode is the only one on the list, set the list to NULL */
+ if ((mode == mode->prev) && (mode == mode->next)) {
+ *modeList = NULL;
+ } else {
+ if ((mode->prev != NULL) && (mode->prev->next == mode))
+ mode->prev->next = mode->next;
+ if ((mode->next != NULL) && (mode->next->prev == mode))
+ mode->next->prev = mode->prev;
+ }
+
+ xfree(mode->name);
+ xfree(mode);
+}
+
+/*
+ * xf86PruneDriverModes
+ *
+ * Remove modes from the driver's mode list which have been marked as
+ * invalid.
+ */
+
+void
+xf86PruneDriverModes(ScrnInfoPtr scrp)
+{
+ DisplayModePtr first, p, n;
+
+ p = scrp->modes;
+ if (p == NULL)
+ return;
+
+ do {
+ if (!(first = scrp->modes))
+ return;
+ n = p->next;
+ if (p->status != MODE_OK) {
+#if 0
+ if (p->type & M_T_BUILTIN)
+ xf86DrvMsg(scrp->scrnIndex, X_INFO,
+ "Not using built-in mode \"%s\" (%s)\n", p->name,
+ xf86ModeStatusToString(p->status));
+ else if (p->type & M_T_DEFAULT)
+ xf86DrvMsg(scrp->scrnIndex, X_INFO,
+ "Not using default mode \"%s\" (%s)\n", p->name,
+ xf86ModeStatusToString(p->status));
+ else
+ xf86DrvMsg(scrp->scrnIndex, X_INFO,
+ "Not using mode \"%s\" (%s)\n", p->name,
+ xf86ModeStatusToString(p->status));
+#endif
+ xf86DeleteMode(&(scrp->modes), p);
+ }
+ p = n;
+ } while (p != NULL && p != first);
+
+ /* modePool is no longer needed, turf it */
+ while (scrp->modePool)
+ xf86DeleteMode(&scrp->modePool, scrp->modePool);
+}
+
+
+/*
+ * xf86SetCrtcForModes
+ *
+ * Goes through the screen's mode list, and initialises the Crtc
+ * parameters for each mode. The initialisation includes adjustments
+ * for interlaced and double scan modes.
+ */
+void
+xf86SetCrtcForModes(ScrnInfoPtr scrp, int adjustFlags)
+{
+ DisplayModePtr p;
+
+ /*
+ * Store adjustFlags for use with the VidMode extension. There is an
+ * implicit assumption here that SetCrtcForModes is called once.
+ */
+ scrp->adjustFlags = adjustFlags;
+
+ p = scrp->modes;
+ if (p == NULL)
+ return;
+
+ do {
+ xf86SetModeCrtc(p, adjustFlags);
+#ifdef DEBUG
+ ErrorF("%sMode %s: %d (%d) %d %d (%d) %d %d (%d) %d %d (%d) %d\n",
+ (p->type & M_T_DEFAULT) ? "Default " : "",
+ p->name, p->CrtcHDisplay, p->CrtcHBlankStart,
+ p->CrtcHSyncStart, p->CrtcHSyncEnd, p->CrtcHBlankEnd,
+ p->CrtcHTotal, p->CrtcVDisplay, p->CrtcVBlankStart,
+ p->CrtcVSyncStart, p->CrtcVSyncEnd, p->CrtcVBlankEnd,
+ p->CrtcVTotal);
+#endif
+ p = p->next;
+ } while (p != NULL && p != scrp->modes);
+}
+
+
+static void
+add(char **p, char *new)
+{
+ *p = xnfrealloc(*p, strlen(*p) + strlen(new) + 2);
+ strcat(*p, " ");
+ strcat(*p, new);
+}
+
+static void
+PrintModeline(int scrnIndex,DisplayModePtr mode)
+{
+ char tmp[256];
+ char *flags = xnfcalloc(1, 1);
+
+ if (mode->HSkew) {
+ snprintf(tmp, 256, "hskew %i", mode->HSkew);
+ add(&flags, tmp);
+ }
+ if (mode->VScan) {
+ snprintf(tmp, 256, "vscan %i", mode->VScan);
+ add(&flags, tmp);
+ }
+ if (mode->Flags & V_INTERLACE) add(&flags, "interlace");
+ if (mode->Flags & V_CSYNC) add(&flags, "composite");
+ if (mode->Flags & V_DBLSCAN) add(&flags, "doublescan");
+ if (mode->Flags & V_BCAST) add(&flags, "bcast");
+ if (mode->Flags & V_PHSYNC) add(&flags, "+hsync");
+ if (mode->Flags & V_NHSYNC) add(&flags, "-hsync");
+ if (mode->Flags & V_PVSYNC) add(&flags, "+vsync");
+ if (mode->Flags & V_NVSYNC) add(&flags, "-vsync");
+ if (mode->Flags & V_PCSYNC) add(&flags, "+csync");
+ if (mode->Flags & V_NCSYNC) add(&flags, "-csync");
+#if 0
+ if (mode->Flags & V_CLKDIV2) add(&flags, "vclk/2");
+#endif
+ xf86DrvMsgVerb(scrnIndex, X_INFO, 3,
+ "Modeline \"%s\" %6.2f %i %i %i %i %i %i %i %i%s\n",
+ mode->name, mode->Clock/1000., mode->HDisplay,
+ mode->HSyncStart, mode->HSyncEnd, mode->HTotal,
+ mode->VDisplay, mode->VSyncStart, mode->VSyncEnd,
+ mode->VTotal, flags);
+ xfree(flags);
+}
+
+void
+xf86PrintModes(ScrnInfoPtr scrp)
+{
+ DisplayModePtr p;
+ float hsync, refresh = 0;
+ char *desc, *desc2, *prefix, *uprefix;
+
+ if (scrp == NULL)
+ return;
+
+ xf86DrvMsg(scrp->scrnIndex, scrp->virtualFrom, "Virtual size is %dx%d "
+ "(pitch %d)\n", scrp->virtualX, scrp->virtualY,
+ scrp->displayWidth);
+
+ p = scrp->modes;
+ if (p == NULL)
+ return;
+
+ do {
+ desc = desc2 = "";
+ if (p->HSync > 0.0)
+ hsync = p->HSync;
+ else if (p->HTotal > 0)
+ hsync = (float)p->Clock / (float)p->HTotal;
+ else
+ hsync = 0.0;
+ if (p->VTotal > 0)
+ refresh = hsync * 1000.0 / p->VTotal;
+ if (p->Flags & V_INTERLACE) {
+ refresh *= 2.0;
+ desc = " (I)";
+ }
+ if (p->Flags & V_DBLSCAN) {
+ refresh /= 2.0;
+ desc = " (D)";
+ }
+ if (p->VScan > 1) {
+ refresh /= p->VScan;
+ desc2 = " (VScan)";
+ }
+ if (p->VRefresh > 0.0)
+ refresh = p->VRefresh;
+ if (p->type & M_T_BUILTIN)
+ prefix = "Built-in mode";
+ else if (p->type & M_T_DEFAULT)
+ prefix = "Default mode";
+ else
+ prefix = "Mode";
+ if (p->type & M_T_USERDEF)
+ uprefix = "*";
+ else
+ uprefix = " ";
+ if (hsync == 0 || refresh == 0) {
+ if (p->name)
+ xf86DrvMsg(scrp->scrnIndex, X_CONFIG,
+ "%s%s \"%s\"\n", uprefix, prefix, p->name);
+ else
+ xf86DrvMsg(scrp->scrnIndex, X_PROBED,
+ "%s%s %dx%d (unnamed)\n",
+ uprefix, prefix, p->HDisplay, p->VDisplay);
+ } else if (p->Clock == p->SynthClock) {
+ xf86DrvMsg(scrp->scrnIndex, X_CONFIG,
+ "%s%s \"%s\": %.1f MHz, %.1f kHz, %.1f Hz%s%s\n",
+ uprefix, prefix, p->name, p->Clock / 1000.0,
+ hsync, refresh, desc, desc2);
+ } else {
+ xf86DrvMsg(scrp->scrnIndex, X_CONFIG,
+ "%s%s \"%s\": %.1f MHz (scaled from %.1f MHz), "
+ "%.1f kHz, %.1f Hz%s%s\n",
+ uprefix, prefix, p->name, p->Clock / 1000.0,
+ p->SynthClock / 1000.0, hsync, refresh, desc, desc2);
+ }
+ if (hsync != 0 && refresh != 0)
+ PrintModeline(scrp->scrnIndex,p);
+ p = p->next;
+ } while (p != NULL && p != scrp->modes);
+}
diff --git a/hw/xfree86/common/xf86Module.h b/hw/xfree86/common/xf86Module.h
new file mode 100644
index 000000000..21b9aa590
--- /dev/null
+++ b/hw/xfree86/common/xf86Module.h
@@ -0,0 +1,203 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86Module.h,v 1.35 2002/12/22 02:03:25 dawes Exp $ */
+
+/*
+ * Copyright (c) 1997-2001 by The XFree86 Project, Inc.
+ */
+
+/*
+ * This file contains the parts of the loader interface that are visible
+ * to modules. This is the only loader-related header that modules should
+ * include.
+ *
+ * It should include a bare minimum of other headers.
+ *
+ * Longer term, the module/loader code should probably live directly under
+ * Xserver/.
+ *
+ * XXX This file arguably belongs in xfree86/loader/.
+ */
+
+#ifndef _XF86MODULE_H
+#define _XF86MODULE_H
+
+#include "misc.h"
+#include "xf86Version.h"
+#ifndef NULL
+#define NULL ((void *)0)
+#endif
+
+typedef enum {
+ LD_RESOLV_IFDONE = 0, /* only check if no more
+ delays pending */
+ LD_RESOLV_NOW = 1, /* finish one delay step */
+ LD_RESOLV_FORCE = 2 /* force checking... */
+} LoaderResolveOptions;
+
+#define DEFAULT_LIST ((char *)-1)
+
+/* This indicates a special module that doesn't have the usual entry point */
+#define EXTERN_MODULE ((pointer)-1)
+
+/* Built-in ABI classes. These definitions must not be changed. */
+#define ABI_CLASS_NONE NULL
+#define ABI_CLASS_ANSIC "XFree86 ANSI C Emulation"
+#define ABI_CLASS_VIDEODRV "XFree86 Video Driver"
+#define ABI_CLASS_XINPUT "XFree86 XInput driver"
+#define ABI_CLASS_EXTENSION "XFree86 Server Extension"
+#define ABI_CLASS_FONT "XFree86 Font Renderer"
+
+#define ABI_MINOR_MASK 0x0000FFFF
+#define ABI_MAJOR_MASK 0xFFFF0000
+#define GET_ABI_MINOR(v) ((v) & ABI_MINOR_MASK)
+#define GET_ABI_MAJOR(v) (((v) & ABI_MAJOR_MASK) >> 16)
+#define SET_ABI_VERSION(maj, min) \
+ ((((maj) << 16) & ABI_MAJOR_MASK) | ((min) & ABI_MINOR_MASK))
+
+/*
+ * ABI versions. Each version has a major and minor revision. Modules
+ * using lower minor revisions must work with servers of a higher minor
+ * revision. There is no compatibility between different major revisions.
+ * Whenever the ABI_ANSIC_VERSION is changed, the others must also be
+ * changed. The minor revision mask is 0x0000FFFF and the major revision
+ * mask is 0xFFFF0000.
+ */
+#define ABI_ANSIC_VERSION SET_ABI_VERSION(0, 2)
+#define ABI_VIDEODRV_VERSION SET_ABI_VERSION(0, 6)
+#define ABI_XINPUT_VERSION SET_ABI_VERSION(0, 4)
+#define ABI_EXTENSION_VERSION SET_ABI_VERSION(0, 2)
+#define ABI_FONT_VERSION SET_ABI_VERSION(0, 4)
+
+#define MODINFOSTRING1 0xef23fdc5
+#define MODINFOSTRING2 0x10dc023a
+
+#ifndef MODULEVENDORSTRING
+#ifndef __OS2ELF__
+#define MODULEVENDORSTRING "The XFree86 Project"
+#else
+#define MODULEVENDORSTRING "The XFree86 Project - XFree86/OS2"
+#endif
+#endif
+
+/* Error return codes for errmaj. New codes must only be added at the end. */
+typedef enum {
+ LDR_NOERROR = 0,
+ LDR_NOMEM, /* memory allocation failed */
+ LDR_NOENT, /* Module file does not exist */
+ LDR_NOSUBENT, /* pre-requsite file to be sub-loaded does not exist */
+ LDR_NOSPACE, /* internal module array full */
+ LDR_NOMODOPEN, /* module file could not be opened (check errmin) */
+ LDR_UNKTYPE, /* file is not a recognized module type */
+ LDR_NOLOAD, /* type specific loader failed */
+ LDR_ONCEONLY, /* Module should only be loaded once (not an error) */
+ LDR_NOPORTOPEN, /* could not open port (check errmin) */
+ LDR_NOHARDWARE, /* could not query/initialize the hardware device */
+ LDR_MISMATCH, /* the module didn't match the spec'd requirments */
+ LDR_BADUSAGE, /* LoadModule is called with bad arguments */
+ LDR_INVALID, /* The module doesn't have a valid ModuleData object */
+ LDR_BADOS, /* The module doesn't support the OS */
+ LDR_MODSPECIFIC /* A module-specific error in the SetupProc */
+} LoaderErrorCode;
+
+/*
+ * Some common module classes. The moduleclass can be used to identify
+ * that modules loaded are of the correct type. This is a finer
+ * classification than the ABI classes even though the default set of
+ * classes have the same names. For example, not all modules that require
+ * the video driver ABI are themselves video drivers.
+ */
+#define MOD_CLASS_NONE NULL
+#define MOD_CLASS_VIDEODRV "XFree86 Video Driver"
+#define MOD_CLASS_XINPUT "XFree86 XInput Driver"
+#define MOD_CLASS_FONT "XFree86 Font Renderer"
+#define MOD_CLASS_EXTENSION "XFree86 Server Extension"
+
+/* This structure is expected to be returned by the initfunc */
+typedef struct {
+ const char * modname; /* name of module, e.g. "foo" */
+ const char * vendor; /* vendor specific string */
+ CARD32 _modinfo1_; /* constant MODINFOSTRING1/2 to find */
+ CARD32 _modinfo2_; /* infoarea with a binary editor or sign tool */
+ CARD32 xf86version; /* contains XF86_VERSION_CURRENT */
+ CARD8 majorversion; /* module-specific major version */
+ CARD8 minorversion; /* module-specific minor version */
+ CARD16 patchlevel; /* module-specific patch level */
+ const char * abiclass; /* ABI class that the module uses */
+ CARD32 abiversion; /* ABI version */
+ const char * moduleclass; /* module class description */
+ CARD32 checksum[4]; /* contains a digital signature of the */
+ /* version info structure */
+} XF86ModuleVersionInfo;
+
+/*
+ * This structure can be used to callers of LoadModule and LoadSubModule to
+ * specify version and/or ABI requirements.
+ */
+typedef struct {
+ CARD8 majorversion; /* module-specific major version */
+ CARD8 minorversion; /* moudle-specific minor version */
+ CARD16 patchlevel; /* module-specific patch level */
+ const char * abiclass; /* ABI class that the module uses */
+ CARD32 abiversion; /* ABI version */
+ const char * moduleclass; /* module class */
+} XF86ModReqInfo;
+
+/* values to indicate unspecified fields in XF86ModReqInfo. */
+#define MAJOR_UNSPEC 0xFF
+#define MINOR_UNSPEC 0xFF
+#define PATCH_UNSPEC 0xFFFF
+#define ABI_VERS_UNSPEC 0xFFFFFFFF
+
+#define MODULE_VERSION_NUMERIC(maj, min, patch) \
+ ((((maj) & 0xFF) << 24) | (((min) & 0xFF) << 16) | (patch & 0xFFFF))
+#define GET_MODULE_MAJOR_VERSION(vers) (((vers) >> 24) & 0xFF)
+#define GET_MODULE_MINOR_VERSION(vers) (((vers) >> 16) & 0xFF)
+#define GET_MODULE_PATCHLEVEL(vers) ((vers) & 0xFFFF)
+
+#define INITARGS void
+
+typedef void (*InitExtension)(INITARGS);
+
+typedef struct {
+ InitExtension initFunc;
+ const char * name;
+ Bool *disablePtr;
+ InitExtension setupFunc;
+ const char ** initDependencies;
+} ExtensionModule;
+
+extern ExtensionModule *ExtensionModuleList;
+
+/* Prototypes for Loader functions that are exported to modules */
+#ifndef IN_LOADER
+/* Prototypes with opaque pointers for use by modules */
+pointer LoadSubModule(pointer, const char *, const char **,
+ const char **, pointer, const XF86ModReqInfo *,
+ int *, int *);
+void UnloadSubModule(pointer);
+void LoadFont(pointer);
+void UnloadModule (pointer);
+#endif
+pointer LoaderSymbol(const char *);
+char **LoaderListDirs(const char **, const char **);
+void LoaderFreeDirList(char **);
+void LoaderErrorMsg(const char *, const char *, int, int);
+void LoadExtension(ExtensionModule *, Bool);
+void LoaderRefSymLists(const char **, ...);
+void LoaderRefSymbols(const char *, ...);
+void LoaderReqSymLists(const char **, ...);
+void LoaderReqSymbols(const char *, ...);
+int LoaderCheckUnresolved(int);
+void LoaderGetOS(const char **name, int *major, int *minor, int *teeny);
+
+typedef pointer (*ModuleSetupProc)(pointer, pointer, int *, int *);
+typedef void (*ModuleTearDownProc)(pointer);
+#define MODULESETUPPROTO(func) pointer func(pointer, pointer, int*, int*)
+#define MODULETEARDOWNPROTO(func) void func(pointer)
+
+typedef struct {
+ XF86ModuleVersionInfo * vers;
+ ModuleSetupProc setup;
+ ModuleTearDownProc teardown;
+} XF86ModuleData;
+
+#endif /* _XF86STR_H */
diff --git a/hw/xfree86/common/xf86Opt.h b/hw/xfree86/common/xf86Opt.h
new file mode 100644
index 000000000..dc5c2ca67
--- /dev/null
+++ b/hw/xfree86/common/xf86Opt.h
@@ -0,0 +1,82 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86Opt.h,v 1.12 2001/05/04 19:05:30 dawes Exp $ */
+
+/* Option handling things that ModuleSetup procs can use */
+
+#ifndef _XF86_OPT_H_
+#define _XF86_OPT_H_
+
+typedef struct {
+ double freq;
+ int units;
+} OptFrequency;
+
+typedef union {
+ unsigned long num;
+ char * str;
+ double realnum;
+ Bool bool;
+ OptFrequency freq;
+} ValueUnion;
+
+typedef enum {
+ OPTV_NONE = 0,
+ OPTV_INTEGER,
+ OPTV_STRING, /* a non-empty string */
+ OPTV_ANYSTR, /* Any string, including an empty one */
+ OPTV_REAL,
+ OPTV_BOOLEAN,
+ OPTV_FREQ
+} OptionValueType;
+
+typedef enum {
+ OPTUNITS_HZ = 1,
+ OPTUNITS_KHZ,
+ OPTUNITS_MHZ
+} OptFreqUnits;
+
+typedef struct {
+ int token;
+ const char* name;
+ OptionValueType type;
+ ValueUnion value;
+ Bool found;
+} OptionInfoRec, *OptionInfoPtr;
+
+int xf86SetIntOption(pointer optlist, const char *name, int deflt);
+double xf86SetRealOption(pointer optlist, const char *name, double deflt);
+char *xf86SetStrOption(pointer optlist, const char *name, char *deflt);
+int xf86SetBoolOption(pointer list, const char *name, int deflt );
+pointer xf86AddNewOption(pointer head, char *name, char *val );
+pointer xf86NewOption(char *name, char *value );
+pointer xf86NextOption(pointer list );
+pointer xf86OptionListCreate(const char **options, int count, int used);
+pointer xf86OptionListMerge(pointer head, pointer tail);
+void xf86OptionListFree(pointer opt);
+char *xf86OptionName(pointer opt);
+char *xf86OptionValue(pointer opt);
+void xf86OptionListReport(pointer parm);
+pointer xf86FindOption(pointer options, const char *name);
+char *xf86FindOptionValue(pointer options, const char *name);
+void xf86MarkOptionUsed(pointer option);
+void xf86MarkOptionUsedByName(pointer options, const char *name);
+Bool xf86CheckIfOptionUsed(pointer option);
+Bool xf86CheckIfOptionUsedByName(pointer options, const char *name);
+void xf86ShowUnusedOptions(int scrnIndex, pointer options);
+void xf86ProcessOptions(int scrnIndex, pointer options, OptionInfoPtr optinfo);
+OptionInfoPtr xf86TokenToOptinfo(const OptionInfoRec *table, int token);
+const char *xf86TokenToOptName(const OptionInfoRec *table, int token);
+Bool xf86IsOptionSet(const OptionInfoRec *table, int token);
+char *xf86GetOptValString(const OptionInfoRec *table, int token);
+Bool xf86GetOptValInteger(const OptionInfoRec *table, int token, int *value);
+Bool xf86GetOptValULong(const OptionInfoRec *table, int token, unsigned long *value);
+Bool xf86GetOptValReal(const OptionInfoRec *table, int token, double *value);
+Bool xf86GetOptValFreq(const OptionInfoRec *table, int token,
+ OptFreqUnits expectedUnits, double *value);
+Bool xf86GetOptValBool(const OptionInfoRec *table, int token, Bool *value);
+Bool xf86ReturnOptValBool(const OptionInfoRec *table, int token, Bool def);
+int xf86NameCmp(const char *s1, const char *s2);
+char *xf86NormalizeName(const char *s);
+pointer xf86ReplaceIntOption(pointer optlist, char *name, int val);
+pointer xf86ReplaceBoolOption(pointer optlist, char *name, Bool val);
+pointer xf86ReplaceStrOption(pointer optlist, char *name, char* val);
+#endif
diff --git a/hw/xfree86/common/xf86Option.c b/hw/xfree86/common/xf86Option.c
new file mode 100644
index 000000000..6ca1590e4
--- /dev/null
+++ b/hw/xfree86/common/xf86Option.c
@@ -0,0 +1,777 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86Option.c,v 1.25 2002/09/10 17:39:28 dawes Exp $ */
+
+/*
+ * Copyright (c) 1998 by The XFree86 Project, Inc.
+ *
+ * Author: David Dawes <dawes@xfree86.org>
+ *
+ *
+ * This file includes public option handling functions.
+ */
+
+#include <stdlib.h>
+#include <ctype.h>
+#include "X.h"
+#include "os.h"
+#include "xf86.h"
+#include "xf86Xinput.h"
+#include "xf86Optrec.h"
+
+static Bool ParseOptionValue(int scrnIndex, pointer options, OptionInfoPtr p);
+
+/*
+ * xf86CollectOptions collects the options from each of the config file
+ * sections used by the screen and puts the combined list in pScrn->options.
+ * This function requires that the following have been initialised:
+ *
+ * pScrn->confScreen
+ * pScrn->Entities[i]->device
+ * pScrn->display
+ * pScrn->monitor
+ *
+ * The extraOpts parameter may optionally contain a list of additional options
+ * to include.
+ *
+ * The order of precedence for options is:
+ *
+ * extraOpts, display, confScreen, monitor, device
+ */
+
+void
+xf86CollectOptions(ScrnInfoPtr pScrn, pointer extraOpts)
+{
+ XF86OptionPtr tmp;
+ XF86OptionPtr extras = (XF86OptionPtr)extraOpts;
+ GDevPtr device;
+
+ int i;
+
+ pScrn->options = NULL;
+
+ for (i=pScrn->numEntities - 1; i >= 0; i--) {
+ device = xf86GetDevFromEntity(pScrn->entityList[i],
+ pScrn->entityInstanceList[i]);
+ if (device && device->options) {
+ tmp = xf86optionListDup(device->options);
+ if (pScrn->options)
+ xf86optionListMerge(pScrn->options,tmp);
+ else
+ pScrn->options = tmp;
+ }
+ }
+ if (pScrn->monitor->options) {
+ tmp = xf86optionListDup(pScrn->monitor->options);
+ if (pScrn->options)
+ pScrn->options = xf86optionListMerge(pScrn->options, tmp);
+ else
+ pScrn->options = tmp;
+ }
+ if (pScrn->confScreen->options) {
+ tmp = xf86optionListDup(pScrn->confScreen->options);
+ if (pScrn->options)
+ pScrn->options = xf86optionListMerge(pScrn->options, tmp);
+ else
+ pScrn->options = tmp;
+ }
+ if (pScrn->display->options) {
+ tmp = xf86optionListDup(pScrn->display->options);
+ if (pScrn->options)
+ pScrn->options = xf86optionListMerge(pScrn->options, tmp);
+ else
+ pScrn->options = tmp;
+ }
+ if (extras) {
+ tmp = xf86optionListDup(extras);
+ if (pScrn->options)
+ pScrn->options = xf86optionListMerge(pScrn->options, tmp);
+ else
+ pScrn->options = tmp;
+ }
+}
+
+/*
+ * xf86CollectInputOptions collects the options for an InputDevice.
+ * This function requires that the following has been initialised:
+ *
+ * pInfo->conf_idev
+ *
+ * The extraOpts parameter may optionally contain a list of additional options
+ * to include.
+ *
+ * The order of precedence for options is:
+ *
+ * extraOpts, pInfo->conf_idev->extraOptions,
+ * pInfo->conf_idev->commonOptions, defaultOpts
+ */
+
+void
+xf86CollectInputOptions(InputInfoPtr pInfo, const char **defaultOpts,
+ pointer extraOpts)
+{
+ XF86OptionPtr tmp;
+ XF86OptionPtr extras = (XF86OptionPtr)extraOpts;
+
+ pInfo->options = NULL;
+ if (defaultOpts) {
+ pInfo->options = xf86OptionListCreate(defaultOpts, -1, 0);
+ }
+ if (pInfo->conf_idev->commonOptions) {
+ tmp = xf86optionListDup(pInfo->conf_idev->commonOptions);
+ if (pInfo->options)
+ pInfo->options = xf86optionListMerge(pInfo->options, tmp);
+ else
+ pInfo->options = tmp;
+ }
+ if (pInfo->conf_idev->extraOptions) {
+ tmp = xf86optionListDup(pInfo->conf_idev->extraOptions);
+ if (pInfo->options)
+ pInfo->options = xf86optionListMerge(pInfo->options, tmp);
+ else
+ pInfo->options = tmp;
+ }
+ if (extras) {
+ tmp = xf86optionListDup(extras);
+ if (pInfo->options)
+ pInfo->options = xf86optionListMerge(pInfo->options, tmp);
+ else
+ pInfo->options = tmp;
+ }
+}
+
+/* Created for new XInput stuff -- essentially extensions to the parser */
+
+/* These xf86Set* functions are intended for use by non-screen specific code */
+
+int
+xf86SetIntOption(pointer optlist, const char *name, int deflt)
+{
+ OptionInfoRec o;
+
+ o.name = name;
+ o.type = OPTV_INTEGER;
+ if (ParseOptionValue(-1, optlist, &o))
+ deflt = o.value.num;
+ return deflt;
+}
+
+
+double
+xf86SetRealOption(pointer optlist, const char *name, double deflt)
+{
+ OptionInfoRec o;
+
+ o.name = name;
+ o.type = OPTV_REAL;
+ if (ParseOptionValue(-1, optlist, &o))
+ deflt = o.value.realnum;
+ return deflt;
+}
+
+
+char *
+xf86SetStrOption(pointer optlist, const char *name, char *deflt)
+{
+ OptionInfoRec o;
+
+ o.name = name;
+ o.type = OPTV_STRING;
+ if (ParseOptionValue(-1, optlist, &o))
+ deflt = o.value.str;
+ if (deflt)
+ return xstrdup(deflt);
+ else
+ return NULL;
+}
+
+
+int
+xf86SetBoolOption(pointer optlist, const char *name, int deflt)
+{
+ OptionInfoRec o;
+
+ o.name = name;
+ o.type = OPTV_BOOLEAN;
+ if (ParseOptionValue(-1, optlist, &o))
+ deflt = o.value.bool;
+ return deflt;
+}
+
+/*
+ * addNewOption() has the required property of replacing the option value
+ * it the option is alread present.
+ */
+pointer
+xf86ReplaceIntOption(pointer optlist, char *name, int val)
+{
+ char *tmp = xnfalloc(16);
+ sprintf(tmp,"%i",val);
+ return xf86AddNewOption(optlist,name,tmp);
+}
+
+pointer
+xf86ReplaceBoolOption(pointer optlist, char *name, Bool val)
+{
+ return xf86AddNewOption(optlist,name,(Bool)val?"True":"False");
+}
+
+pointer
+xf86ReplaceStrOption(pointer optlist, char *name, char* val)
+{
+ return xf86AddNewOption(optlist,name,val);
+}
+
+pointer
+xf86AddNewOption(pointer head, char *name, char *val)
+{
+ char *tmp = strdup(val);
+ char *tmp_name = strdup(name);
+
+ return xf86addNewOption(head, tmp_name, tmp);
+}
+
+
+pointer
+xf86NewOption(char *name, char *value)
+{
+ return xf86newOption(name, value);
+}
+
+
+pointer
+xf86NextOption(pointer list)
+{
+ return xf86nextOption(list);
+}
+
+pointer
+xf86OptionListCreate(const char **options, int count, int used)
+{
+ return xf86optionListCreate(options, count, used);
+}
+
+pointer
+xf86OptionListMerge(pointer head, pointer tail)
+{
+ return xf86optionListMerge(head, tail);
+}
+
+void
+xf86OptionListFree(pointer opt)
+{
+ xf86optionListFree(opt);
+}
+
+char *
+xf86OptionName(pointer opt)
+{
+ return xf86optionName(opt);
+}
+
+char *
+xf86OptionValue(pointer opt)
+{
+ return xf86optionValue(opt);
+}
+
+void
+xf86OptionListReport(pointer parm)
+{
+ XF86OptionPtr opts = parm;
+
+ while(opts) {
+ if (xf86optionValue(opts))
+ xf86ErrorFVerb(5, "\tOption \"%s\" \"%s\"\n",
+ xf86optionName(opts), xf86optionValue(opts));
+ else
+ xf86ErrorFVerb( 5, "\tOption \"%s\"\n", xf86optionName(opts));
+ opts = xf86nextOption(opts);
+ }
+}
+
+/* End of XInput-caused section */
+
+pointer
+xf86FindOption(pointer options, const char *name)
+{
+ return xf86findOption(options, name);
+}
+
+
+char *
+xf86FindOptionValue(pointer options, const char *name)
+{
+ return xf86findOptionValue(options, name);
+}
+
+
+void
+xf86MarkOptionUsed(pointer option)
+{
+ if (option != NULL)
+ ((XF86OptionPtr)option)->opt_used = TRUE;
+}
+
+
+void
+xf86MarkOptionUsedByName(pointer options, const char *name)
+{
+ XF86OptionPtr opt;
+
+ opt = xf86findOption(options, name);
+ if (opt != NULL)
+ opt->opt_used = TRUE;
+}
+
+Bool
+xf86CheckIfOptionUsed(pointer option)
+{
+ if (option != NULL)
+ return ((XF86OptionPtr)option)->opt_used;
+ else
+ return FALSE;
+}
+
+Bool
+xf86CheckIfOptionUsedByName(pointer options, const char *name)
+{
+ XF86OptionPtr opt;
+
+ opt = xf86findOption(options, name);
+ if (opt != NULL)
+ return opt->opt_used;
+ else
+ return FALSE;
+}
+
+void
+xf86ShowUnusedOptions(int scrnIndex, pointer options)
+{
+ XF86OptionPtr opt = options;
+
+ while (opt) {
+ if (opt->opt_name && !opt->opt_used) {
+ xf86DrvMsg(scrnIndex, X_WARNING, "Option \"%s\" is not used\n",
+ opt->opt_name);
+ }
+ opt = opt->list.next;
+ }
+}
+
+
+static Bool
+GetBoolValue(OptionInfoPtr p, const char *s)
+{
+ if (*s == '\0') {
+ p->value.bool = TRUE;
+ } else {
+ if (xf86NameCmp(s, "1") == 0)
+ p->value.bool = TRUE;
+ else if (xf86NameCmp(s, "on") == 0)
+ p->value.bool = TRUE;
+ else if (xf86NameCmp(s, "true") == 0)
+ p->value.bool = TRUE;
+ else if (xf86NameCmp(s, "yes") == 0)
+ p->value.bool = TRUE;
+ else if (xf86NameCmp(s, "0") == 0)
+ p->value.bool = FALSE;
+ else if (xf86NameCmp(s, "off") == 0)
+ p->value.bool = FALSE;
+ else if (xf86NameCmp(s, "false") == 0)
+ p->value.bool = FALSE;
+ else if (xf86NameCmp(s, "no") == 0)
+ p->value.bool = FALSE;
+ else
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static Bool
+ParseOptionValue(int scrnIndex, pointer options, OptionInfoPtr p)
+{
+ char *s, *end;
+ Bool wasUsed;
+
+ if ((s = xf86findOptionValue(options, p->name)) != NULL) {
+ wasUsed = xf86CheckIfOptionUsedByName(options, p->name);
+ xf86MarkOptionUsedByName(options, p->name);
+ switch (p->type) {
+ case OPTV_INTEGER:
+ if (*s == '\0') {
+ xf86DrvMsg(scrnIndex, X_WARNING,
+ "Option \"%s\" requires an integer value\n",
+ p->name);
+ p->found = FALSE;
+ } else {
+ p->value.num = strtoul(s, &end, 0);
+ if (*end == '\0') {
+ p->found = TRUE;
+ } else {
+ xf86DrvMsg(scrnIndex, X_WARNING,
+ "Option \"%s\" requires an integer value\n",
+ p->name);
+ p->found = FALSE;
+ }
+ }
+ break;
+ case OPTV_STRING:
+ if (*s == '\0') {
+ xf86DrvMsg(scrnIndex, X_WARNING,
+ "Option \"%s\" requires an string value\n",
+ p->name);
+ p->found = FALSE;
+ } else {
+ p->value.str = s;
+ p->found = TRUE;
+ }
+ break;
+ case OPTV_ANYSTR:
+ p->value.str = s;
+ p->found = TRUE;
+ break;
+ case OPTV_REAL:
+ if (*s == '\0') {
+ xf86DrvMsg(scrnIndex, X_WARNING,
+ "Option \"%s\" requires a floating point value\n",
+ p->name);
+ p->found = FALSE;
+ } else {
+ p->value.realnum = strtod(s, &end);
+ if (*end == '\0') {
+ p->found = TRUE;
+ } else {
+ xf86DrvMsg(scrnIndex, X_WARNING,
+ "Option \"%s\" requires a floating point value\n",
+ p->name);
+ p->found = FALSE;
+ }
+ }
+ break;
+ case OPTV_BOOLEAN:
+ if (GetBoolValue(p, s)) {
+ p->found = TRUE;
+ } else {
+ xf86DrvMsg(scrnIndex, X_WARNING,
+ "Option \"%s\" requires a boolean value\n", p->name);
+ p->found = FALSE;
+ }
+ break;
+ case OPTV_FREQ:
+ if (*s == '\0') {
+ xf86DrvMsg(scrnIndex, X_WARNING,
+ "Option \"%s\" requires a frequency value\n",
+ p->name);
+ p->found = FALSE;
+ } else {
+ double freq = strtod(s, &end);
+ int units = 0;
+
+ if (end != s) {
+ p->found = TRUE;
+ if (!xf86NameCmp(end, "Hz"))
+ units = 1;
+ else if (!xf86NameCmp(end, "kHz") ||
+ !xf86NameCmp(end, "k"))
+ units = 1000;
+ else if (!xf86NameCmp(end, "MHz") ||
+ !xf86NameCmp(end, "M"))
+ units = 1000000;
+ else {
+ xf86DrvMsg(scrnIndex, X_WARNING,
+ "Option \"%s\" requires a frequency value\n",
+ p->name);
+ p->found = FALSE;
+ }
+ if (p->found)
+ freq *= (double)units;
+ } else {
+ xf86DrvMsg(scrnIndex, X_WARNING,
+ "Option \"%s\" requires a frequency value\n",
+ p->name);
+ p->found = FALSE;
+ }
+ if (p->found) {
+ p->value.freq.freq = freq;
+ p->value.freq.units = units;
+ }
+ }
+ break;
+ case OPTV_NONE:
+ /* Should never get here */
+ p->found = FALSE;
+ break;
+ }
+ if (p->found) {
+ int verb = 2;
+ if (wasUsed)
+ verb = 4;
+ xf86DrvMsgVerb(scrnIndex, X_CONFIG, verb, "Option \"%s\"", p->name);
+ if (!(p->type == OPTV_BOOLEAN && *s == 0)) {
+ xf86ErrorFVerb(verb, " \"%s\"", s);
+ }
+ xf86ErrorFVerb(verb, "\n");
+ }
+ } else if (p->type == OPTV_BOOLEAN) {
+ /* Look for matches with options with or without a "No" prefix. */
+ char *n, *newn;
+ OptionInfoRec opt;
+
+ n = xf86NormalizeName(p->name);
+ if (!n) {
+ p->found = FALSE;
+ return FALSE;
+ }
+ if (strncmp(n, "no", 2) == 0) {
+ newn = n + 2;
+ } else {
+ xfree(n);
+ n = xalloc(strlen(p->name) + 2 + 1);
+ if (!n) {
+ p->found = FALSE;
+ return FALSE;
+ }
+ strcpy(n, "No");
+ strcat(n, p->name);
+ newn = n;
+ }
+ if ((s = xf86findOptionValue(options, newn)) != NULL) {
+ xf86MarkOptionUsedByName(options, newn);
+ if (GetBoolValue(&opt, s)) {
+ p->value.bool = !opt.value.bool;
+ p->found = TRUE;
+ } else {
+ xf86DrvMsg(scrnIndex, X_WARNING,
+ "Option \"%s\" requires a boolean value\n", newn);
+ p->found = FALSE;
+ }
+ } else {
+ p->found = FALSE;
+ }
+ if (p->found) {
+ xf86DrvMsgVerb(scrnIndex, X_CONFIG, 2, "Option \"%s\"", newn);
+ if (*s != 0) {
+ xf86ErrorFVerb(2, " \"%s\"", s);
+ }
+ xf86ErrorFVerb(2, "\n");
+ }
+ xfree(n);
+ } else {
+ p->found = FALSE;
+ }
+ return p->found;
+}
+
+
+void
+xf86ProcessOptions(int scrnIndex, pointer options, OptionInfoPtr optinfo)
+{
+ OptionInfoPtr p;
+
+ for (p = optinfo; p->name != NULL; p++) {
+ ParseOptionValue(scrnIndex, options, p);
+ }
+}
+
+
+OptionInfoPtr
+xf86TokenToOptinfo(const OptionInfoRec *table, int token)
+{
+ const OptionInfoRec *p;
+
+ if (!table) {
+ ErrorF("xf86TokenToOptinfo: table is NULL\n");
+ return NULL;
+ }
+
+ for (p = table; p->token >= 0 && p->token != token; p++)
+ ;
+
+ if (p->token < 0)
+ return NULL;
+ else
+ return (OptionInfoPtr)p;
+}
+
+
+const char *
+xf86TokenToOptName(const OptionInfoRec *table, int token)
+{
+ const OptionInfoRec *p;
+
+ p = xf86TokenToOptinfo(table, token);
+ return p->name;
+}
+
+
+Bool
+xf86IsOptionSet(const OptionInfoRec *table, int token)
+{
+ OptionInfoPtr p;
+
+ p = xf86TokenToOptinfo(table, token);
+ return (p && p->found);
+}
+
+
+char *
+xf86GetOptValString(const OptionInfoRec *table, int token)
+{
+ OptionInfoPtr p;
+
+ p = xf86TokenToOptinfo(table, token);
+ if (p && p->found)
+ return p->value.str;
+ else
+ return NULL;
+}
+
+
+Bool
+xf86GetOptValInteger(const OptionInfoRec *table, int token, int *value)
+{
+ OptionInfoPtr p;
+
+ p = xf86TokenToOptinfo(table, token);
+ if (p && p->found) {
+ *value = p->value.num;
+ return TRUE;
+ } else
+ return FALSE;
+}
+
+
+Bool
+xf86GetOptValULong(const OptionInfoRec *table, int token, unsigned long *value)
+{
+ OptionInfoPtr p;
+
+ p = xf86TokenToOptinfo(table, token);
+ if (p && p->found) {
+ *value = p->value.num;
+ return TRUE;
+ } else
+ return FALSE;
+}
+
+
+Bool
+xf86GetOptValReal(const OptionInfoRec *table, int token, double *value)
+{
+ OptionInfoPtr p;
+
+ p = xf86TokenToOptinfo(table, token);
+ if (p && p->found) {
+ *value = p->value.realnum;
+ return TRUE;
+ } else
+ return FALSE;
+}
+
+
+Bool
+xf86GetOptValFreq(const OptionInfoRec *table, int token,
+ OptFreqUnits expectedUnits, double *value)
+{
+ OptionInfoPtr p;
+
+ p = xf86TokenToOptinfo(table, token);
+ if (p && p->found) {
+ if (p->value.freq.units > 0) {
+ /* Units give, so the scaling is known. */
+ switch (expectedUnits) {
+ case OPTUNITS_HZ:
+ *value = p->value.freq.freq;
+ break;
+ case OPTUNITS_KHZ:
+ *value = p->value.freq.freq / 1000.0;
+ break;
+ case OPTUNITS_MHZ:
+ *value = p->value.freq.freq / 1000000.0;
+ break;
+ }
+ } else {
+ /* No units given, so try to guess the scaling. */
+ switch (expectedUnits) {
+ case OPTUNITS_HZ:
+ *value = p->value.freq.freq;
+ break;
+ case OPTUNITS_KHZ:
+ if (p->value.freq.freq > 1000.0)
+ *value = p->value.freq.freq / 1000.0;
+ else
+ *value = p->value.freq.freq;
+ break;
+ case OPTUNITS_MHZ:
+ if (p->value.freq.freq > 1000000.0)
+ *value = p->value.freq.freq / 1000000.0;
+ else if (p->value.freq.freq > 1000.0)
+ *value = p->value.freq.freq / 1000.0;
+ else
+ *value = p->value.freq.freq;
+ }
+ }
+ return TRUE;
+ } else
+ return FALSE;
+}
+
+
+Bool
+xf86GetOptValBool(const OptionInfoRec *table, int token, Bool *value)
+{
+ OptionInfoPtr p;
+
+ p = xf86TokenToOptinfo(table, token);
+ if (p && p->found) {
+ *value = p->value.bool;
+ return TRUE;
+ } else
+ return FALSE;
+}
+
+
+Bool
+xf86ReturnOptValBool(const OptionInfoRec *table, int token, Bool def)
+{
+ OptionInfoPtr p;
+
+ p = xf86TokenToOptinfo(table, token);
+ if (p && p->found) {
+ return p->value.bool;
+ } else
+ return def;
+}
+
+
+int
+xf86NameCmp(const char *s1, const char *s2)
+{
+ return xf86nameCompare(s1, s2);
+}
+
+char *
+xf86NormalizeName(const char *s)
+{
+ char *ret, *q;
+ const char *p;
+
+ if (s == NULL)
+ return NULL;
+
+ ret = xalloc(strlen(s) + 1);
+ for (p = s, q = ret; *p != 0; p++) {
+ switch (*p) {
+ case '_':
+ case ' ':
+ case '\t':
+ continue;
+ default:
+ if (isupper(*p))
+ *q++ = tolower(*p);
+ else
+ *q++ = *p;
+ }
+ }
+ *q = '\0';
+ return ret;
+}
diff --git a/hw/xfree86/common/xf86PM.c b/hw/xfree86/common/xf86PM.c
new file mode 100644
index 000000000..03f5bdec1
--- /dev/null
+++ b/hw/xfree86/common/xf86PM.c
@@ -0,0 +1,188 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86PM.c,v 3.8 2002/09/29 23:54:34 keithp Exp $ */
+
+
+#include "X.h"
+#include "xf86.h"
+#include "xf86Priv.h"
+#include "xf86Xinput.h"
+
+int (*xf86PMGetEventFromOs)(int fd,pmEvent *events,int num) = NULL;
+pmWait (*xf86PMConfirmEventToOs)(int fd,pmEvent event) = NULL;
+
+static Bool suspended = FALSE;
+
+static char *
+eventName(pmEvent event)
+{
+ switch(event) {
+ case XF86_APM_SYS_STANDBY: return ("System Standby Request");
+ case XF86_APM_SYS_SUSPEND: return ("System Suspend Request");
+ case XF86_APM_CRITICAL_SUSPEND: return ("Critical Suspend");
+ case XF86_APM_USER_STANDBY: return ("User System Standby Request");
+ case XF86_APM_USER_SUSPEND: return ("User System Suspend Request");
+ case XF86_APM_STANDBY_RESUME: return ("System Standby Resume");
+ case XF86_APM_NORMAL_RESUME: return ("Normal Resume System");
+ case XF86_APM_CRITICAL_RESUME: return ("Critical Resume System");
+ case XF86_APM_LOW_BATTERY: return ("Battery Low");
+ case XF86_APM_POWER_STATUS_CHANGE: return ("Power Status Change");
+ case XF86_APM_UPDATE_TIME: return ("Update Time");
+ case XF86_APM_CAPABILITY_CHANGED: return ("Capability Changed");
+ case XF86_APM_STANDBY_FAILED: return ("Standby Request Failed");
+ case XF86_APM_SUSPEND_FAILED: return ("Suspend Request Failed");
+ default: return ("Unknown Event");
+ }
+}
+
+static void
+suspend (pmEvent event, Bool undo)
+{
+ int i;
+ InputInfoPtr pInfo;
+
+ xf86inSuspend = TRUE;
+
+ for (i = 0; i < xf86NumScreens; i++) {
+ xf86EnableAccess(xf86Screens[i]);
+ if (xf86Screens[i]->EnableDisableFBAccess)
+ (*xf86Screens[i]->EnableDisableFBAccess) (i, FALSE);
+ }
+#if !defined(__EMX__)
+ pInfo = xf86InputDevs;
+ while (pInfo) {
+ DisableDevice(pInfo->dev);
+ pInfo = pInfo->next;
+ }
+#endif
+ xf86EnterServerState(SETUP);
+ for (i = 0; i < xf86NumScreens; i++) {
+ xf86EnableAccess(xf86Screens[i]);
+ if (xf86Screens[i]->PMEvent)
+ xf86Screens[i]->PMEvent(i,event,undo);
+ else {
+ xf86Screens[i]->LeaveVT(i, 0);
+ xf86Screens[i]->vtSema = FALSE;
+ }
+ }
+ xf86AccessLeave();
+ xf86AccessLeaveState();
+}
+
+static void
+resume(pmEvent event, Bool undo)
+{
+ int i;
+ InputInfoPtr pInfo;
+
+ xf86AccessEnter();
+ xf86EnterServerState(SETUP);
+ for (i = 0; i < xf86NumScreens; i++) {
+ xf86EnableAccess(xf86Screens[i]);
+ if (xf86Screens[i]->PMEvent)
+ xf86Screens[i]->PMEvent(i,event,undo);
+ else {
+ xf86Screens[i]->vtSema = TRUE;
+ xf86Screens[i]->EnterVT(i, 0);
+ }
+ }
+ xf86EnterServerState(OPERATING);
+ for (i = 0; i < xf86NumScreens; i++) {
+ xf86EnableAccess(xf86Screens[i]);
+ if (xf86Screens[i]->EnableDisableFBAccess)
+ (*xf86Screens[i]->EnableDisableFBAccess) (i, TRUE);
+ }
+ SaveScreens(SCREEN_SAVER_FORCER, ScreenSaverReset);
+#if !defined(__EMX__)
+ pInfo = xf86InputDevs;
+ while (pInfo) {
+ EnableDevice(pInfo->dev);
+ pInfo = pInfo->next;
+ }
+#endif
+ xf86inSuspend = FALSE;
+}
+
+static void
+DoApmEvent(pmEvent event, Bool undo)
+{
+ /*
+ * we leave that as a global function for now. I don't know if
+ * this might cause problems in the future. It is a global server
+ * variable therefore it needs to be in a server info structure
+ */
+ int i;
+
+ switch(event) {
+ case XF86_APM_SYS_STANDBY:
+ case XF86_APM_SYS_SUSPEND:
+ case XF86_APM_CRITICAL_SUSPEND: /*do we want to delay a critical suspend?*/
+ case XF86_APM_USER_STANDBY:
+ case XF86_APM_USER_SUSPEND:
+ /* should we do this ? */
+ if (!undo && !suspended) {
+ suspend(event,undo);
+ suspended = TRUE;
+ } else if (undo && suspended) {
+ resume(event,undo);
+ suspended = FALSE;
+ }
+ break;
+ case XF86_APM_STANDBY_RESUME:
+ case XF86_APM_NORMAL_RESUME:
+ case XF86_APM_CRITICAL_RESUME:
+ if (suspended) {
+ resume(event,undo);
+ suspended = FALSE;
+ }
+ break;
+ default:
+ xf86EnterServerState(SETUP);
+ for (i = 0; i < xf86NumScreens; i++) {
+ xf86EnableAccess(xf86Screens[i]);
+ if (xf86Screens[i]->PMEvent)
+ xf86Screens[i]->PMEvent(i,event,undo);
+ }
+ xf86EnterServerState(OPERATING);
+ break;
+ }
+}
+
+#define MAX_NO_EVENTS 8
+
+void
+xf86HandlePMEvents(int fd, pointer data)
+{
+ pmEvent events[MAX_NO_EVENTS];
+ int i,n;
+ Bool wait = FALSE;
+
+ if (!xf86PMGetEventFromOs)
+ return;
+
+ if ((n = xf86PMGetEventFromOs(fd,events,MAX_NO_EVENTS))) {
+ do {
+ for (i = 0; i < n; i++) {
+ xf86MsgVerb(X_INFO,3,"PM Event received: %s\n",
+ eventName(events[i]));
+ DoApmEvent(events[i],FALSE);
+ switch (xf86PMConfirmEventToOs(fd,events[i])) {
+ case PM_WAIT:
+ wait = TRUE;
+ break;
+ case PM_CONTINUE:
+ wait = FALSE;
+ break;
+ case PM_FAILED:
+ DoApmEvent(events[i],TRUE);
+ wait = FALSE;
+ break;
+ default:
+ break;
+ }
+ }
+ if (wait)
+ n = xf86PMGetEventFromOs(fd,events,MAX_NO_EVENTS);
+ else
+ break;
+ } while (1);
+ }
+}
diff --git a/hw/xfree86/common/xf86PciInfo.h b/hw/xfree86/common/xf86PciInfo.h
new file mode 100644
index 000000000..14f86cf89
--- /dev/null
+++ b/hw/xfree86/common/xf86PciInfo.h
@@ -0,0 +1,573 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86PciInfo.h,v 1.144 2003/02/07 20:41:11 martin Exp $ */
+/*
+ * Copyright 1995-2002 by The XFree86 Project, Inc.
+ *
+ * This file contains macros for the PCI Vendor and Device IDs for video
+ * cards plus a few other things that are needed in drivers or elsewhere.
+ * This information is used in several ways:
+ * 1. It is used by drivers and/or other code.
+ * 2. It is used by the pciid2c.pl script to determine what vendor data to
+ * include in the pcidata module that the X server loads.
+ * 3. A side-effect of 2. affects how config-generation works for
+ * otherwise "unknown" cards.
+ *
+ * Don't add entries here for vendors that don't make video cards,
+ * or for non-video devices unless they're needed by a driver or elsewhere.
+ * A comprehensive set of PCI vendor, device and subsystem data is
+ * auto-generated from the ../etc/pci.ids file using the pciids2c.pl script,
+ * and is used in both the scanpci module and the scanpci utility. Don't
+ * modify the pci.ids file. If new/corrected entries are required, add them
+ * to ../etc/extrapci.ids.
+ */
+
+
+#ifndef _XF86_PCIINFO_H
+#define _XF86_PCIINFO_H
+
+/* PCI Pseudo Vendor */
+#define PCI_VENDOR_GENERIC 0x00FF
+
+#define PCI_VENDOR_REAL3D 0x003D
+#define PCI_VENDOR_COMPAQ 0x0E11
+#define PCI_VENDOR_ATI 0x1002
+#define PCI_VENDOR_AVANCE 0x1005
+#define PCI_VENDOR_TSENG 0x100C
+#define PCI_VENDOR_NS 0x100B
+#define PCI_VENDOR_WEITEK 0x100E
+#define PCI_VENDOR_VIDEOLOGIC 0x1010
+#define PCI_VENDOR_DIGITAL 0x1011
+#define PCI_VENDOR_CIRRUS 0x1013
+#define PCI_VENDOR_AMD 0x1022
+#define PCI_VENDOR_TRIDENT 0x1023
+#define PCI_VENDOR_ALI 0x1025
+#define PCI_VENDOR_DELL 0x1028
+#define PCI_VENDOR_MATROX 0x102B
+#define PCI_VENDOR_CHIPSTECH 0x102C
+#define PCI_VENDOR_MIRO 0x1031
+#define PCI_VENDOR_NEC 0x1033
+#define PCI_VENDOR_SIS 0x1039
+#define PCI_VENDOR_HP 0x103C
+#define PCI_VENDOR_SGS 0x104A
+#define PCI_VENDOR_TI 0x104C
+#define PCI_VENDOR_SONY 0x104D
+#define PCI_VENDOR_OAK 0x104E
+#define PCI_VENDOR_MOTOROLA 0x1057
+#define PCI_VENDOR_NUMNINE 0x105D
+#define PCI_VENDOR_CYRIX 0x1078
+#define PCI_VENDOR_SUN 0x108E
+#define PCI_VENDOR_DIAMOND 0x1092
+#define PCI_VENDOR_BROOKTREE 0x109E
+#define PCI_VENDOR_ALI_2 0x10B9
+#define PCI_VENDOR_NEOMAGIC 0x10C8
+#define PCI_VENDOR_NVIDIA 0x10DE
+#define PCI_VENDOR_IMS 0x10E0
+#define PCI_VENDOR_INTEGRAPHICS 0x10EA
+#define PCI_VENDOR_VIA 0x1106
+#define PCI_VENDOR_ALLIANCE 0x1142
+#define PCI_VENDOR_RENDITION 0x1163
+#define PCI_VENDOR_3DFX 0x121A
+#define PCI_VENDOR_SMI 0x126F
+#define PCI_VENDOR_TRITECH 0x1292
+#define PCI_VENDOR_NVIDIA_SGS 0x12D2
+#define PCI_VENDOR_VMWARE 0x15AD
+#define PCI_VENDOR_3DLABS 0x3D3D
+#define PCI_VENDOR_AVANCE_2 0x4005
+#define PCI_VENDOR_HERCULES 0x4843
+#define PCI_VENDOR_S3 0x5333
+#define PCI_VENDOR_INTEL 0x8086
+#define PCI_VENDOR_ARK 0xEDD8
+
+
+/* Generic */
+#define PCI_CHIP_VGA 0x0000
+#define PCI_CHIP_8514 0x0001
+
+/* Real 3D */
+#define PCI_CHIP_I740_PCI 0x00D1
+
+/* Compaq */
+#define PCI_CHIP_QV1280 0x3033
+
+/* ATI */
+#define PCI_CHIP_R300_AD 0x4144
+#define PCI_CHIP_R300_AE 0x4145
+#define PCI_CHIP_R300_AF 0x4146
+#define PCI_CHIP_R300_AG 0x4147
+#define PCI_CHIP_MACH32 0x4158
+#define PCI_CHIP_R200_BB 0x4242
+#define PCI_CHIP_MACH64CT 0x4354
+#define PCI_CHIP_MACH64CX 0x4358
+#define PCI_CHIP_MACH64ET 0x4554
+#define PCI_CHIP_MACH64GB 0x4742
+#define PCI_CHIP_MACH64GD 0x4744
+#define PCI_CHIP_MACH64GI 0x4749
+#define PCI_CHIP_MACH64GL 0x474C
+#define PCI_CHIP_MACH64GM 0x474D
+#define PCI_CHIP_MACH64GN 0x474E
+#define PCI_CHIP_MACH64GO 0x474F
+#define PCI_CHIP_MACH64GP 0x4750
+#define PCI_CHIP_MACH64GQ 0x4751
+#define PCI_CHIP_MACH64GR 0x4752
+#define PCI_CHIP_MACH64GS 0x4753
+#define PCI_CHIP_MACH64GT 0x4754
+#define PCI_CHIP_MACH64GU 0x4755
+#define PCI_CHIP_MACH64GV 0x4756
+#define PCI_CHIP_MACH64GW 0x4757
+#define PCI_CHIP_MACH64GX 0x4758
+#define PCI_CHIP_MACH64GY 0x4759
+#define PCI_CHIP_MACH64GZ 0x475A
+#define PCI_CHIP_RV250_Id 0x4964
+#define PCI_CHIP_RV250_Ie 0x4965
+#define PCI_CHIP_RV250_If 0x4966
+#define PCI_CHIP_RV250_Ig 0x4967
+#define PCI_CHIP_MACH64LB 0x4C42
+#define PCI_CHIP_MACH64LD 0x4C44
+#define PCI_CHIP_RAGE128LE 0x4C45
+#define PCI_CHIP_RAGE128LF 0x4C46
+#define PCI_CHIP_MACH64LG 0x4C47
+#define PCI_CHIP_MACH64LI 0x4C49
+#define PCI_CHIP_MACH64LM 0x4C4D
+#define PCI_CHIP_MACH64LN 0x4C4E
+#define PCI_CHIP_MACH64LP 0x4C50
+#define PCI_CHIP_MACH64LQ 0x4C51
+#define PCI_CHIP_MACH64LR 0x4C52
+#define PCI_CHIP_MACH64LS 0x4C53
+#define PCI_CHIP_RADEON_LW 0x4C57
+#define PCI_CHIP_RADEON_LX 0x4C58
+#define PCI_CHIP_RADEON_LY 0x4C59
+#define PCI_CHIP_RADEON_LZ 0x4C5A
+#define PCI_CHIP_RV250_Ld 0x4C64
+#define PCI_CHIP_RV250_Le 0x4C65
+#define PCI_CHIP_RV250_Lf 0x4C66
+#define PCI_CHIP_RV250_Lg 0x4C67
+#define PCI_CHIP_RAGE128MF 0x4D46
+#define PCI_CHIP_RAGE128ML 0x4D4C
+#define PCI_CHIP_R300_ND 0x4E44
+#define PCI_CHIP_R300_NE 0x4E45
+#define PCI_CHIP_R300_NF 0x4E46
+#define PCI_CHIP_R300_NG 0x4E47
+#define PCI_CHIP_RAGE128PA 0x5041
+#define PCI_CHIP_RAGE128PB 0x5042
+#define PCI_CHIP_RAGE128PC 0x5043
+#define PCI_CHIP_RAGE128PD 0x5044
+#define PCI_CHIP_RAGE128PE 0x5045
+#define PCI_CHIP_RAGE128PF 0x5046
+#define PCI_CHIP_RAGE128PG 0x5047
+#define PCI_CHIP_RAGE128PH 0x5048
+#define PCI_CHIP_RAGE128PI 0x5049
+#define PCI_CHIP_RAGE128PJ 0x504A
+#define PCI_CHIP_RAGE128PK 0x504B
+#define PCI_CHIP_RAGE128PL 0x504C
+#define PCI_CHIP_RAGE128PM 0x504D
+#define PCI_CHIP_RAGE128PN 0x504E
+#define PCI_CHIP_RAGE128PO 0x504F
+#define PCI_CHIP_RAGE128PP 0x5050
+#define PCI_CHIP_RAGE128PQ 0x5051
+#define PCI_CHIP_RAGE128PR 0x5052
+#define PCI_CHIP_RAGE128PS 0x5053
+#define PCI_CHIP_RAGE128PT 0x5054
+#define PCI_CHIP_RAGE128PU 0x5055
+#define PCI_CHIP_RAGE128PV 0x5056
+#define PCI_CHIP_RAGE128PW 0x5057
+#define PCI_CHIP_RAGE128PX 0x5058
+#define PCI_CHIP_RADEON_QD 0x5144
+#define PCI_CHIP_RADEON_QE 0x5145
+#define PCI_CHIP_RADEON_QF 0x5146
+#define PCI_CHIP_RADEON_QG 0x5147
+#define PCI_CHIP_R200_QH 0x5148
+#define PCI_CHIP_R200_QI 0x5149
+#define PCI_CHIP_R200_QJ 0x514A
+#define PCI_CHIP_R200_QK 0x514B
+#define PCI_CHIP_R200_QL 0x514C
+#define PCI_CHIP_R200_QM 0x514D
+#define PCI_CHIP_R200_QN 0x514E
+#define PCI_CHIP_R200_QO 0x514F
+#define PCI_CHIP_RV200_QW 0x5157
+#define PCI_CHIP_RV200_QX 0x5158
+#define PCI_CHIP_RV100_QY 0x5159
+#define PCI_CHIP_RV100_QZ 0x515A
+#define PCI_CHIP_R200_Qh 0x5168
+#define PCI_CHIP_R200_Qi 0x5169
+#define PCI_CHIP_R200_Qj 0x516A
+#define PCI_CHIP_R200_Qk 0x516B
+#define PCI_CHIP_R200_Ql 0x516C /* Undocumented in all ATI manuals */
+#define PCI_CHIP_RAGE128RE 0x5245
+#define PCI_CHIP_RAGE128RF 0x5246
+#define PCI_CHIP_RAGE128RG 0x5247
+#define PCI_CHIP_RAGE128RK 0x524B
+#define PCI_CHIP_RAGE128RL 0x524C
+#define PCI_CHIP_RAGE128SE 0x5345
+#define PCI_CHIP_RAGE128SF 0x5346
+#define PCI_CHIP_RAGE128SG 0x5347
+#define PCI_CHIP_RAGE128SH 0x5348
+#define PCI_CHIP_RAGE128SK 0x534B
+#define PCI_CHIP_RAGE128SL 0x534C
+#define PCI_CHIP_RAGE128SM 0x534D
+#define PCI_CHIP_RAGE128SN 0x534E
+#define PCI_CHIP_RAGE128TF 0x5446
+#define PCI_CHIP_RAGE128TL 0x544C
+#define PCI_CHIP_RAGE128TR 0x5452
+#define PCI_CHIP_RAGE128TS 0x5453
+#define PCI_CHIP_RAGE128TT 0x5454
+#define PCI_CHIP_RAGE128TU 0x5455
+#define PCI_CHIP_MACH64VT 0x5654
+#define PCI_CHIP_MACH64VU 0x5655
+#define PCI_CHIP_MACH64VV 0x5656
+
+/* Avance Logic */
+#define PCI_CHIP_ALG2064 0x2064
+#define PCI_CHIP_ALG2301 0x2301
+#define PCI_CHIP_ALG2501 0x2501
+
+/* Tseng */
+#define PCI_CHIP_ET4000_W32P_A 0x3202
+#define PCI_CHIP_ET4000_W32P_B 0x3205
+#define PCI_CHIP_ET4000_W32P_D 0x3206
+#define PCI_CHIP_ET4000_W32P_C 0x3207
+#define PCI_CHIP_ET6000 0x3208
+#define PCI_CHIP_ET6300 0x4702
+
+/* Weitek */
+#define PCI_CHIP_P9000 0x9001
+#define PCI_CHIP_P9100 0x9100
+
+/* Digital */
+#define PCI_CHIP_DC21050 0x0001
+#define PCI_CHIP_DEC21030 0x0004
+#define PCI_CHIP_TGA2 0x000D
+
+/* Cirrus Logic */
+#define PCI_CHIP_GD7548 0x0038
+#define PCI_CHIP_GD7555 0x0040
+#define PCI_CHIP_GD5430 0x00A0
+#define PCI_CHIP_GD5434_4 0x00A4
+#define PCI_CHIP_GD5434_8 0x00A8
+#define PCI_CHIP_GD5436 0x00AC
+#define PCI_CHIP_GD5446 0x00B8
+#define PCI_CHIP_GD5480 0x00BC
+#define PCI_CHIP_GD5462 0x00D0
+#define PCI_CHIP_GD5464 0x00D4
+#define PCI_CHIP_GD5464BD 0x00D5
+#define PCI_CHIP_GD5465 0x00D6
+#define PCI_CHIP_6729 0x1100
+#define PCI_CHIP_6832 0x1110
+#define PCI_CHIP_GD7542 0x1200
+#define PCI_CHIP_GD7543 0x1202
+#define PCI_CHIP_GD7541 0x1204
+
+/* AMD */
+#define PCI_CHIP_AMD761 0x700E
+
+/* Trident */
+#define PCI_CHIP_8400 0x8400
+#define PCI_CHIP_8420 0x8420
+#define PCI_CHIP_8500 0x8500
+#define PCI_CHIP_8520 0x8520
+#define PCI_CHIP_8600 0x8600
+#define PCI_CHIP_8620 0x8620
+#define PCI_CHIP_8820 0x8820
+#define PCI_CHIP_9320 0x9320
+#define PCI_CHIP_9388 0x9388
+#define PCI_CHIP_9397 0x9397
+#define PCI_CHIP_939A 0x939A
+#define PCI_CHIP_9420 0x9420
+#define PCI_CHIP_9440 0x9440
+#define PCI_CHIP_9520 0x9520
+#define PCI_CHIP_9525 0x9525
+#define PCI_CHIP_9540 0x9540
+#define PCI_CHIP_9660 0x9660
+#define PCI_CHIP_9750 0x9750
+#define PCI_CHIP_9850 0x9850
+#define PCI_CHIP_9880 0x9880
+#define PCI_CHIP_9910 0x9910
+
+/* ALI */
+#define PCI_CHIP_M1435 0x1435
+
+/* Matrox */
+#define PCI_CHIP_MGA2085 0x0518
+#define PCI_CHIP_MGA2064 0x0519
+#define PCI_CHIP_MGA1064 0x051A
+#define PCI_CHIP_MGA2164 0x051B
+#define PCI_CHIP_MGA2164_AGP 0x051F
+#define PCI_CHIP_MGAG200_PCI 0x0520
+#define PCI_CHIP_MGAG200 0x0521
+#define PCI_CHIP_MGAG400 0x0525
+#define PCI_CHIP_MGAG550 0x2527
+#define PCI_CHIP_IMPRESSION 0x0D10
+#define PCI_CHIP_MGAG100_PCI 0x1000
+#define PCI_CHIP_MGAG100 0x1001
+
+#define PCI_CARD_G400_TH 0x2179
+#define PCI_CARD_MILL_G200_SD 0xFF00
+#define PCI_CARD_PROD_G100_SD 0xFF01
+#define PCI_CARD_MYST_G200_SD 0xFF02
+#define PCI_CARD_MILL_G200_SG 0xFF03
+#define PCI_CARD_MARV_G200_SD 0xFF04
+
+/* Chips & Tech */
+#define PCI_CHIP_65545 0x00D8
+#define PCI_CHIP_65548 0x00DC
+#define PCI_CHIP_65550 0x00E0
+#define PCI_CHIP_65554 0x00E4
+#define PCI_CHIP_65555 0x00E5
+#define PCI_CHIP_68554 0x00F4
+#define PCI_CHIP_69000 0x00C0
+#define PCI_CHIP_69030 0x0C30
+
+/* Miro */
+#define PCI_CHIP_ZR36050 0x5601
+
+/* NEC */
+#define PCI_CHIP_POWER_VR 0x0046
+
+/* SiS */
+#define PCI_CHIP_SG86C201 0x0001
+#define PCI_CHIP_SG86C202 0x0002
+#define PCI_CHIP_SG85C503 0x0008
+#define PCI_CHIP_SIS5597 0x0200
+/* Agregado por Carlos Duclos & Manuel Jander */
+#define PCI_CHIP_SIS82C204 0x0204
+#define PCI_CHIP_SG86C205 0x0205
+#define PCI_CHIP_SG86C215 0x0215
+#define PCI_CHIP_SG86C225 0x0225
+#define PCI_CHIP_85C501 0x0406
+#define PCI_CHIP_85C496 0x0496
+#define PCI_CHIP_85C601 0x0601
+#define PCI_CHIP_85C5107 0x5107
+#define PCI_CHIP_85C5511 0x5511
+#define PCI_CHIP_85C5513 0x5513
+#define PCI_CHIP_SIS5571 0x5571
+#define PCI_CHIP_SIS5597_2 0x5597
+#define PCI_CHIP_SIS530 0x6306
+#define PCI_CHIP_SIS6326 0x6326
+#define PCI_CHIP_SIS7001 0x7001
+#define PCI_CHIP_SIS300 0x0300
+#define PCI_CHIP_SIS315H 0x0310
+#define PCI_CHIP_SIS315PRO 0x0325
+#define PCI_CHIP_SIS330 0x0330
+#define PCI_CHIP_SIS630 0x6300
+#define PCI_CHIP_SIS540 0x5300
+#define PCI_CHIP_SIS550 0x5315
+#define PCI_CHIP_SIS650 0x6325
+#define PCI_CHIP_SIS730 0x7300
+
+/* Hewlett-Packard */
+#define PCI_CHIP_ELROY 0x1054
+#define PCI_CHIP_ZX1_SBA 0x1229
+#define PCI_CHIP_ZX1_IOC 0x122A
+#define PCI_CHIP_ZX1_LBA 0x122E /* a.k.a. Mercury */
+
+/* SGS */
+#define PCI_CHIP_STG2000 0x0008
+#define PCI_CHIP_STG1764 0x0009
+#define PCI_CHIP_KYROII 0x0010
+
+/* Texas Instruments */
+#define PCI_CHIP_TI_PERMEDIA 0x3D04
+#define PCI_CHIP_TI_PERMEDIA2 0x3D07
+
+/* Oak */
+#define PCI_CHIP_OTI107 0x0107
+
+/* Number Nine */
+#define PCI_CHIP_I128 0x2309
+#define PCI_CHIP_I128_2 0x2339
+#define PCI_CHIP_I128_T2R 0x493D
+#define PCI_CHIP_I128_T2R4 0x5348
+
+/* Sun */
+#define PCI_CHIP_EBUS 0x1000
+#define PCI_CHIP_HAPPY_MEAL 0x1001
+#define PCI_CHIP_SIMBA 0x5000
+#define PCI_CHIP_PSYCHO 0x8000
+#define PCI_CHIP_SCHIZO 0x8001
+#define PCI_CHIP_SABRE 0xA000
+#define PCI_CHIP_HUMMINGBIRD 0xA001
+
+/* BrookTree */
+#define PCI_CHIP_BT848 0x0350
+#define PCI_CHIP_BT849 0x0351
+
+/* Acer Laboratories Inc (ALI_2) */
+#define PCI_CHIP_M1541 0x1541
+
+/* NVIDIA */
+#define PCI_CHIP_NV1 0x0008
+#define PCI_CHIP_DAC64 0x0009
+#define PCI_CHIP_TNT 0x0020
+#define PCI_CHIP_TNT2 0x0028
+#define PCI_CHIP_UTNT2 0x0029
+#define PCI_CHIP_VTNT2 0x002C
+#define PCI_CHIP_UVTNT2 0x002D
+#define PCI_CHIP_ITNT2 0x00A0
+#define PCI_CHIP_GEFORCE_256 0x0100
+#define PCI_CHIP_GEFORCE_DDR 0x0101
+#define PCI_CHIP_QUADRO 0x0103
+#define PCI_CHIP_GEFORCE2_MX 0x0110
+#define PCI_CHIP_GEFORCE2_MX_100 0x0111
+#define PCI_CHIP_GEFORCE2_GO 0x0112
+#define PCI_CHIP_QUADRO2_MXR 0x0113
+#define PCI_CHIP_GEFORCE2_GTS 0x0150
+#define PCI_CHIP_GEFORCE2_TI 0x0151
+#define PCI_CHIP_GEFORCE2_ULTRA 0x0152
+#define PCI_CHIP_QUADRO2_PRO 0x0153
+#define PCI_CHIP_GEFORCE4_MX_460 0x0170
+#define PCI_CHIP_GEFORCE4_MX_440 0x0171
+#define PCI_CHIP_GEFORCE4_MX_420 0x0172
+#define PCI_CHIP_GEFORCE4_440_GO 0x0174
+#define PCI_CHIP_GEFORCE4_420_GO 0x0175
+#define PCI_CHIP_GEFORCE4_420_GO_M32 0x0176
+#define PCI_CHIP_QUADRO4_500XGL 0x0178
+#define PCI_CHIP_GEFORCE4_440_GO_M64 0x0179
+#define PCI_CHIP_QUADRO4_200 0x017A
+#define PCI_CHIP_QUADRO4_550XGL 0x017B
+#define PCI_CHIP_QUADRO4_500_GOGL 0x017C
+#define PCI_CHIP_IGEFORCE2 0x01A0
+#define PCI_CHIP_GEFORCE3 0x0200
+#define PCI_CHIP_GEFORCE3_TI_200 0x0201
+#define PCI_CHIP_GEFORCE3_TI_500 0x0202
+#define PCI_CHIP_QUADRO_DCC 0x0203
+#define PCI_CHIP_GEFORCE4_TI_4600 0x0250
+#define PCI_CHIP_GEFORCE4_TI_4400 0x0251
+#define PCI_CHIP_GEFORCE4_TI_4200 0x0253
+#define PCI_CHIP_QUADRO4_900XGL 0x0258
+#define PCI_CHIP_QUADRO4_750XGL 0x0259
+#define PCI_CHIP_QUADRO4_700XGL 0x025B
+
+/* NVIDIA & SGS */
+#define PCI_CHIP_RIVA128 0x0018
+
+/* IMS */
+#define PCI_CHIP_IMSTT128 0x9128
+#define PCI_CHIP_IMSTT3D 0x9135
+
+/* VIA Technologies */
+#define PCI_CHIP_APOLLOVP1 0x0585
+#define PCI_CHIP_APOLLOPRO133X 0x0691
+
+/* Alliance Semiconductor */
+#define PCI_CHIP_AP6410 0x3210
+#define PCI_CHIP_AP6422 0x6422
+#define PCI_CHIP_AT24 0x6424
+#define PCI_CHIP_AT3D 0x643D
+
+/* 3dfx Interactive */
+#define PCI_CHIP_VOODOO_GRAPHICS 0x0001
+#define PCI_CHIP_VOODOO2 0x0002
+#define PCI_CHIP_BANSHEE 0x0003
+#define PCI_CHIP_VOODOO3 0x0005
+#define PCI_CHIP_VOODOO5 0x0009
+
+#define PCI_CARD_VOODOO3_2000 0x0036
+#define PCI_CARD_VOODOO3_3000 0x003A
+
+/* Rendition */
+#define PCI_CHIP_V1000 0x0001
+#define PCI_CHIP_V2x00 0x2000
+
+/* 3Dlabs */
+#define PCI_CHIP_300SX 0x0001
+#define PCI_CHIP_500TX 0x0002
+#define PCI_CHIP_DELTA 0x0003
+#define PCI_CHIP_PERMEDIA 0x0004
+#define PCI_CHIP_MX 0x0006
+#define PCI_CHIP_PERMEDIA2 0x0007
+#define PCI_CHIP_GAMMA 0x0008
+#define PCI_CHIP_PERMEDIA2V 0x0009
+#define PCI_CHIP_PERMEDIA3 0x000A
+#define PCI_CHIP_PERMEDIA4 0x000C
+#define PCI_CHIP_R4 0x000D
+#define PCI_CHIP_GAMMA2 0x000E
+#define PCI_CHIP_R4ALT 0x0011
+
+/* S3 */
+#define PCI_CHIP_PLATO 0x0551
+#define PCI_CHIP_VIRGE 0x5631
+#define PCI_CHIP_TRIO 0x8811
+#define PCI_CHIP_AURORA64VP 0x8812
+#define PCI_CHIP_TRIO64UVP 0x8814
+#define PCI_CHIP_VIRGE_VX 0x883D
+#define PCI_CHIP_868 0x8880
+#define PCI_CHIP_928 0x88B0
+#define PCI_CHIP_864_0 0x88C0
+#define PCI_CHIP_864_1 0x88C1
+#define PCI_CHIP_964_0 0x88D0
+#define PCI_CHIP_964_1 0x88D1
+#define PCI_CHIP_968 0x88F0
+#define PCI_CHIP_TRIO64V2_DXGX 0x8901
+#define PCI_CHIP_PLATO_PX 0x8902
+#define PCI_CHIP_Trio3D 0x8904
+#define PCI_CHIP_Trio3D_2X 0x8A13
+#define PCI_CHIP_VIRGE_DXGX 0x8A01
+#define PCI_CHIP_VIRGE_GX2 0x8A10
+#define PCI_CHIP_SAVAGE3D 0x8A20
+#define PCI_CHIP_SAVAGE3D_MV 0x8A21
+#define PCI_CHIP_SAVAGE4 0x8A22
+#define PCI_CHIP_VIRGE_MX 0x8C01
+#define PCI_CHIP_VIRGE_MXPLUS 0x8C01
+#define PCI_CHIP_VIRGE_MXP 0x8C03
+#define PCI_CHIP_PROSAVAGE_PM 0x8A25
+#define PCI_CHIP_PROSAVAGE_KM 0x8A26
+#define PCI_CHIP_SAVAGE_MX_MV 0x8C10
+#define PCI_CHIP_SAVAGE_MX 0x8C11
+#define PCI_CHIP_SAVAGE_IX_MV 0x8C12
+#define PCI_CHIP_SAVAGE_IX 0x8C13
+#define PCI_CHIP_SAVAGE2000 0x9102
+
+/* ARK Logic */
+#define PCI_CHIP_1000PV 0xA091
+#define PCI_CHIP_2000PV 0xA099
+#define PCI_CHIP_2000MT 0xA0A1
+#define PCI_CHIP_2000MI 0xA0A9
+
+/* Tritech Microelectronics */
+#define PCI_CHIP_TR25202 0xFC02
+
+/* Neomagic */
+#define PCI_CHIP_NM2070 0x0001
+#define PCI_CHIP_NM2090 0x0002
+#define PCI_CHIP_NM2093 0x0003
+#define PCI_CHIP_NM2097 0x0083
+#define PCI_CHIP_NM2160 0x0004
+#define PCI_CHIP_NM2200 0x0005
+#define PCI_CHIP_NM2230 0x0025
+#define PCI_CHIP_NM2360 0x0006
+#define PCI_CHIP_NM2380 0x0016
+
+/* Intel */
+#define PCI_CHIP_I815_BRIDGE 0x1130
+#define PCI_CHIP_I815 0x1132
+#define PCI_CHIP_430HX_BRIDGE 0x1250
+#define PCI_CHIP_82801_P2P 0x244E
+#define PCI_CHIP_845_G_BRIDGE 0x2560
+#define PCI_CHIP_845_G 0x2562
+#define PCI_CHIP_I830_M_BRIDGE 0x3575
+#define PCI_CHIP_I830_M 0x3577
+#define PCI_CHIP_I810_BRIDGE 0x7120
+#define PCI_CHIP_I810 0x7121
+#define PCI_CHIP_I810_DC100_BRIDGE 0x7122
+#define PCI_CHIP_I810_DC100 0x7123
+#define PCI_CHIP_I810_E_BRIDGE 0x7124
+#define PCI_CHIP_I810_E 0x7125
+#define PCI_CHIP_440BX_BRIDGE 0x7190
+#define PCI_CHIP_I740_AGP 0x7800
+#define PCI_CHIP_460GX_PXB 0x84CB
+#define PCI_CHIP_460GX_SAC 0x84E0
+#define PCI_CHIP_460GX_GXB_2 0x84E2 /* PCI function 2 */
+#define PCI_CHIP_460GX_WXB 0x84E6
+#define PCI_CHIP_460GX_GXB_1 0x84EA /* PCI function 1 */
+
+/* Silicon Motion Inc. */
+#define PCI_CHIP_SMI910 0x0910
+#define PCI_CHIP_SMI810 0x0810
+#define PCI_CHIP_SMI820 0x0820
+#define PCI_CHIP_SMI710 0x0710
+#define PCI_CHIP_SMI712 0x0712
+#define PCI_CHIP_SMI720 0x0720
+
+/* VMware */
+#define PCI_CHIP_VMWARE0405 0x0405
+#define PCI_CHIP_VMWARE0710 0x0710
+
+#endif /* _XF86_PCIINFO_H */
diff --git a/hw/xfree86/common/xf86Privstr.h b/hw/xfree86/common/xf86Privstr.h
new file mode 100644
index 000000000..ff704b912
--- /dev/null
+++ b/hw/xfree86/common/xf86Privstr.h
@@ -0,0 +1,234 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86Privstr.h,v 1.37 2003/02/20 04:05:14 dawes Exp $ */
+
+/*
+ * Copyright (c) 1997,1998 by The XFree86 Project, Inc.
+ */
+
+/*
+ * This file contains definitions of the private XFree86 data structures/types.
+ * None of the data structures here should be used by video drivers.
+ */
+
+#ifndef _XF86PRIVSTR_H
+#define _XF86PRIVSTR_H
+
+#include "xf86Pci.h"
+#include "xf86str.h"
+
+/* PCI probe flags */
+
+typedef enum {
+ PCIProbe1 = 0,
+ PCIProbe2,
+ PCIForceConfig1,
+ PCIForceConfig2,
+ PCIForceNone,
+ PCIOsConfig
+} PciProbeType;
+
+typedef enum {
+ LogNone,
+ LogFlush,
+ LogSync
+} Log;
+
+typedef enum {
+ SKNever,
+ SKWhenNeeded,
+ SKAlways
+} SpecialKeysInDDX;
+
+/*
+ * xf86InfoRec contains global parameters which the video drivers never
+ * need to access. Global parameters which the video drivers do need
+ * should be individual globals.
+ */
+
+typedef struct {
+
+ /* keyboard part */
+ DeviceIntPtr pKeyboard;
+ DeviceProc kbdProc; /* procedure for initializing */
+ void (* kbdEvents)(void); /* proc for processing events */
+ int consoleFd;
+ int kbdFd;
+ int vtno;
+ int kbdType; /* AT84 / AT101 */
+ int kbdRate;
+ int kbdDelay;
+ int bell_pitch;
+ int bell_duration;
+ Bool autoRepeat;
+ unsigned long leds;
+ unsigned long xleds;
+ char * vtinit;
+ int scanPrefix; /* scancode-state */
+ Bool capsLock;
+ Bool numLock;
+ Bool scrollLock;
+ Bool modeSwitchLock;
+ Bool composeLock;
+ Bool vtSysreq;
+ SpecialKeysInDDX ddxSpecialKeys;
+ Bool ActionKeyBindingsSet;
+#if defined(SVR4) && defined(i386)
+ Bool panix106;
+#endif /* SVR4 && i386 */
+#if defined(__OpenBSD__) || defined(__NetBSD__)
+ int wsKbdType;
+#endif
+
+ /* mouse part */
+ DeviceIntPtr pMouse;
+#ifdef XINPUT
+ pointer mouseLocal;
+#endif
+
+ /* event handler part */
+ int lastEventTime;
+ Bool vtRequestsPending;
+ Bool inputPending;
+ Bool dontVTSwitch;
+ Bool dontZap;
+ Bool dontZoom;
+ Bool notrapSignals; /* don't exit cleanly - die at fault */
+ Bool caughtSignal;
+
+ /* graphics part */
+ Bool sharedMonitor;
+ ScreenPtr currentScreen;
+#ifdef CSRG_BASED
+ int screenFd; /* fd for memory mapped access to
+ * vga card */
+ int consType; /* Which console driver? */
+#endif
+
+#ifdef XKB
+ /*
+ * would like to use an XkbComponentNamesRec here but can't without
+ * pulling in a bunch of header files. :-(
+ */
+ char * xkbkeymap;
+ char * xkbkeycodes;
+ char * xkbtypes;
+ char * xkbcompat;
+ char * xkbsymbols;
+ char * xkbgeometry;
+ Bool xkbcomponents_specified;
+ char * xkbrules;
+ char * xkbmodel;
+ char * xkblayout;
+ char * xkbvariant;
+ char * xkboptions;
+#endif
+
+ /* Other things */
+ Bool allowMouseOpenFail;
+ Bool vidModeEnabled; /* VidMode extension enabled */
+ Bool vidModeAllowNonLocal; /* allow non-local VidMode
+ * connections */
+ Bool miscModInDevEnabled; /* Allow input devices to be
+ * changed */
+ Bool miscModInDevAllowNonLocal;
+ PciProbeType pciFlags;
+ Pix24Flags pixmap24;
+ MessageType pix24From;
+#if defined(i386) || defined(__i386__)
+ Bool pc98;
+#endif
+ Bool pmFlag;
+ Log log;
+ int estimateSizesAggressively;
+ Bool kbdCustomKeycodes;
+ Bool disableRandR;
+ MessageType randRFrom;
+ struct {
+ Bool disabled; /* enable/disable deactivating
+ * grabs or closing the
+ * connection to the grabbing
+ * client */
+ ClientPtr override; /* client that disabled
+ * grab deactivation.
+ */
+ Bool allowDeactivate;
+ Bool allowClosedown;
+ ServerGrabInfoRec server;
+ } grabInfo;
+} xf86InfoRec, *xf86InfoPtr;
+
+#ifdef DPMSExtension
+/* Private info for DPMS */
+typedef struct {
+ DPMSSetProcPtr Set;
+ CloseScreenProcPtr CloseScreen;
+ Bool Enabled;
+ int Flags;
+} DPMSRec, *DPMSPtr;
+#endif
+
+#ifdef XF86VIDMODE
+/* Private info for Video Mode Extentsion */
+typedef struct {
+ DisplayModePtr First;
+ DisplayModePtr Next;
+ int Flags;
+ CloseScreenProcPtr CloseScreen;
+} VidModeRec, *VidModePtr;
+#endif
+
+/* private resource types */
+#define ResNoAvoid ResBios
+
+/* ISC's cc can't handle ~ of UL constants, so explicitly type cast them. */
+#define XLED1 ((unsigned long) 0x00000001)
+#define XLED2 ((unsigned long) 0x00000002)
+#define XLED3 ((unsigned long) 0x00000004)
+#define XLED4 ((unsigned long) 0x00000008)
+#define XCAPS ((unsigned long) 0x20000000)
+#define XNUM ((unsigned long) 0x40000000)
+#define XSCR ((unsigned long) 0x80000000)
+#define XCOMP ((unsigned long) 0x00008000)
+
+/* BSD console driver types (consType) */
+#ifdef CSRG_BASED
+#define PCCONS 0
+#define CODRV011 1
+#define CODRV01X 2
+#define SYSCONS 8
+#define PCVT 16
+#define WSCONS 32
+#endif
+
+/* Prefix strings for driver messages */
+#ifndef X_UNKNOWN_STRING
+#define X_UNKNOWN_STRING "(\?\?)"
+#endif
+#ifndef X_PROBE_STRING
+#define X_PROBE_STRING "(--)"
+#endif
+#ifndef X_CONFIG_STRING
+#define X_CONFIG_STRING "(**)"
+#endif
+#ifndef X_DEFAULT_STRING
+#define X_DEFAULT_STRING "(==)"
+#endif
+#ifndef X_CMDLINE_STRING
+#define X_CMDLINE_STRING "(++)"
+#endif
+#ifndef X_NOTICE_STRING
+#define X_NOTICE_STRING "(!!)"
+#endif
+#ifndef X_ERROR_STRING
+#define X_ERROR_STRING "(EE)"
+#endif
+#ifndef X_WARNING_STRING
+#define X_WARNING_STRING "(WW)"
+#endif
+#ifndef X_INFO_STRING
+#define X_INFO_STRING "(II)"
+#endif
+#ifndef X_NOT_IMPLEMENTED_STRING
+#define X_NOT_IMPLEMENTED_STRING "(NI)"
+#endif
+
+#endif /* _XF86PRIVSTR_H */
diff --git a/hw/xfree86/common/xf86RandR.c b/hw/xfree86/common/xf86RandR.c
new file mode 100644
index 000000000..c2dbcc170
--- /dev/null
+++ b/hw/xfree86/common/xf86RandR.c
@@ -0,0 +1,280 @@
+/*
+ * $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86RandR.c,v 1.4 2003/02/13 10:49:38 eich Exp $
+ *
+ * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Keith Packard makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "X.h"
+#include "os.h"
+#include "mibank.h"
+#include "globals.h"
+#include "xf86.h"
+#include "xf86Priv.h"
+#include "xf86DDC.h"
+#include "mipointer.h"
+#include <randrstr.h>
+
+typedef struct _xf86RandRInfo {
+ CreateScreenResourcesProcPtr CreateScreenResources;
+ CloseScreenProcPtr CloseScreen;
+ int virtualX;
+ int virtualY;
+} XF86RandRInfoRec, *XF86RandRInfoPtr;
+
+static int xf86RandRIndex;
+static int xf86RandRGeneration;
+
+#define XF86RANDRINFO(p) ((XF86RandRInfoPtr) (p)->devPrivates[xf86RandRIndex].ptr)
+
+static int
+xf86RandRModeRefresh (DisplayModePtr mode)
+{
+ if (mode->VRefresh)
+ return (int) mode->VRefresh;
+ else
+ return (int) (mode->Clock * 1000.0 / mode->HTotal / mode->VTotal);
+}
+
+static Bool
+xf86RandRGetInfo (ScreenPtr pScreen, Rotation *rotations)
+{
+ RRScreenSizePtr pSize;
+ ScrnInfoPtr scrp = XF86SCRNINFO(pScreen);
+ XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
+ DisplayModePtr mode;
+ Bool reportVirtual = TRUE;
+ int refresh0 = 60;
+
+ *rotations = RR_Rotate_0;
+
+ for (mode = scrp->modes; ; mode = mode->next)
+ {
+ int refresh = xf86RandRModeRefresh (mode);
+ if (mode == scrp->modes)
+ refresh0 = refresh;
+ pSize = RRRegisterSize (pScreen,
+ mode->HDisplay, mode->VDisplay,
+ pScreen->mmWidth, pScreen->mmHeight);
+ if (!pSize)
+ return FALSE;
+ if (mode->HDisplay == randrp->virtualX &&
+ mode->VDisplay == randrp->virtualY)
+ reportVirtual = FALSE;
+ RRRegisterRate (pScreen, pSize, refresh);
+ if (mode == scrp->currentMode &&
+ mode->HDisplay == pScreen->width && mode->VDisplay == pScreen->height)
+ RRSetCurrentConfig (pScreen, RR_Rotate_0, refresh, pSize);
+ if (mode->next == scrp->modes)
+ break;
+ }
+ if (reportVirtual)
+ {
+ mode = scrp->modes;
+ pSize = RRRegisterSize (pScreen,
+ randrp->virtualX, randrp->virtualY,
+ pScreen->mmWidth * randrp->virtualX / mode->HDisplay,
+ pScreen->mmHeight * randrp->virtualY / mode->VDisplay);
+ if (!pSize)
+ return FALSE;
+ RRRegisterRate (pScreen, pSize, refresh0);
+ if (pScreen->width == randrp->virtualX &&
+ pScreen->height == randrp->virtualY)
+ {
+ RRSetCurrentConfig (pScreen, RR_Rotate_0, refresh0, pSize);
+ }
+ }
+ return TRUE;
+}
+
+static Bool
+xf86RandRSetMode (ScreenPtr pScreen,
+ DisplayModePtr mode,
+ Bool useVirtual)
+{
+ ScrnInfoPtr scrp = XF86SCRNINFO(pScreen);
+ XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
+ int oldWidth = pScreen->width;
+ int oldHeight = pScreen->height;
+ WindowPtr pRoot = WindowTable[pScreen->myNum];
+
+ if (pRoot)
+ xf86EnableDisableFBAccess (pScreen->myNum, FALSE);
+ if (useVirtual)
+ {
+ scrp->virtualX = randrp->virtualX;
+ scrp->virtualY = randrp->virtualY;
+ }
+ else
+ {
+ scrp->virtualX = mode->HDisplay;
+ scrp->virtualY = mode->VDisplay;
+ }
+ pScreen->width = scrp->virtualX;
+ pScreen->height = scrp->virtualY;
+ if (!xf86SwitchMode (pScreen, mode))
+ {
+ scrp->virtualX = pScreen->width = oldWidth;
+ scrp->virtualY = pScreen->height = oldHeight;
+ return FALSE;
+ }
+ /*
+ * Make sure the layout is correct
+ */
+ xf86ReconfigureLayout();
+
+ /*
+ * Make sure the whole screen is visible
+ */
+ xf86SetViewport (pScreen, pScreen->width, pScreen->height);
+ xf86SetViewport (pScreen, 0, 0);
+ if (pRoot)
+ xf86EnableDisableFBAccess (pScreen->myNum, TRUE);
+ return TRUE;
+}
+
+static Bool
+xf86RandRSetConfig (ScreenPtr pScreen,
+ Rotation rotation,
+ int rate,
+ RRScreenSizePtr pSize)
+{
+ ScrnInfoPtr scrp = XF86SCRNINFO(pScreen);
+ XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
+ DisplayModePtr mode;
+ int px, py;
+ Bool useVirtual = FALSE;
+
+ miPointerPosition (&px, &py);
+ for (mode = scrp->modes; ; mode = mode->next)
+ {
+ if (mode->HDisplay == pSize->width &&
+ mode->VDisplay == pSize->height &&
+ (rate == 0 || xf86RandRModeRefresh (mode) == rate))
+ break;
+ if (mode->next == scrp->modes)
+ {
+ if (pSize->width == randrp->virtualX &&
+ pSize->height == randrp->virtualY)
+ {
+ mode = scrp->modes;
+ useVirtual = TRUE;
+ break;
+ }
+ return FALSE;
+ }
+ }
+ if (!xf86RandRSetMode (pScreen, mode, useVirtual))
+ return FALSE;
+ /*
+ * Move the cursor back where it belongs; SwitchMode repositions it
+ */
+ if (pScreen == miPointerCurrentScreen ())
+ {
+ if (px < pSize->width && py < pSize->height)
+ (*pScreen->SetCursorPosition) (pScreen, px, py, FALSE);
+ }
+ return TRUE;
+}
+
+/*
+ * Wait until the screen is initialized before whacking the
+ * sizes around; otherwise the screen pixmap will be allocated
+ * at the current mode size rather than the maximum size
+ */
+static Bool
+xf86RandRCreateScreenResources (ScreenPtr pScreen)
+{
+ ScrnInfoPtr scrp = XF86SCRNINFO(pScreen);
+ XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
+ DisplayModePtr mode;
+
+ pScreen->CreateScreenResources = randrp->CreateScreenResources;
+ if (!(*pScreen->CreateScreenResources) (pScreen))
+ return FALSE;
+
+ mode = scrp->currentMode;
+ if (mode)
+ xf86RandRSetMode (pScreen, mode, TRUE);
+
+ return TRUE;
+}
+
+/*
+ * Reset size back to original
+ */
+static Bool
+xf86RandRCloseScreen (int index, ScreenPtr pScreen)
+{
+ ScrnInfoPtr scrp = XF86SCRNINFO(pScreen);
+ XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
+
+ scrp->virtualX = pScreen->width = randrp->virtualX;
+ scrp->virtualY = pScreen->height = randrp->virtualY;
+ scrp->currentMode = scrp->modes;
+ pScreen->CloseScreen = randrp->CloseScreen;
+ xfree (randrp);
+ pScreen->devPrivates[xf86RandRIndex].ptr = 0;
+ return (*pScreen->CloseScreen) (index, pScreen);
+}
+
+Bool
+xf86RandRInit (ScreenPtr pScreen)
+{
+ rrScrPrivPtr rp;
+ XF86RandRInfoPtr randrp;
+ ScrnInfoPtr scrp = XF86SCRNINFO(pScreen);
+
+#ifdef PANORAMIX
+ /* XXX disable RandR when using Xinerama */
+ if (!noPanoramiXExtension)
+ return TRUE;
+#endif
+ if (xf86RandRGeneration != serverGeneration)
+ {
+ xf86RandRIndex = AllocateScreenPrivateIndex();
+ xf86RandRGeneration = serverGeneration;
+ }
+
+ randrp = xalloc (sizeof (XF86RandRInfoRec));
+ if (!randrp)
+ return FALSE;
+
+ if (!RRScreenInit (pScreen))
+ {
+ xfree (randrp);
+ return FALSE;
+ }
+ rp = rrGetScrPriv(pScreen);
+ rp->rrGetInfo = xf86RandRGetInfo;
+ rp->rrSetConfig = xf86RandRSetConfig;
+
+ randrp->virtualX = scrp->virtualX;
+ randrp->virtualY = scrp->virtualY;
+
+ randrp->CreateScreenResources = pScreen->CreateScreenResources;
+ pScreen->CreateScreenResources = xf86RandRCreateScreenResources;
+
+ randrp->CloseScreen = pScreen->CloseScreen;
+ pScreen->CloseScreen = xf86RandRCloseScreen;
+
+ pScreen->devPrivates[xf86RandRIndex].ptr = randrp;
+ return TRUE;
+}
diff --git a/hw/xfree86/common/xf86Resources.h b/hw/xfree86/common/xf86Resources.h
new file mode 100644
index 000000000..6ed3015ec
--- /dev/null
+++ b/hw/xfree86/common/xf86Resources.h
@@ -0,0 +1,113 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86Resources.h,v 1.14 2002/07/24 01:47:24 tsi Exp $ */
+
+#ifndef _XF86_RESOURCES_H
+
+#define _XF86_RESOURCES_H
+
+#include "xf86str.h"
+
+#define _END {ResEnd,0,0}
+
+#define _VGA_EXCLUSIVE \
+ {ResExcMemBlock | ResBios | ResBus, 0x000A0000, 0x000AFFFF},\
+ {ResExcMemBlock | ResBios | ResBus, 0x000B0000, 0x000B7FFF},\
+ {ResExcMemBlock | ResBios | ResBus, 0x000B8000, 0x000BFFFF},\
+ {ResExcIoBlock | ResBios | ResBus, 0x03B0, 0x03BB},\
+ {ResExcIoBlock | ResBios | ResBus, 0x03C0, 0x03DF}
+
+#define _VGA_SHARED \
+ {ResShrMemBlock | ResBios | ResBus, 0x000A0000, 0x000AFFFF},\
+ {ResShrMemBlock | ResBios | ResBus, 0x000B0000, 0x000B7FFF},\
+ {ResShrMemBlock | ResBios | ResBus, 0x000B8000, 0x000BFFFF},\
+ {ResShrIoBlock | ResBios | ResBus, 0x03B0, 0x03BB},\
+ {ResShrIoBlock | ResBios | ResBus, 0x03C0, 0x03DF}
+
+#define _VGA_SHARED_MEM \
+ {ResShrMemBlock | ResBios | ResBus, 0x000A0000, 0x000AFFFF},\
+ {ResShrMemBlock | ResBios | ResBus, 0x000B0000, 0x000B7FFF},\
+ {ResShrMemBlock | ResBios | ResBus, 0x000B8000, 0x000BFFFF}
+
+#define _VGA_SHARED_IO \
+ {ResShrIoBlock | ResBios | ResBus, 0x03B0, 0x03BB},\
+ {ResShrIoBlock | ResBios | ResBus, 0x03C0, 0x03DF}
+
+/*
+ * Exclusive unused VGA: resources unneeded but cannot be disabled.
+ * Like old Millennium.
+ */
+#define _VGA_EXCLUSIVE_UNUSED \
+ {ResExcUusdMemBlock | ResBios | ResBus, 0x000A0000, 0x000AFFFF},\
+ {ResExcUusdMemBlock | ResBios | ResBus, 0x000B0000, 0x000B7FFF},\
+ {ResExcUusdMemBlock | ResBios | ResBus, 0x000B8000, 0x000BFFFF},\
+ {ResExcUusdIoBlock | ResBios | ResBus, 0x03B0, 0x03BB},\
+ {ResExcUusdIoBlock | ResBios | ResBus, 0x03C0, 0x03DF}
+
+/*
+ * Shared unused VGA: resources unneeded but cannot be disabled
+ * independently. This is used to determine if a device needs RAC.
+ */
+#define _VGA_SHARED_UNUSED \
+ {ResShrUusdMemBlock | ResBios | ResBus, 0x000A0000, 0x000AFFFF},\
+ {ResShrUusdMemBlock | ResBios | ResBus, 0x000B0000, 0x000B7FFF},\
+ {ResShrUusdMemBlock | ResBios | ResBus, 0x000B8000, 0x000BFFFF},\
+ {ResShrUusdIoBlock | ResBios | ResBus, 0x03B0, 0x03BB},\
+ {ResShrUusdIoBlock | ResBios | ResBus, 0x03C0, 0x03DF}
+
+/*
+ * Sparse versions of the above for those adapters that respond to all ISA
+ * aliases of VGA ports.
+ */
+#define _VGA_EXCLUSIVE_SPARSE \
+ {ResExcMemBlock | ResBios | ResBus, 0x000A0000, 0x000AFFFF},\
+ {ResExcMemBlock | ResBios | ResBus, 0x000B0000, 0x000B7FFF},\
+ {ResExcMemBlock | ResBios | ResBus, 0x000B8000, 0x000BFFFF},\
+ {ResExcIoSparse | ResBios | ResBus, 0x03B0, 0x03F8},\
+ {ResExcIoSparse | ResBios | ResBus, 0x03B8, 0x03FC},\
+ {ResExcIoSparse | ResBios | ResBus, 0x03C0, 0x03E0}
+
+#define _VGA_SHARED_SPARSE \
+ {ResShrMemBlock | ResBios | ResBus, 0x000A0000, 0x000AFFFF},\
+ {ResShrMemBlock | ResBios | ResBus, 0x000B0000, 0x000B7FFF},\
+ {ResShrMemBlock | ResBios | ResBus, 0x000B8000, 0x000BFFFF},\
+ {ResShrIoSparse | ResBios | ResBus, 0x03B0, 0x03F8},\
+ {ResShrIoSparse | ResBios | ResBus, 0x03B8, 0x03FC},\
+ {ResShrIoSparse | ResBios | ResBus, 0x03C0, 0x03E0}
+
+#define _8514_EXCLUSIVE \
+ {ResExcIoSparse | ResBios | ResBus, 0x02E8, 0x03F8}
+
+#define _8514_SHARED \
+ {ResShrIoSparse | ResBios | ResBus, 0x02E8, 0x03F8}
+
+/* Predefined resources */
+extern resRange resVgaExclusive[];
+extern resRange resVgaShared[];
+extern resRange resVgaIoShared[];
+extern resRange resVgaMemShared[];
+extern resRange resVgaUnusedExclusive[];
+extern resRange resVgaUnusedShared[];
+extern resRange resVgaSparseExclusive[];
+extern resRange resVgaSparseShared[];
+extern resRange res8514Exclusive[];
+extern resRange res8514Shared[];
+
+/* Less misleading aliases for xf86SetOperatingState() */
+#define resVgaMem resVgaMemShared
+#define resVgaIo resVgaIoShared
+#define resVga resVgaShared
+
+/* Old style names */
+#define RES_EXCLUSIVE_VGA resVgaExclusive
+#define RES_SHARED_VGA resVgaShared
+#define RES_EXCLUSIVE_8514 res8514Exclusive
+#define RES_SHARED_8514 res8514Shared
+
+#define _PCI_AVOID_PC_STYLE \
+ {ResExcIoSparse | ResBus, 0x0100, 0x0300},\
+ {ResExcIoSparse | ResBus, 0x0200, 0x0200},\
+ {ResExcMemBlock | ResBus, 0xA0000,0xFFFFF}
+
+extern resRange PciAvoid[];
+
+#define RES_UNDEFINED NULL
+#endif
diff --git a/hw/xfree86/common/xf86VidMode.c b/hw/xfree86/common/xf86VidMode.c
new file mode 100644
index 000000000..f766f899e
--- /dev/null
+++ b/hw/xfree86/common/xf86VidMode.c
@@ -0,0 +1,683 @@
+/*
+ * Copyright (c) 1999 by The XFree86 Project, Inc.
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86VidMode.c,v 1.14 2003/01/28 20:52:28 tsi Exp $ */
+
+/*
+ * This file contains the VidMode functions required by the extension.
+ * These have been added to avoid the need for the higher level extension
+ * code to access the private XFree86 data structures directly. Wherever
+ * possible this code uses the functions in xf86Mode.c to do the work,
+ * so that two version of code that do similar things don't have to be
+ * maintained.
+ */
+
+#include "X.h"
+#include "os.h"
+#include "xf86.h"
+#include "xf86Priv.h"
+
+#ifdef XF86VIDMODE
+#include "vidmodeproc.h"
+#include "xf86cmap.h"
+
+static int VidModeGeneration = 0;
+static int VidModeIndex = -1;
+static int VidModeCount = 0;
+static Bool VidModeClose(int i, ScreenPtr pScreen);
+
+#define VMPTR(p) ((VidModePtr)(p)->devPrivates[VidModeIndex].ptr)
+
+#endif
+
+#ifdef DEBUG
+# define DEBUG_P(x) ErrorF(x"\n");
+#else
+# define DEBUG_P(x) /**/
+#endif
+
+Bool
+VidModeExtensionInit(ScreenPtr pScreen)
+{
+#ifdef XF86VIDMODE
+ VidModePtr pVidMode;
+
+ DEBUG_P("VidModeExtensionInit");
+
+ if (!xf86GetVidModeEnabled()) {
+ DEBUG_P("!xf86GetVidModeEnabled()");
+ return FALSE;
+ }
+
+ if (serverGeneration != VidModeGeneration) {
+ if ((VidModeIndex = AllocateScreenPrivateIndex()) < 0) {
+ DEBUG_P("AllocateScreenPrivateIndex() failed");
+ return FALSE;
+ }
+ VidModeGeneration = serverGeneration;
+ }
+
+ if (!(pScreen->devPrivates[VidModeIndex].ptr = xcalloc(sizeof(VidModeRec), 1))) {
+ DEBUG_P("xcalloc failed");
+ return FALSE;
+ }
+
+ pVidMode = VMPTR(pScreen);
+ pVidMode->Flags = 0;
+ pVidMode->Next = NULL;
+ pVidMode->CloseScreen = pScreen->CloseScreen;
+ pScreen->CloseScreen = VidModeClose;
+ VidModeCount++;
+ return TRUE;
+#else
+ DEBUG_P("no vidmode extension");
+ return FALSE;
+#endif
+}
+
+
+#ifdef XF86VIDMODE
+
+static Bool
+VidModeClose(int i, ScreenPtr pScreen)
+{
+ VidModePtr pVidMode = VMPTR(pScreen);
+
+ DEBUG_P("VidModeClose");
+
+ /* This shouldn't happen */
+ if (!pVidMode)
+ return FALSE;
+
+ pScreen->CloseScreen = pVidMode->CloseScreen;
+
+ if (--VidModeCount == 0) {
+ if (pScreen->devPrivates[VidModeIndex].ptr)
+ xfree(pScreen->devPrivates[VidModeIndex].ptr);
+ pScreen->devPrivates[VidModeIndex].ptr = NULL;
+ VidModeIndex = -1;
+ }
+ return pScreen->CloseScreen(i, pScreen);
+}
+
+Bool
+VidModeAvailable(int scrnIndex)
+{
+ ScrnInfoPtr pScrn;
+ VidModePtr pVidMode;
+
+ DEBUG_P("VidModeAvailable");
+
+ if (VidModeIndex < 0) {
+ DEBUG_P("VidModeIndex < 0");
+ return FALSE;
+ }
+
+ pScrn = xf86Screens[scrnIndex];
+ if (pScrn == NULL) {
+ DEBUG_P("pScrn == NULL");
+ return FALSE;
+ }
+
+ pVidMode = VMPTR(pScrn->pScreen);
+ if (pVidMode)
+ return TRUE;
+ else {
+ DEBUG_P("pVidMode == NULL");
+ return FALSE;
+ }
+}
+
+Bool
+VidModeGetCurrentModeline(int scrnIndex, pointer *mode, int *dotClock)
+{
+ ScrnInfoPtr pScrn;
+
+ DEBUG_P("VidModeGetCurrentModeline");
+
+ if (!VidModeAvailable(scrnIndex))
+ return FALSE;
+
+ pScrn = xf86Screens[scrnIndex];
+ *mode = (pointer)(pScrn->currentMode);
+ *dotClock = pScrn->currentMode->Clock;
+
+ return TRUE;
+}
+
+int
+VidModeGetDotClock(int scrnIndex, int Clock)
+{
+ ScrnInfoPtr pScrn;
+
+ DEBUG_P("VidModeGetDotClock");
+
+ if (!VidModeAvailable(scrnIndex))
+ return 0;
+
+ pScrn = xf86Screens[scrnIndex];
+ if ((pScrn->progClock) || (Clock > MAXCLOCKS))
+ return Clock;
+ else
+ return pScrn->clock[Clock];
+}
+
+int
+VidModeGetNumOfClocks(int scrnIndex, Bool *progClock)
+{
+ ScrnInfoPtr pScrn;
+
+ DEBUG_P("VidModeGetNumOfClocks");
+
+ if (!VidModeAvailable(scrnIndex))
+ return 0;
+
+ pScrn = xf86Screens[scrnIndex];
+ if (pScrn->progClock){
+ *progClock = TRUE;
+ return 0;
+ } else {
+ *progClock = FALSE;
+ return pScrn->numClocks;
+ }
+}
+
+Bool
+VidModeGetClocks(int scrnIndex, int *Clocks)
+{
+ ScrnInfoPtr pScrn;
+ int i;
+
+ DEBUG_P("VidModeGetClocks");
+
+ if (!VidModeAvailable(scrnIndex))
+ return FALSE;
+
+ pScrn = xf86Screens[scrnIndex];
+
+ if (pScrn->progClock)
+ return FALSE;
+
+ for (i = 0; i < pScrn->numClocks; i++)
+ *Clocks++ = pScrn->clock[i];
+
+ return TRUE;
+}
+
+
+Bool
+VidModeGetFirstModeline(int scrnIndex, pointer *mode, int *dotClock)
+{
+ ScrnInfoPtr pScrn;
+ VidModePtr pVidMode;
+
+ DEBUG_P("VidModeGetFirstModeline");
+
+ if (!VidModeAvailable(scrnIndex))
+ return FALSE;
+
+ pScrn = xf86Screens[scrnIndex];
+ pVidMode = VMPTR(pScrn->pScreen);
+ pVidMode->First = pScrn->modes;
+ pVidMode->Next = pVidMode->First->next;
+
+ if (pVidMode->First->status == MODE_OK) {
+ *mode = (pointer)(pVidMode->First);
+ *dotClock = VidModeGetDotClock(scrnIndex, pVidMode->First->Clock);
+ return TRUE;
+ }
+
+ return VidModeGetNextModeline(scrnIndex, mode, dotClock);
+}
+
+Bool
+VidModeGetNextModeline(int scrnIndex, pointer *mode, int *dotClock)
+{
+ ScrnInfoPtr pScrn;
+ VidModePtr pVidMode;
+ DisplayModePtr p;
+
+ DEBUG_P("VidModeGetNextModeline");
+
+ if (!VidModeAvailable(scrnIndex))
+ return FALSE;
+
+ pScrn = xf86Screens[scrnIndex];
+ pVidMode = VMPTR(pScrn->pScreen);
+
+ for (p = pVidMode->Next; p != NULL && p != pVidMode->First; p = p->next) {
+ if (p->status == MODE_OK) {
+ pVidMode->Next = p->next;
+ *mode = (pointer)p;
+ *dotClock = VidModeGetDotClock(scrnIndex, p->Clock);
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+Bool
+VidModeDeleteModeline(int scrnIndex, pointer mode)
+{
+ ScrnInfoPtr pScrn;
+
+ DEBUG_P("VidModeDeleteModeline");
+
+ if ((mode == NULL) || (!VidModeAvailable(scrnIndex)))
+ return FALSE;
+
+ pScrn = xf86Screens[scrnIndex];
+ xf86DeleteMode(&(pScrn->modes), (DisplayModePtr)mode);
+ return TRUE;
+}
+
+Bool
+VidModeZoomViewport(int scrnIndex, int zoom)
+{
+ ScrnInfoPtr pScrn;
+
+ DEBUG_P("VidModeZoomViewPort");
+
+ if (!VidModeAvailable(scrnIndex))
+ return FALSE;
+
+ pScrn = xf86Screens[scrnIndex];
+ xf86ZoomViewport(pScrn->pScreen, zoom);
+ return TRUE;
+}
+
+Bool
+VidModeSetViewPort(int scrnIndex, int x, int y)
+{
+ ScrnInfoPtr pScrn;
+
+ DEBUG_P("VidModeSetViewPort");
+
+ if (!VidModeAvailable(scrnIndex))
+ return FALSE;
+
+ pScrn = xf86Screens[scrnIndex];
+ pScrn->frameX0 = min( max(x, 0),
+ pScrn->virtualX - pScrn->currentMode->HDisplay );
+ pScrn->frameX1 = pScrn->frameX0 + pScrn->currentMode->HDisplay - 1;
+ pScrn->frameY0 = min( max(y, 0),
+ pScrn->virtualY - pScrn->currentMode->VDisplay );
+ pScrn->frameY1 = pScrn->frameY0 + pScrn->currentMode->VDisplay - 1;
+ if (pScrn->AdjustFrame != NULL)
+ (pScrn->AdjustFrame)(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
+
+ return TRUE;
+}
+
+Bool
+VidModeGetViewPort(int scrnIndex, int *x, int *y)
+{
+ ScrnInfoPtr pScrn;
+
+ DEBUG_P("VidModeGetViewPort");
+
+ if (!VidModeAvailable(scrnIndex))
+ return FALSE;
+
+ pScrn = xf86Screens[scrnIndex];
+ *x = pScrn->frameX0;
+ *y = pScrn->frameY0;
+ return TRUE;
+}
+
+Bool
+VidModeSwitchMode(int scrnIndex, pointer mode)
+{
+ ScrnInfoPtr pScrn;
+
+ DEBUG_P("VidModeSwitchMode");
+
+ if (!VidModeAvailable(scrnIndex))
+ return FALSE;
+
+ pScrn = xf86Screens[scrnIndex];
+ /* Force a mode switch */
+ pScrn->currentMode = NULL;
+ return xf86SwitchMode(pScrn->pScreen, mode);
+}
+
+Bool
+VidModeLockZoom(int scrnIndex, Bool lock)
+{
+ ScrnInfoPtr pScrn;
+
+ DEBUG_P("VidModeLockZoom");
+
+ if (!VidModeAvailable(scrnIndex))
+ return FALSE;
+
+ pScrn = xf86Screens[scrnIndex];
+
+ if (xf86Info.dontZoom)
+ return FALSE;
+
+ xf86LockZoom(pScrn->pScreen, lock);
+ return TRUE;
+}
+
+Bool
+VidModeGetMonitor(int scrnIndex, pointer *monitor)
+{
+ ScrnInfoPtr pScrn;
+
+ DEBUG_P("VidModeGetMonitor");
+
+ if (!VidModeAvailable(scrnIndex))
+ return FALSE;
+
+ pScrn = xf86Screens[scrnIndex];
+ *monitor = (pointer)(pScrn->monitor);
+
+ return TRUE;
+}
+
+ModeStatus
+VidModeCheckModeForMonitor(int scrnIndex, pointer mode)
+{
+ ScrnInfoPtr pScrn;
+
+ DEBUG_P("VidModeCheckModeForMonitor");
+
+ if ((mode == NULL) || (!VidModeAvailable(scrnIndex)))
+ return MODE_ERROR;
+
+ pScrn = xf86Screens[scrnIndex];
+
+ return xf86CheckModeForMonitor((DisplayModePtr)mode, pScrn->monitor);
+}
+
+ModeStatus
+VidModeCheckModeForDriver(int scrnIndex, pointer mode)
+{
+ ScrnInfoPtr pScrn;
+
+ DEBUG_P("VidModeCheckModeForDriver");
+
+ if ((mode == NULL) || (!VidModeAvailable(scrnIndex)))
+ return MODE_ERROR;
+
+ pScrn = xf86Screens[scrnIndex];
+
+ return xf86CheckModeForDriver(pScrn, (DisplayModePtr)mode, 0);
+}
+
+void
+VidModeSetCrtcForMode(int scrnIndex, pointer mode)
+{
+ ScrnInfoPtr pScrn;
+ DisplayModePtr ScreenModes;
+
+ DEBUG_P("VidModeSetCrtcForMode");
+
+ if ((mode == NULL) || (!VidModeAvailable(scrnIndex)))
+ return;
+
+ /* Ugly hack so that the xf86Mode.c function can be used without change */
+ pScrn = xf86Screens[scrnIndex];
+ ScreenModes = pScrn->modes;
+ pScrn->modes = (DisplayModePtr)mode;
+
+ xf86SetCrtcForModes(pScrn, pScrn->adjustFlags);
+ pScrn->modes = ScreenModes;
+ return;
+}
+
+Bool
+VidModeAddModeline(int scrnIndex, pointer mode)
+{
+ ScrnInfoPtr pScrn;
+
+ DEBUG_P("VidModeAddModeline");
+
+ if ((mode == NULL) || (!VidModeAvailable(scrnIndex)))
+ return FALSE;
+
+ pScrn = xf86Screens[scrnIndex];
+
+ ((DisplayModePtr)mode)->next = pScrn->modes->next;
+ ((DisplayModePtr)mode)->prev = pScrn->modes;
+ pScrn->modes->next = (DisplayModePtr)mode;
+ ((DisplayModePtr)mode)->next->prev = (DisplayModePtr)mode;
+
+ return TRUE;
+}
+
+int
+VidModeGetNumOfModes(int scrnIndex)
+{
+ pointer mode = NULL;
+ int dotClock= 0, nummodes = 0;
+
+ DEBUG_P("VidModeGetNumOfModes");
+
+ if (!VidModeGetFirstModeline(scrnIndex, &mode, &dotClock))
+ return nummodes;
+
+ do {
+ nummodes++;
+ if (!VidModeGetNextModeline(scrnIndex, &mode, &dotClock))
+ return nummodes;
+ } while (TRUE);
+}
+
+Bool
+VidModeSetGamma(int scrnIndex, float red, float green, float blue)
+{
+ ScrnInfoPtr pScrn;
+ Gamma gamma;
+
+ DEBUG_P("VidModeSetGamma");
+
+ if (!VidModeAvailable(scrnIndex))
+ return FALSE;
+
+ pScrn = xf86Screens[scrnIndex];
+ gamma.red = red;
+ gamma.green = green;
+ gamma.blue = blue;
+ if (xf86ChangeGamma(pScrn->pScreen, gamma) != Success)
+ return FALSE;
+ else
+ return TRUE;
+}
+
+Bool
+VidModeGetGamma(int scrnIndex, float *red, float *green, float *blue)
+{
+ ScrnInfoPtr pScrn;
+
+ DEBUG_P("VidModeGetGamma");
+
+ if (!VidModeAvailable(scrnIndex))
+ return FALSE;
+
+ pScrn = xf86Screens[scrnIndex];
+ *red = pScrn->gamma.red;
+ *green = pScrn->gamma.green;
+ *blue = pScrn->gamma.blue;
+ return TRUE;
+}
+
+Bool
+VidModeSetGammaRamp(int scrnIndex, int size, CARD16 *r, CARD16 *g, CARD16 *b)
+{
+ ScrnInfoPtr pScrn;
+
+ if (!VidModeAvailable(scrnIndex))
+ return FALSE;
+
+ pScrn = xf86Screens[scrnIndex];
+ xf86ChangeGammaRamp(pScrn->pScreen, size, r, g, b);
+ return TRUE;
+}
+
+Bool
+VidModeGetGammaRamp(int scrnIndex, int size, CARD16 *r, CARD16 *g, CARD16 *b)
+{
+ ScrnInfoPtr pScrn;
+
+ if (!VidModeAvailable(scrnIndex))
+ return FALSE;
+
+ pScrn = xf86Screens[scrnIndex];
+ xf86GetGammaRamp(pScrn->pScreen, size, r, g, b);
+ return TRUE;
+}
+
+int
+VidModeGetGammaRampSize(int scrnIndex)
+{
+ if (!VidModeAvailable(scrnIndex))
+ return 0;
+
+ return xf86GetGammaRampSize(xf86Screens[scrnIndex]->pScreen);
+}
+
+pointer
+VidModeCreateMode(void)
+{
+ DisplayModePtr mode;
+
+ mode = xalloc(sizeof(DisplayModeRec));
+ if (mode != NULL) {
+ mode->name = "";
+ mode->Private = NULL;
+ mode->next = mode;
+ mode->prev = mode;
+ }
+ return mode;
+}
+
+void
+VidModeCopyMode(pointer modefrom, pointer modeto)
+{
+ memcpy(modeto, modefrom, sizeof(DisplayModeRec));
+}
+
+
+int
+VidModeGetModeValue(pointer mode, int valtyp)
+{
+ int ret = 0;
+
+ switch (valtyp) {
+ case VIDMODE_H_DISPLAY:
+ ret = ((DisplayModePtr) mode)->HDisplay;
+ break;
+ case VIDMODE_H_SYNCSTART:
+ ret = ((DisplayModePtr)mode)->HSyncStart;
+ break;
+ case VIDMODE_H_SYNCEND:
+ ret = ((DisplayModePtr)mode)->HSyncEnd;
+ break;
+ case VIDMODE_H_TOTAL:
+ ret = ((DisplayModePtr)mode)->HTotal;
+ break;
+ case VIDMODE_H_SKEW:
+ ret = ((DisplayModePtr)mode)->HSkew;
+ break;
+ case VIDMODE_V_DISPLAY:
+ ret = ((DisplayModePtr)mode)->VDisplay;
+ break;
+ case VIDMODE_V_SYNCSTART:
+ ret = ((DisplayModePtr)mode)->VSyncStart;
+ break;
+ case VIDMODE_V_SYNCEND:
+ ret = ((DisplayModePtr)mode)->VSyncEnd;
+ break;
+ case VIDMODE_V_TOTAL:
+ ret = ((DisplayModePtr)mode)->VTotal;
+ break;
+ case VIDMODE_FLAGS:
+ ret = ((DisplayModePtr)mode)->Flags;
+ break;
+ case VIDMODE_CLOCK:
+ ret = ((DisplayModePtr)mode)->Clock;
+ break;
+ }
+ return ret;
+}
+
+void
+VidModeSetModeValue(pointer mode, int valtyp, int val)
+{
+ switch (valtyp) {
+ case VIDMODE_H_DISPLAY:
+ ((DisplayModePtr)mode)->HDisplay = val;
+ break;
+ case VIDMODE_H_SYNCSTART:
+ ((DisplayModePtr)mode)->HSyncStart = val;
+ break;
+ case VIDMODE_H_SYNCEND:
+ ((DisplayModePtr)mode)->HSyncEnd = val;
+ break;
+ case VIDMODE_H_TOTAL:
+ ((DisplayModePtr)mode)->HTotal = val;
+ break;
+ case VIDMODE_H_SKEW:
+ ((DisplayModePtr)mode)->HSkew = val;
+ break;
+ case VIDMODE_V_DISPLAY:
+ ((DisplayModePtr)mode)->VDisplay = val;
+ break;
+ case VIDMODE_V_SYNCSTART:
+ ((DisplayModePtr)mode)->VSyncStart = val;
+ break;
+ case VIDMODE_V_SYNCEND:
+ ((DisplayModePtr)mode)->VSyncEnd = val;
+ break;
+ case VIDMODE_V_TOTAL:
+ ((DisplayModePtr)mode)->VTotal = val;
+ break;
+ case VIDMODE_FLAGS:
+ ((DisplayModePtr)mode)->Flags = val;
+ break;
+ case VIDMODE_CLOCK:
+ ((DisplayModePtr)mode)->Clock = val;
+ break;
+ }
+ return;
+}
+
+vidMonitorValue
+VidModeGetMonitorValue(pointer monitor, int valtyp, int indx)
+{
+ vidMonitorValue ret;
+
+ switch (valtyp) {
+ case VIDMODE_MON_VENDOR:
+ ret.ptr = (((MonPtr)monitor)->vendor);
+ break;
+ case VIDMODE_MON_MODEL:
+ ret.ptr = (((MonPtr)monitor)->model);
+ break;
+ case VIDMODE_MON_NHSYNC:
+ ret.i = ((MonPtr)monitor)->nHsync;
+ break;
+ case VIDMODE_MON_NVREFRESH:
+ ret.i = ((MonPtr)monitor)->nVrefresh;
+ break;
+ case VIDMODE_MON_HSYNC_LO:
+ ret.f = (100.0 * ((MonPtr)monitor)->hsync[indx].lo);
+ break;
+ case VIDMODE_MON_HSYNC_HI:
+ ret.f = (100.0 * ((MonPtr)monitor)->hsync[indx].hi);
+ break;
+ case VIDMODE_MON_VREFRESH_LO:
+ ret.f = (100.0 * ((MonPtr)monitor)->vrefresh[indx].lo);
+ break;
+ case VIDMODE_MON_VREFRESH_HI:
+ ret.f = (100.0 * ((MonPtr)monitor)->vrefresh[indx].hi);
+ break;
+ }
+ return ret;
+}
+
+
+#endif /* XF86VIDMODE */
diff --git a/hw/xfree86/common/xf86cmap.c b/hw/xfree86/common/xf86cmap.c
new file mode 100644
index 000000000..531a83c08
--- /dev/null
+++ b/hw/xfree86/common/xf86cmap.c
@@ -0,0 +1,1081 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86cmap.c,v 1.23 2001/11/16 16:47:55 dawes Exp $ */
+
+#if defined(_XOPEN_SOURCE) || defined(__QNXNTO__)
+#include <math.h>
+#else
+#define _XOPEN_SOURCE /* to get prototype for pow on some systems */
+#include <math.h>
+#undef _XOPEN_SOURCE
+#endif
+
+#include "X.h"
+#include "misc.h"
+#include "Xproto.h"
+#include "colormapst.h"
+#include "scrnintstr.h"
+
+#include "resource.h"
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86str.h"
+#include "micmap.h"
+
+#ifdef XFreeXDGA
+#define _XF86DGA_SERVER_
+#include "extensions/xf86dgastr.h"
+#include "dgaproc.h"
+#endif
+
+#include "xf86cmap.h"
+
+#define SCREEN_PROLOGUE(pScreen, field) ((pScreen)->field = \
+ ((CMapScreenPtr) (pScreen)->devPrivates[CMapScreenIndex].ptr)->field)
+#define SCREEN_EPILOGUE(pScreen, field, wrapper)\
+ ((pScreen)->field = wrapper)
+
+#define LOAD_PALETTE(pmap, index) \
+ ((pmap == miInstalledMaps[index]) && \
+ ((pScreenPriv->flags & CMAP_LOAD_EVEN_IF_OFFSCREEN) || \
+ xf86Screens[index]->vtSema || pScreenPriv->isDGAmode))
+
+
+typedef struct _CMapLink {
+ ColormapPtr cmap;
+ struct _CMapLink *next;
+} CMapLink, *CMapLinkPtr;
+
+typedef struct {
+ ScrnInfoPtr pScrn;
+ CloseScreenProcPtr CloseScreen;
+ CreateColormapProcPtr CreateColormap;
+ DestroyColormapProcPtr DestroyColormap;
+ InstallColormapProcPtr InstallColormap;
+ StoreColorsProcPtr StoreColors;
+ LoadPaletteFuncPtr LoadPalette;
+ SetOverscanFuncPtr SetOverscan;
+ Bool (*EnterVT)(int, int);
+ Bool (*SwitchMode)(int, DisplayModePtr, int);
+ int (*SetDGAMode)(int, int, DGADevicePtr);
+ int maxColors;
+ int sigRGBbits;
+ int gammaElements;
+ LOCO *gamma;
+ int *PreAllocIndices;
+ CMapLinkPtr maps;
+ unsigned int flags;
+ Bool isDGAmode;
+} CMapScreenRec, *CMapScreenPtr;
+
+typedef struct {
+ int numColors;
+ LOCO *colors;
+ Bool recalculate;
+ int overscan;
+} CMapColormapRec, *CMapColormapPtr;
+
+static unsigned long CMapGeneration = 0;
+static int CMapScreenIndex = -1;
+static int CMapColormapIndex = -1;
+
+static void CMapInstallColormap(ColormapPtr);
+static void CMapStoreColors(ColormapPtr, int, xColorItem *);
+static Bool CMapCloseScreen (int, ScreenPtr);
+static Bool CMapCreateColormap (ColormapPtr);
+static void CMapDestroyColormap (ColormapPtr);
+
+static Bool CMapEnterVT(int, int);
+static Bool CMapSwitchMode(int, DisplayModePtr, int);
+static int CMapSetDGAMode(int, int, DGADevicePtr);
+static int CMapChangeGamma(int, Gamma);
+
+static void ComputeGamma(CMapScreenPtr);
+static Bool CMapAllocateColormapPrivate(ColormapPtr);
+static Bool CMapInitDefMap(ColormapPtr);
+static void CMapRefreshColors(ColormapPtr, int, int*);
+static void CMapSetOverscan(ColormapPtr, int, int *);
+static void CMapReinstallMap(ColormapPtr);
+static void CMapUnwrapScreen(ScreenPtr pScreen);
+
+
+
+Bool xf86HandleColormaps(
+ ScreenPtr pScreen,
+ int maxColors,
+ int sigRGBbits,
+ LoadPaletteFuncPtr loadPalette,
+ SetOverscanFuncPtr setOverscan,
+ unsigned int flags
+){
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ ColormapPtr pDefMap = NULL;
+ CMapScreenPtr pScreenPriv;
+ LOCO *gamma;
+ int *indices;
+ int elements;
+
+ if(!maxColors || !sigRGBbits || !loadPalette)
+ return FALSE;
+
+ if(CMapGeneration != serverGeneration) {
+ if(((CMapScreenIndex = AllocateScreenPrivateIndex()) < 0) ||
+ ((CMapColormapIndex = AllocateColormapPrivateIndex(
+ CMapInitDefMap)) < 0))
+ return FALSE;
+ CMapGeneration = serverGeneration;
+ }
+
+ elements = 1 << sigRGBbits;
+
+ if(!(gamma = xalloc(elements * sizeof(LOCO))))
+ return FALSE;
+
+ if(!(indices = xalloc(maxColors * sizeof(int)))) {
+ xfree(gamma);
+ return FALSE;
+ }
+
+ if(!(pScreenPriv = xalloc(sizeof(CMapScreenRec)))) {
+ xfree(gamma);
+ xfree(indices);
+ return FALSE;
+ }
+
+ pScreen->devPrivates[CMapScreenIndex].ptr = (pointer)pScreenPriv;
+
+ pScreenPriv->CloseScreen = pScreen->CloseScreen;
+ pScreenPriv->CreateColormap = pScreen->CreateColormap;
+ pScreenPriv->DestroyColormap = pScreen->DestroyColormap;
+ pScreenPriv->InstallColormap = pScreen->InstallColormap;
+ pScreenPriv->StoreColors = pScreen->StoreColors;
+ pScreen->CloseScreen = CMapCloseScreen;
+ pScreen->CreateColormap = CMapCreateColormap;
+ pScreen->DestroyColormap = CMapDestroyColormap;
+ pScreen->InstallColormap = CMapInstallColormap;
+ pScreen->StoreColors = CMapStoreColors;
+
+ pScreenPriv->pScrn = pScrn;
+ pScreenPriv->LoadPalette = loadPalette;
+ pScreenPriv->SetOverscan = setOverscan;
+ pScreenPriv->maxColors = maxColors;
+ pScreenPriv->sigRGBbits = sigRGBbits;
+ pScreenPriv->gammaElements = elements;
+ pScreenPriv->gamma = gamma;
+ pScreenPriv->PreAllocIndices = indices;
+ pScreenPriv->maps = NULL;
+ pScreenPriv->flags = flags;
+ pScreenPriv->isDGAmode = FALSE;
+
+ pScreenPriv->EnterVT = pScrn->EnterVT;
+ pScreenPriv->SwitchMode = pScrn->SwitchMode;
+ pScreenPriv->SetDGAMode = pScrn->SetDGAMode;
+
+ if (!(flags & CMAP_LOAD_EVEN_IF_OFFSCREEN)) {
+ pScrn->EnterVT = CMapEnterVT;
+ if ((flags & CMAP_RELOAD_ON_MODE_SWITCH) && pScrn->SwitchMode)
+ pScrn->SwitchMode = CMapSwitchMode;
+ }
+#ifdef XFreeXDGA
+ pScrn->SetDGAMode = CMapSetDGAMode;
+#endif
+ pScrn->ChangeGamma = CMapChangeGamma;
+
+ ComputeGamma(pScreenPriv);
+
+ /* get the default map */
+
+ pDefMap = (ColormapPtr) LookupIDByType(pScreen->defColormap, RT_COLORMAP);
+
+ if(!CMapAllocateColormapPrivate(pDefMap)) {
+ CMapUnwrapScreen(pScreen);
+ return FALSE;
+ }
+
+ /* Force the initial map to be loaded */
+ miInstalledMaps[pScreen->myNum] = NULL;
+ CMapInstallColormap(pDefMap);
+ return TRUE;
+}
+
+static Bool
+CMapInitDefMap(ColormapPtr cmap)
+{
+ return TRUE;
+}
+
+
+/**** Screen functions ****/
+
+
+static Bool
+CMapCloseScreen (int i, ScreenPtr pScreen)
+{
+ CMapUnwrapScreen(pScreen);
+
+ return (*pScreen->CloseScreen) (i, pScreen);
+}
+
+static Bool
+CMapAllocateColormapPrivate(ColormapPtr pmap)
+{
+ CMapScreenPtr pScreenPriv =
+ (CMapScreenPtr) pmap->pScreen->devPrivates[CMapScreenIndex].ptr;
+ CMapColormapPtr pColPriv;
+ CMapLinkPtr pLink;
+ int numColors;
+ LOCO *colors;
+
+ if((1 << pmap->pVisual->nplanes) > pScreenPriv->maxColors)
+ numColors = pmap->pVisual->ColormapEntries;
+ else
+ numColors = 1 << pmap->pVisual->nplanes;
+
+ if(!(colors = xalloc(numColors * sizeof(LOCO))))
+ return FALSE;
+
+ if(!(pColPriv = xalloc(sizeof(CMapColormapRec)))) {
+ xfree(colors);
+ return FALSE;
+ }
+
+ pmap->devPrivates[CMapColormapIndex].ptr = (pointer)pColPriv;
+
+ pColPriv->numColors = numColors;
+ pColPriv->colors = colors;
+ pColPriv->recalculate = TRUE;
+ pColPriv->overscan = -1;
+
+ /* add map to list */
+ pLink = xalloc(sizeof(CMapLink));
+ if(pLink) {
+ pLink->cmap = pmap;
+ pLink->next = pScreenPriv->maps;
+ pScreenPriv->maps = pLink;
+ }
+
+ return TRUE;
+}
+
+static Bool
+CMapCreateColormap (ColormapPtr pmap)
+{
+ ScreenPtr pScreen = pmap->pScreen;
+ CMapScreenPtr pScreenPriv =
+ (CMapScreenPtr)pScreen->devPrivates[CMapScreenIndex].ptr;
+ Bool ret = FALSE;
+
+ pScreen->CreateColormap = pScreenPriv->CreateColormap;
+ if((*pScreen->CreateColormap)(pmap)) {
+ if(CMapAllocateColormapPrivate(pmap))
+ ret = TRUE;
+ }
+ pScreen->CreateColormap = CMapCreateColormap;
+
+ return ret;
+}
+
+static void
+CMapDestroyColormap (ColormapPtr cmap)
+{
+ ScreenPtr pScreen = cmap->pScreen;
+ CMapScreenPtr pScreenPriv =
+ (CMapScreenPtr) pScreen->devPrivates[CMapScreenIndex].ptr;
+ CMapColormapPtr pColPriv =
+ (CMapColormapPtr) cmap->devPrivates[CMapColormapIndex].ptr;
+ CMapLinkPtr prevLink = NULL, pLink = pScreenPriv->maps;
+
+ if(pColPriv) {
+ if(pColPriv->colors) xfree(pColPriv->colors);
+ xfree(pColPriv);
+ }
+
+ /* remove map from list */
+ while(pLink) {
+ if(pLink->cmap == cmap) {
+ if(prevLink)
+ prevLink->next = pLink->next;
+ else
+ pScreenPriv->maps = pLink->next;
+ xfree(pLink);
+ break;
+ }
+ prevLink = pLink;
+ pLink = pLink->next;
+ }
+
+ if(pScreenPriv->DestroyColormap) {
+ pScreen->DestroyColormap = pScreenPriv->DestroyColormap;
+ (*pScreen->DestroyColormap)(cmap);
+ pScreen->DestroyColormap = CMapDestroyColormap;
+ }
+}
+
+
+
+static void
+CMapStoreColors(
+ ColormapPtr pmap,
+ int ndef,
+ xColorItem *pdefs
+){
+ ScreenPtr pScreen = pmap->pScreen;
+ VisualPtr pVisual = pmap->pVisual;
+ CMapScreenPtr pScreenPriv =
+ (CMapScreenPtr) pScreen->devPrivates[CMapScreenIndex].ptr;
+ int *indices = pScreenPriv->PreAllocIndices;
+ int num = ndef;
+
+ /* At the moment this isn't necessary since there's nobody below us */
+ pScreen->StoreColors = pScreenPriv->StoreColors;
+ (*pScreen->StoreColors)(pmap, ndef, pdefs);
+ pScreen->StoreColors = CMapStoreColors;
+
+ /* should never get here for these */
+ if( (pVisual->class == TrueColor) ||
+ (pVisual->class == StaticColor) ||
+ (pVisual->class == StaticGray))
+ return;
+
+ if(pVisual->class == DirectColor) {
+ CMapColormapPtr pColPriv =
+ (CMapColormapPtr) pmap->devPrivates[CMapColormapIndex].ptr;
+ int i;
+
+ if((1 << pVisual->nplanes) > pScreenPriv->maxColors) {
+ int index;
+
+ num = 0;
+ while(ndef--) {
+ if(pdefs[ndef].flags & DoRed) {
+ index = (pdefs[ndef].pixel & pVisual->redMask) >>
+ pVisual->offsetRed;
+ i = num;
+ while(i--)
+ if(indices[i] == index) break;
+ if(i == -1)
+ indices[num++] = index;
+ }
+ if(pdefs[ndef].flags & DoGreen) {
+ index = (pdefs[ndef].pixel & pVisual->greenMask) >>
+ pVisual->offsetGreen;
+ i = num;
+ while(i--)
+ if(indices[i] == index) break;
+ if(i == -1)
+ indices[num++] = index;
+ }
+ if(pdefs[ndef].flags & DoBlue) {
+ index = (pdefs[ndef].pixel & pVisual->blueMask) >>
+ pVisual->offsetBlue;
+ i = num;
+ while(i--)
+ if(indices[i] == index) break;
+ if(i == -1)
+ indices[num++] = index;
+ }
+ }
+
+ } else {
+ /* not really as overkill as it seems */
+ num = pColPriv->numColors;
+ for(i = 0; i < pColPriv->numColors; i++)
+ indices[i] = i;
+ }
+ } else {
+ while(ndef--)
+ indices[ndef] = pdefs[ndef].pixel;
+ }
+
+ CMapRefreshColors(pmap, num, indices);
+}
+
+
+static void
+CMapInstallColormap(ColormapPtr pmap)
+{
+ ScreenPtr pScreen = pmap->pScreen;
+ int index = pScreen->myNum;
+ CMapScreenPtr pScreenPriv =
+ (CMapScreenPtr) pScreen->devPrivates[CMapScreenIndex].ptr;
+
+ if (pmap == miInstalledMaps[index])
+ return;
+
+ pScreen->InstallColormap = pScreenPriv->InstallColormap;
+ (*pScreen->InstallColormap)(pmap);
+ pScreen->InstallColormap = CMapInstallColormap;
+
+ /* Important. We let the lower layers, namely DGA,
+ overwrite the choice of Colormap to install */
+ pmap = miInstalledMaps[index];
+
+ if(!(pScreenPriv->flags & CMAP_PALETTED_TRUECOLOR) &&
+ (pmap->pVisual->class == TrueColor) &&
+ ((1 << pmap->pVisual->nplanes) > pScreenPriv->maxColors))
+ return;
+
+ if(LOAD_PALETTE(pmap, index))
+ CMapReinstallMap(pmap);
+}
+
+
+/**** ScrnInfoRec functions ****/
+
+static Bool
+CMapEnterVT(int index, int flags)
+{
+ ScreenPtr pScreen = screenInfo.screens[index];
+ CMapScreenPtr pScreenPriv =
+ (CMapScreenPtr) pScreen->devPrivates[CMapScreenIndex].ptr;
+
+ if((*pScreenPriv->EnterVT)(index, flags)) {
+ if(miInstalledMaps[index])
+ CMapReinstallMap(miInstalledMaps[index]);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+static Bool
+CMapSwitchMode(int index, DisplayModePtr mode, int flags)
+{
+ ScreenPtr pScreen = screenInfo.screens[index];
+ CMapScreenPtr pScreenPriv =
+ (CMapScreenPtr) pScreen->devPrivates[CMapScreenIndex].ptr;
+
+ if((*pScreenPriv->SwitchMode)(index, mode, flags)) {
+ if(miInstalledMaps[index])
+ CMapReinstallMap(miInstalledMaps[index]);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+#ifdef XFreeXDGA
+static int
+CMapSetDGAMode(int index, int num, DGADevicePtr dev)
+{
+ ScreenPtr pScreen = screenInfo.screens[index];
+ CMapScreenPtr pScreenPriv =
+ (CMapScreenPtr) pScreen->devPrivates[CMapScreenIndex].ptr;
+ int ret;
+
+ ret = (*pScreenPriv->SetDGAMode)(index, num, dev);
+
+ pScreenPriv->isDGAmode = DGAActive(index);
+
+ if(!pScreenPriv->isDGAmode && miInstalledMaps[index]
+ && xf86Screens[pScreen->myNum]->vtSema)
+ CMapReinstallMap(miInstalledMaps[index]);
+
+ return ret;
+}
+#endif
+
+
+/**** Utilities ****/
+
+static void
+CMapReinstallMap(ColormapPtr pmap)
+{
+ CMapScreenPtr pScreenPriv =
+ (CMapScreenPtr) pmap->pScreen->devPrivates[CMapScreenIndex].ptr;
+ CMapColormapPtr cmapPriv =
+ (CMapColormapPtr) pmap->devPrivates[CMapColormapIndex].ptr;
+ int i = cmapPriv->numColors;
+ int *indices = pScreenPriv->PreAllocIndices;
+
+ while(i--)
+ indices[i] = i;
+
+ if(cmapPriv->recalculate)
+ CMapRefreshColors(pmap, cmapPriv->numColors, indices);
+ else {
+ (*pScreenPriv->LoadPalette)(pScreenPriv->pScrn, cmapPriv->numColors,
+ indices, cmapPriv->colors, pmap->pVisual);
+ if (pScreenPriv->SetOverscan) {
+#ifdef DEBUGOVERSCAN
+ ErrorF("SetOverscan() called from CMapReinstallMap\n");
+#endif
+ pScreenPriv->SetOverscan(pScreenPriv->pScrn, cmapPriv->overscan);
+ }
+ }
+
+ cmapPriv->recalculate = FALSE;
+}
+
+
+static void
+CMapRefreshColors(ColormapPtr pmap, int defs, int* indices)
+{
+ CMapScreenPtr pScreenPriv =
+ (CMapScreenPtr) pmap->pScreen->devPrivates[CMapScreenIndex].ptr;
+ CMapColormapPtr pColPriv =
+ (CMapColormapPtr) pmap->devPrivates[CMapColormapIndex].ptr;
+ VisualPtr pVisual = pmap->pVisual;
+ int numColors, i;
+ LOCO *gamma, *colors;
+ EntryPtr entry;
+ int reds, greens, blues, maxValue, index, shift;
+
+ numColors = pColPriv->numColors;
+ shift = 16 - pScreenPriv->sigRGBbits;
+ maxValue = (1 << pScreenPriv->sigRGBbits) - 1;
+ gamma = pScreenPriv->gamma;
+ colors = pColPriv->colors;
+
+ reds = pVisual->redMask >> pVisual->offsetRed;
+ greens = pVisual->greenMask >> pVisual->offsetGreen;
+ blues = pVisual->blueMask >> pVisual->offsetBlue;
+
+ switch(pVisual->class) {
+ case StaticGray:
+ for(i = 0; i <= numColors - 1; i++) {
+ index = i * maxValue / numColors;
+ colors[i].red = gamma[index].red;
+ colors[i].green = gamma[index].green;
+ colors[i].blue = gamma[index].blue;
+ }
+ break;
+ case TrueColor:
+ if((1 << pVisual->nplanes) > pScreenPriv->maxColors) {
+ for(i = 0; i <= reds; i++)
+ colors[i].red = gamma[i * maxValue / reds].red;
+ for(i = 0; i <= greens; i++)
+ colors[i].green = gamma[i * maxValue / greens].green;
+ for(i = 0; i <= blues; i++)
+ colors[i].blue = gamma[i * maxValue / blues].blue;
+ break;
+ }
+ for(i = 0; i < numColors; i++) {
+ colors[i].red = gamma[((i >> pVisual->offsetRed) & reds) *
+ maxValue / reds].red;
+ colors[i].green = gamma[((i >> pVisual->offsetGreen) & greens) *
+ maxValue / greens].green;
+ colors[i].blue = gamma[((i >> pVisual->offsetBlue) & blues) *
+ maxValue / blues].blue;
+ }
+ break;
+ case StaticColor:
+ case PseudoColor:
+ case GrayScale:
+ for(i = 0; i < defs; i++) {
+ index = indices[i];
+ entry = (EntryPtr)&pmap->red[index];
+
+ if(entry->fShared) {
+ colors[index].red =
+ gamma[entry->co.shco.red->color >> shift].red;
+ colors[index].green =
+ gamma[entry->co.shco.green->color >> shift].green;
+ colors[index].blue =
+ gamma[entry->co.shco.blue->color >> shift].blue;
+ } else {
+ colors[index].red =
+ gamma[entry->co.local.red >> shift].red;
+ colors[index].green =
+ gamma[entry->co.local.green >> shift].green;
+ colors[index].blue =
+ gamma[entry->co.local.blue >> shift].blue;
+ }
+ }
+ break;
+ case DirectColor:
+ if((1 << pVisual->nplanes) > pScreenPriv->maxColors) {
+ for(i = 0; i < defs; i++) {
+ index = indices[i];
+ if(index <= reds)
+ colors[index].red =
+ gamma[pmap->red[index].co.local.red >> shift].red;
+ if(index <= greens)
+ colors[index].green =
+ gamma[pmap->green[index].co.local.green >> shift].green;
+ if(index <= blues)
+ colors[index].blue =
+ gamma[pmap->blue[index].co.local.blue >> shift].blue;
+
+ }
+ break;
+ }
+ for(i = 0; i < defs; i++) {
+ index = indices[i];
+
+ colors[index].red = gamma[pmap->red[
+ (index >> pVisual->offsetRed) & reds
+ ].co.local.red >> shift].red;
+ colors[index].green = gamma[pmap->green[
+ (index >> pVisual->offsetGreen) & greens
+ ].co.local.green >> shift].green;
+ colors[index].blue = gamma[pmap->blue[
+ (index >> pVisual->offsetBlue) & blues
+ ].co.local.blue >> shift].blue;
+ }
+ break;
+ }
+
+
+ if(LOAD_PALETTE(pmap, pmap->pScreen->myNum))
+ (*pScreenPriv->LoadPalette)(pScreenPriv->pScrn, defs, indices,
+ colors, pmap->pVisual);
+
+ if (pScreenPriv->SetOverscan)
+ CMapSetOverscan(pmap, defs, indices);
+
+}
+
+static Bool
+CMapCompareColors(LOCO *color1, LOCO *color2)
+{
+ /* return TRUE if the color1 is "closer" to black than color2 */
+#ifdef DEBUGOVERSCAN
+ ErrorF("#%02x%02x%02x vs #%02x%02x%02x (%d vs %d)\n",
+ color1->red, color1->green, color1->blue,
+ color2->red, color2->green, color2->blue,
+ color1->red + color1->green + color1->blue,
+ color2->red + color2->green + color2->blue);
+#endif
+ return (color1->red + color1->green + color1->blue <
+ color2->red + color2->green + color2->blue);
+}
+
+static void
+CMapSetOverscan(ColormapPtr pmap, int defs, int *indices)
+{
+ CMapScreenPtr pScreenPriv =
+ (CMapScreenPtr) pmap->pScreen->devPrivates[CMapScreenIndex].ptr;
+ CMapColormapPtr pColPriv =
+ (CMapColormapPtr) pmap->devPrivates[CMapColormapIndex].ptr;
+ VisualPtr pVisual = pmap->pVisual;
+ int i;
+ LOCO *colors;
+ int index;
+ Bool newOverscan = FALSE;
+ int overscan, tmpOverscan;
+
+ colors = pColPriv->colors;
+ overscan = pColPriv->overscan;
+
+ /*
+ * Search for a new overscan index in the following cases:
+ *
+ * - The index hasn't yet been initialised.  In this case search
+ * for an index that is black or a close match to black.
+ *
+ * - The colour of the old index is changed. In this case search
+ * all indices for a black or close match to black.
+ *
+ * - The colour of the old index wasn't black. In this case only
+ * search the indices that were changed for a better match to black.
+ */
+
+ switch (pVisual->class) {
+ case StaticGray:
+ case TrueColor:
+ /* Should only come here once. Initialise the overscan index to 0 */
+ overscan = 0;
+ newOverscan = TRUE;
+ break;
+ case StaticColor:
+ /*
+ * Only come here once, but search for the overscan in the same way
+ * as for the other cases.
+ */
+ case DirectColor:
+ case PseudoColor:
+ case GrayScale:
+ if (overscan < 0 || overscan > pScreenPriv->maxColors - 1) {
+ /* Uninitialised */
+ newOverscan = TRUE;
+ } else {
+ /* Check if the overscan was changed */
+ for (i = 0; i < defs; i++) {
+ index = indices[i];
+ if (index == overscan) {
+ newOverscan = TRUE;
+ break;
+ }
+ }
+ }
+ if (newOverscan) {
+ /* The overscan is either uninitialised or it has been changed */
+
+ if (overscan < 0 || overscan > pScreenPriv->maxColors - 1)
+ tmpOverscan = pScreenPriv->maxColors - 1;
+ else
+ tmpOverscan = overscan;
+
+ /* search all entries for a close match to black */
+ for (i = pScreenPriv->maxColors - 1; i >= 0; i--) {
+ if (colors[i].red == 0 && colors[i].green == 0 &&
+ colors[i].blue == 0) {
+ overscan = i;
+#ifdef DEBUGOVERSCAN
+ ErrorF("Black found at index 0x%02x\n", i);
+#endif
+ break;
+ } else {
+#ifdef DEBUGOVERSCAN
+ ErrorF("0x%02x: ", i);
+#endif
+ if (CMapCompareColors(&colors[i], &colors[tmpOverscan])) {
+ tmpOverscan = i;
+#ifdef DEBUGOVERSCAN
+ ErrorF("possible \"Black\" at index 0x%02x\n", i);
+#endif
+ }
+ }
+ }
+ if (i < 0)
+ overscan = tmpOverscan;
+ } else {
+ /* Check of the old overscan wasn't black */
+ if (colors[overscan].red != 0 || colors[overscan].green != 0 ||
+ colors[overscan].blue != 0) {
+ int oldOverscan = tmpOverscan = overscan;
+ /* See of there is now a better match */
+ for (i = 0; i < defs; i++) {
+ index = indices[i];
+ if (colors[index].red == 0 && colors[index].green == 0 &&
+ colors[index].blue == 0) {
+ overscan = index;
+#ifdef DEBUGOVERSCAN
+ ErrorF("Black found at index 0x%02x\n", index);
+#endif
+ break;
+ } else {
+#ifdef DEBUGOVERSCAN
+ ErrorF("0x%02x: ", index);
+#endif
+ if (CMapCompareColors(&colors[index],
+ &colors[tmpOverscan])) {
+ tmpOverscan = index;
+#ifdef DEBUGOVERSCAN
+ ErrorF("possible \"Black\" at index 0x%02x\n",
+ index);
+#endif
+ }
+ }
+ }
+ if (i == defs)
+ overscan = tmpOverscan;
+ if (overscan != oldOverscan)
+ newOverscan = TRUE;
+ }
+ }
+ break;
+ }
+ if (newOverscan) {
+ pColPriv->overscan = overscan;
+ if (LOAD_PALETTE(pmap, pmap->pScreen->myNum)) {
+#ifdef DEBUGOVERSCAN
+ ErrorF("SetOverscan() called from CmapSetOverscan\n");
+#endif
+ pScreenPriv->SetOverscan(pScreenPriv->pScrn, overscan);
+ }
+ }
+}
+
+static void
+CMapUnwrapScreen(ScreenPtr pScreen)
+{
+ CMapScreenPtr pScreenPriv =
+ (CMapScreenPtr) pScreen->devPrivates[CMapScreenIndex].ptr;
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+
+ pScreen->CloseScreen = pScreenPriv->CloseScreen;
+ pScreen->CreateColormap = pScreenPriv->CreateColormap;
+ pScreen->DestroyColormap = pScreenPriv->DestroyColormap;
+ pScreen->InstallColormap = pScreenPriv->InstallColormap;
+ pScreen->StoreColors = pScreenPriv->StoreColors;
+
+ pScrn->EnterVT = pScreenPriv->EnterVT;
+ pScrn->SwitchMode = pScreenPriv->SwitchMode;
+ pScrn->SetDGAMode = pScreenPriv->SetDGAMode;
+
+ xfree(pScreenPriv->gamma);
+ xfree(pScreenPriv->PreAllocIndices);
+ xfree(pScreenPriv);
+}
+
+
+static void
+ComputeGamma(CMapScreenPtr priv)
+{
+ int elements = priv->gammaElements - 1;
+ double RedGamma, GreenGamma, BlueGamma;
+ int i;
+
+#ifndef DONT_CHECK_GAMMA
+ /* This check is to catch drivers that are not initialising pScrn->gamma */
+ if (priv->pScrn->gamma.red < GAMMA_MIN ||
+ priv->pScrn->gamma.red > GAMMA_MAX ||
+ priv->pScrn->gamma.green < GAMMA_MIN ||
+ priv->pScrn->gamma.green > GAMMA_MAX ||
+ priv->pScrn->gamma.blue < GAMMA_MIN ||
+ priv->pScrn->gamma.blue > GAMMA_MAX) {
+
+ xf86DrvMsgVerb(priv->pScrn->scrnIndex, X_WARNING, 0,
+ "The %s driver didn't call xf86SetGamma() to initialise\n"
+ "\tthe gamma values.\n", priv->pScrn->driverName);
+ xf86DrvMsgVerb(priv->pScrn->scrnIndex, X_WARNING, 0,
+ "PLEASE FIX THE `%s' DRIVER!\n", priv->pScrn->driverName);
+ priv->pScrn->gamma.red = 1.0;
+ priv->pScrn->gamma.green = 1.0;
+ priv->pScrn->gamma.blue = 1.0;
+ }
+#endif
+
+ RedGamma = 1.0 / (double)priv->pScrn->gamma.red;
+ GreenGamma = 1.0 / (double)priv->pScrn->gamma.green;
+ BlueGamma = 1.0 / (double)priv->pScrn->gamma.blue;
+
+ for(i = 0; i <= elements; i++) {
+ if(RedGamma == 1.0)
+ priv->gamma[i].red = i;
+ else
+ priv->gamma[i].red = (CARD16)(pow((double)i/(double)elements,
+ RedGamma) * (double)elements + 0.5);
+
+ if(GreenGamma == 1.0)
+ priv->gamma[i].green = i;
+ else
+ priv->gamma[i].green = (CARD16)(pow((double)i/(double)elements,
+ GreenGamma) * (double)elements + 0.5);
+
+ if(BlueGamma == 1.0)
+ priv->gamma[i].blue = i;
+ else
+ priv->gamma[i].blue = (CARD16)(pow((double)i/(double)elements,
+ BlueGamma) * (double)elements + 0.5);
+ }
+}
+
+
+int
+CMapChangeGamma(
+ int index,
+ Gamma gamma
+){
+ ScrnInfoPtr pScrn = xf86Screens[index];
+ ScreenPtr pScreen = pScrn->pScreen;
+ CMapColormapPtr pColPriv;
+ CMapScreenPtr pScreenPriv;
+ CMapLinkPtr pLink;
+
+ /* Is this sufficient checking ? */
+ if(CMapScreenIndex == -1)
+ return BadImplementation;
+
+ pScreenPriv = (CMapScreenPtr)pScreen->devPrivates[CMapScreenIndex].ptr;
+ if(!pScreenPriv)
+ return BadImplementation;
+
+ if (gamma.red < GAMMA_MIN || gamma.red > GAMMA_MAX ||
+ gamma.green < GAMMA_MIN || gamma.green > GAMMA_MAX ||
+ gamma.blue < GAMMA_MIN || gamma.blue > GAMMA_MAX)
+ return BadValue;
+
+ pScrn->gamma.red = gamma.red;
+ pScrn->gamma.green = gamma.green;
+ pScrn->gamma.blue = gamma.blue;
+
+ ComputeGamma(pScreenPriv);
+
+ /* mark all colormaps on this screen */
+ pLink = pScreenPriv->maps;
+ while(pLink) {
+ pColPriv =
+ (CMapColormapPtr) pLink->cmap->devPrivates[CMapColormapIndex].ptr;
+ pColPriv->recalculate = TRUE;
+ pLink = pLink->next;
+ }
+
+ if(miInstalledMaps[pScreen->myNum] &&
+ ((pScreenPriv->flags & CMAP_LOAD_EVEN_IF_OFFSCREEN) ||
+ pScrn->vtSema || pScreenPriv->isDGAmode)) {
+ ColormapPtr pMap = miInstalledMaps[pScreen->myNum];
+
+ if(!(pScreenPriv->flags & CMAP_PALETTED_TRUECOLOR) &&
+ (pMap->pVisual->class == TrueColor) &&
+ ((1 << pMap->pVisual->nplanes) > pScreenPriv->maxColors)) {
+
+ /* if the current map doesn't have a palette look
+ for another map to change the gamma on. */
+
+ pLink = pScreenPriv->maps;
+ while(pLink) {
+ if(pLink->cmap->pVisual->class == PseudoColor)
+ break;
+ pLink = pLink->next;
+ }
+
+ if(pLink) {
+ /* need to trick CMapRefreshColors() into thinking
+ this is the currently installed map */
+ miInstalledMaps[pScreen->myNum] = pLink->cmap;
+ CMapReinstallMap(pLink->cmap);
+ miInstalledMaps[pScreen->myNum] = pMap;
+ }
+ } else
+ CMapReinstallMap(pMap);
+ }
+
+ return Success;
+}
+
+
+static void
+ComputeGammaRamp (
+ CMapScreenPtr priv,
+ unsigned short *red,
+ unsigned short *green,
+ unsigned short *blue
+){
+ int elements = priv->gammaElements;
+ LOCO *entry = priv->gamma;
+ int shift = 16 - priv->sigRGBbits;
+
+ while(elements--) {
+ entry->red = *(red++) >> shift;
+ entry->green = *(green++) >> shift;
+ entry->blue = *(blue++) >> shift;
+ entry++;
+ }
+}
+
+int
+xf86ChangeGammaRamp(
+ ScreenPtr pScreen,
+ int size,
+ unsigned short *red,
+ unsigned short *green,
+ unsigned short *blue
+){
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ CMapColormapPtr pColPriv;
+ CMapScreenPtr pScreenPriv;
+ CMapLinkPtr pLink;
+
+ if(CMapScreenIndex == -1)
+ return BadImplementation;
+
+ pScreenPriv = (CMapScreenPtr)pScreen->devPrivates[CMapScreenIndex].ptr;
+ if(!pScreenPriv)
+ return BadImplementation;
+
+ if(pScreenPriv->gammaElements != size)
+ return BadValue;
+
+ ComputeGammaRamp(pScreenPriv, red, green, blue);
+
+ /* mark all colormaps on this screen */
+ pLink = pScreenPriv->maps;
+ while(pLink) {
+ pColPriv =
+ (CMapColormapPtr) pLink->cmap->devPrivates[CMapColormapIndex].ptr;
+ pColPriv->recalculate = TRUE;
+ pLink = pLink->next;
+ }
+
+ if(miInstalledMaps[pScreen->myNum] &&
+ ((pScreenPriv->flags & CMAP_LOAD_EVEN_IF_OFFSCREEN) ||
+ pScrn->vtSema || pScreenPriv->isDGAmode)) {
+ ColormapPtr pMap = miInstalledMaps[pScreen->myNum];
+
+ if(!(pScreenPriv->flags & CMAP_PALETTED_TRUECOLOR) &&
+ (pMap->pVisual->class == TrueColor) &&
+ ((1 << pMap->pVisual->nplanes) > pScreenPriv->maxColors)) {
+
+ /* if the current map doesn't have a palette look
+ for another map to change the gamma on. */
+
+ pLink = pScreenPriv->maps;
+ while(pLink) {
+ if(pLink->cmap->pVisual->class == PseudoColor)
+ break;
+ pLink = pLink->next;
+ }
+
+ if(pLink) {
+ /* need to trick CMapRefreshColors() into thinking
+ this is the currently installed map */
+ miInstalledMaps[pScreen->myNum] = pLink->cmap;
+ CMapReinstallMap(pLink->cmap);
+ miInstalledMaps[pScreen->myNum] = pMap;
+ }
+ } else
+ CMapReinstallMap(pMap);
+ }
+
+ return Success;
+}
+
+int
+xf86GetGammaRampSize(ScreenPtr pScreen)
+{
+ CMapScreenPtr pScreenPriv;
+
+ if(CMapScreenIndex == -1) return 0;
+
+ pScreenPriv = (CMapScreenPtr)pScreen->devPrivates[CMapScreenIndex].ptr;
+ if(!pScreenPriv) return 0;
+
+ return pScreenPriv->gammaElements;
+}
+
+int
+xf86GetGammaRamp(
+ ScreenPtr pScreen,
+ int size,
+ unsigned short *red,
+ unsigned short *green,
+ unsigned short *blue
+){
+ CMapScreenPtr pScreenPriv;
+ LOCO *entry;
+ int shift, sigbits;
+
+ if(CMapScreenIndex == -1)
+ return BadImplementation;
+
+ pScreenPriv = (CMapScreenPtr)pScreen->devPrivates[CMapScreenIndex].ptr;
+ if(!pScreenPriv)
+ return BadImplementation;
+
+ if(size > pScreenPriv->gammaElements)
+ return BadValue;
+
+ entry = pScreenPriv->gamma;
+ sigbits = pScreenPriv->sigRGBbits;
+
+ while(size--) {
+ *red = entry->red << (16 - sigbits);
+ *green = entry->green << (16 - sigbits);
+ *blue = entry->blue << (16 - sigbits);
+ shift = sigbits;
+ while(shift < 16) {
+ *red |= *red >> shift;
+ *green |= *green >> shift;
+ *blue |= *blue >> shift;
+ shift += sigbits;
+ }
+ red++; green++; blue++;
+ entry++;
+ }
+
+ return Success;
+}
+
+int
+xf86ChangeGamma(
+ ScreenPtr pScreen,
+ Gamma gamma
+){
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+
+ if(pScrn->ChangeGamma)
+ return (*pScrn->ChangeGamma)(pScreen->myNum, gamma);
+
+ return Success; /* Success? */
+}
diff --git a/hw/xfree86/common/xf86cmap.h b/hw/xfree86/common/xf86cmap.h
new file mode 100644
index 000000000..b871d6762
--- /dev/null
+++ b/hw/xfree86/common/xf86cmap.h
@@ -0,0 +1,62 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86cmap.h,v 1.7 2001/05/06 00:49:12 mvojkovi Exp $ */
+
+#ifndef _XF86CMAP_H
+#define _XF86CMAP_H
+
+#include "xf86str.h"
+#include "colormapst.h"
+
+#define CMAP_PALETTED_TRUECOLOR 0x0000001
+#define CMAP_RELOAD_ON_MODE_SWITCH 0x0000002
+#define CMAP_LOAD_EVEN_IF_OFFSCREEN 0x0000004
+
+typedef void (*LoadPaletteFuncPtr)(
+ ScrnInfoPtr pScrn,
+ int numColors,
+ int *indicies,
+ LOCO *colors,
+ VisualPtr pVisual
+);
+
+typedef void (*SetOverscanFuncPtr)(
+ ScrnInfoPtr pScrn,
+ int Index
+);
+
+Bool xf86HandleColormaps(
+ ScreenPtr pScreen,
+ int maxCol,
+ int sigRGBbits,
+ LoadPaletteFuncPtr loadPalette,
+ SetOverscanFuncPtr setOverscan,
+ unsigned int flags
+);
+
+int
+xf86ChangeGamma(
+ ScreenPtr pScreen,
+ Gamma newGamma
+);
+
+int
+xf86ChangeGammaRamp(
+ ScreenPtr pScreen,
+ int size,
+ unsigned short *red,
+ unsigned short *green,
+ unsigned short *blue
+);
+
+int xf86GetGammaRampSize(ScreenPtr pScreen);
+
+int
+xf86GetGammaRamp(
+ ScreenPtr pScreen,
+ int size,
+ unsigned short *red,
+ unsigned short *green,
+ unsigned short *blue
+);
+
+#endif /* _XF86CMAP_H */
+
diff --git a/hw/xfree86/common/xf86fbBus.c b/hw/xfree86/common/xf86fbBus.c
new file mode 100644
index 000000000..8fcf9b817
--- /dev/null
+++ b/hw/xfree86/common/xf86fbBus.c
@@ -0,0 +1,70 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86fbBus.c,v 1.2 2001/10/28 03:33:19 tsi Exp $ */
+
+/*
+ * Copyright (c) 2000 by The XFree86 Project, Inc.
+ */
+
+/*
+ * This file contains the interfaces to the bus-specific code
+ */
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "X.h"
+#include "os.h"
+#include "xf86.h"
+#include "xf86Priv.h"
+#include "xf86Resources.h"
+
+#include "xf86Bus.h"
+
+#define XF86_OS_PRIVS
+#define NEED_OS_RAC_PROTOS
+#include "xf86_OSproc.h"
+
+#include "xf86RAC.h"
+
+Bool fbSlotClaimed = FALSE;
+
+int
+xf86ClaimFbSlot(DriverPtr drvp, int chipset, GDevPtr dev, Bool active)
+{
+ EntityPtr p;
+ int num;
+
+ num = xf86AllocateEntity();
+ p = xf86Entities[num];
+ p->driver = drvp;
+ p->chipset = 0;
+ p->busType = BUS_NONE;
+ p->active = active;
+ p->inUse = FALSE;
+ xf86AddDevToEntity(num, dev);
+ p->access = xnfcalloc(1,sizeof(EntityAccessRec));
+ p->access->fallback = &AccessNULL;
+ p->access->pAccess = &AccessNULL;
+ p->busAcc = NULL;
+
+ fbSlotClaimed = TRUE;
+ return num;
+}
+
+/*
+ * Get the list of FB "slots" claimed by a screen
+ */
+int
+xf86GetFbInfoForScreen(int scrnIndex)
+{
+ int num = 0;
+ int i;
+ EntityPtr p;
+
+ for (i = 0; i < xf86Screens[scrnIndex]->numEntities; i++) {
+ p = xf86Entities[xf86Screens[scrnIndex]->entityList[i]];
+ if (p->busType == BUS_NONE) {
+ num++;
+ }
+ }
+ return num;
+}
diff --git a/hw/xfree86/common/xf86fbman.c b/hw/xfree86/common/xf86fbman.c
new file mode 100644
index 000000000..7f4cffaae
--- /dev/null
+++ b/hw/xfree86/common/xf86fbman.c
@@ -0,0 +1,1236 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86fbman.c,v 1.24 2001/12/05 19:23:52 mvojkovi Exp $ */
+
+#include "misc.h"
+#include "xf86.h"
+
+#include "X.h"
+#include "scrnintstr.h"
+#include "regionstr.h"
+#include "xf86fbman.h"
+
+static int xf86FBMangerIndex = -1;
+static unsigned long xf86ManagerGeneration = 0;
+
+Bool xf86RegisterOffscreenManager(
+ ScreenPtr pScreen,
+ FBManagerFuncsPtr funcs
+){
+
+ if(xf86ManagerGeneration != serverGeneration) {
+ if((xf86FBMangerIndex = AllocateScreenPrivateIndex()) < 0)
+ return FALSE;
+ xf86ManagerGeneration = serverGeneration;
+ }
+
+ pScreen->devPrivates[xf86FBMangerIndex].ptr = (pointer)funcs;
+
+ return TRUE;
+}
+
+
+Bool
+xf86FBManagerRunning(ScreenPtr pScreen)
+{
+ if(xf86FBMangerIndex < 0)
+ return FALSE;
+ if(!pScreen->devPrivates[xf86FBMangerIndex].ptr)
+ return FALSE;
+
+ return TRUE;
+}
+
+Bool
+xf86RegisterFreeBoxCallback(
+ ScreenPtr pScreen,
+ FreeBoxCallbackProcPtr FreeBoxCallback,
+ pointer devPriv
+){
+ FBManagerFuncsPtr funcs;
+
+ if(xf86FBMangerIndex < 0)
+ return FALSE;
+ if(!(funcs = (FBManagerFuncsPtr)pScreen->devPrivates[xf86FBMangerIndex].ptr))
+ return FALSE;
+
+ return (*funcs->RegisterFreeBoxCallback)(pScreen, FreeBoxCallback, devPriv);
+}
+
+
+FBAreaPtr
+xf86AllocateOffscreenArea(
+ ScreenPtr pScreen,
+ int w, int h,
+ int gran,
+ MoveAreaCallbackProcPtr moveCB,
+ RemoveAreaCallbackProcPtr removeCB,
+ pointer privData
+){
+ FBManagerFuncsPtr funcs;
+
+ if(xf86FBMangerIndex < 0)
+ return NULL;
+ if(!(funcs = (FBManagerFuncsPtr)pScreen->devPrivates[xf86FBMangerIndex].ptr))
+ return NULL;
+
+ return (*funcs->AllocateOffscreenArea)(
+ pScreen, w, h, gran, moveCB, removeCB, privData);
+}
+
+
+FBLinearPtr
+xf86AllocateOffscreenLinear(
+ ScreenPtr pScreen,
+ int length,
+ int gran,
+ MoveLinearCallbackProcPtr moveCB,
+ RemoveLinearCallbackProcPtr removeCB,
+ pointer privData
+){
+ FBManagerFuncsPtr funcs;
+
+ if(xf86FBMangerIndex < 0)
+ return NULL;
+ if(!(funcs = (FBManagerFuncsPtr)pScreen->devPrivates[xf86FBMangerIndex].ptr))
+ return NULL;
+
+ return (*funcs->AllocateOffscreenLinear)(
+ pScreen, length, gran, moveCB, removeCB, privData);
+}
+
+
+void
+xf86FreeOffscreenArea(FBAreaPtr area)
+{
+ FBManagerFuncsPtr funcs;
+
+ if(!area) return;
+
+ if(xf86FBMangerIndex < 0)
+ return;
+ if(!(funcs =
+ (FBManagerFuncsPtr)area->pScreen->devPrivates[xf86FBMangerIndex].ptr))
+ return;
+
+ (*funcs->FreeOffscreenArea)(area);
+
+ return;
+}
+
+
+void
+xf86FreeOffscreenLinear(FBLinearPtr area)
+{
+ FBManagerFuncsPtr funcs;
+
+ if(!area) return;
+
+ if(xf86FBMangerIndex < 0)
+ return;
+ if(!(funcs =
+ (FBManagerFuncsPtr)area->pScreen->devPrivates[xf86FBMangerIndex].ptr))
+ return;
+
+ (*funcs->FreeOffscreenLinear)(area);
+
+ return;
+}
+
+
+Bool
+xf86ResizeOffscreenArea(
+ FBAreaPtr resize,
+ int w, int h
+){
+ FBManagerFuncsPtr funcs;
+
+ if(!resize) return FALSE;
+
+ if(xf86FBMangerIndex < 0)
+ return FALSE;
+ if(!(funcs =
+ (FBManagerFuncsPtr)resize->pScreen->devPrivates[xf86FBMangerIndex].ptr))
+ return FALSE;
+
+ return (*funcs->ResizeOffscreenArea)(resize, w, h);
+}
+
+Bool
+xf86ResizeOffscreenLinear(
+ FBLinearPtr resize,
+ int size
+){
+ FBManagerFuncsPtr funcs;
+
+ if(!resize) return FALSE;
+
+ if(xf86FBMangerIndex < 0)
+ return FALSE;
+ if(!(funcs =
+ (FBManagerFuncsPtr)resize->pScreen->devPrivates[xf86FBMangerIndex].ptr))
+ return FALSE;
+
+ return (*funcs->ResizeOffscreenLinear)(resize, size);
+}
+
+
+Bool
+xf86QueryLargestOffscreenArea(
+ ScreenPtr pScreen,
+ int *w, int *h,
+ int gran,
+ int preferences,
+ int severity
+){
+ FBManagerFuncsPtr funcs;
+
+ *w = 0;
+ *h = 0;
+
+ if(xf86FBMangerIndex < 0)
+ return FALSE;
+ if(!(funcs = (FBManagerFuncsPtr)pScreen->devPrivates[xf86FBMangerIndex].ptr))
+ return FALSE;
+
+ return (*funcs->QueryLargestOffscreenArea)(
+ pScreen, w, h, gran, preferences, severity);
+}
+
+Bool
+xf86QueryLargestOffscreenLinear(
+ ScreenPtr pScreen,
+ int *size,
+ int gran,
+ int severity
+){
+ FBManagerFuncsPtr funcs;
+
+ *size = 0;
+
+ if(xf86FBMangerIndex < 0)
+ return FALSE;
+ if(!(funcs = (FBManagerFuncsPtr)pScreen->devPrivates[xf86FBMangerIndex].ptr))
+ return FALSE;
+
+ return (*funcs->QueryLargestOffscreenLinear)(
+ pScreen, size, gran, severity);
+}
+
+
+Bool
+xf86PurgeUnlockedOffscreenAreas(ScreenPtr pScreen)
+{
+ FBManagerFuncsPtr funcs;
+
+ if(xf86FBMangerIndex < 0)
+ return FALSE;
+ if(!(funcs = (FBManagerFuncsPtr)pScreen->devPrivates[xf86FBMangerIndex].ptr))
+ return FALSE;
+
+ return (*funcs->PurgeOffscreenAreas)(pScreen);
+}
+
+/************************************************************\
+
+ Below is a specific implementation of an offscreen manager.
+
+\************************************************************/
+
+static unsigned long xf86FBGeneration = 0;
+static int xf86FBScreenIndex = -1;
+
+typedef struct _FBLink {
+ FBArea area;
+ struct _FBLink *next;
+} FBLink, *FBLinkPtr;
+
+typedef struct _FBLinearLink {
+ FBLinear linear;
+ FBAreaPtr area;
+ struct _FBLinearLink *next;
+} FBLinearLink, *FBLinearLinkPtr;
+
+
+typedef struct {
+ ScreenPtr pScreen;
+ RegionPtr InitialBoxes;
+ RegionPtr FreeBoxes;
+ FBLinkPtr UsedAreas;
+ int NumUsedAreas;
+ FBLinearLinkPtr LinearAreas;
+ CloseScreenProcPtr CloseScreen;
+ int NumCallbacks;
+ FreeBoxCallbackProcPtr *FreeBoxesUpdateCallback;
+ DevUnion *devPrivates;
+} FBManager, *FBManagerPtr;
+
+
+static void
+SendCallFreeBoxCallbacks(FBManagerPtr offman)
+{
+ int i = offman->NumCallbacks;
+
+ while(i--) {
+ (*offman->FreeBoxesUpdateCallback[i])(
+ offman->pScreen, offman->FreeBoxes, offman->devPrivates[i].ptr);
+ }
+}
+
+static Bool
+localRegisterFreeBoxCallback(
+ ScreenPtr pScreen,
+ FreeBoxCallbackProcPtr FreeBoxCallback,
+ pointer devPriv
+){
+ FBManagerPtr offman;
+ FreeBoxCallbackProcPtr *newCallbacks;
+ DevUnion *newPrivates;
+
+ offman = pScreen->devPrivates[xf86FBScreenIndex].ptr;
+
+ newCallbacks = xrealloc( offman->FreeBoxesUpdateCallback,
+ sizeof(FreeBoxCallbackProcPtr) * (offman->NumCallbacks + 1));
+
+ newPrivates = xrealloc(offman->devPrivates,
+ sizeof(DevUnion) * (offman->NumCallbacks + 1));
+
+ if(!newCallbacks || !newPrivates)
+ return FALSE;
+
+ offman->FreeBoxesUpdateCallback = newCallbacks;
+ offman->devPrivates = newPrivates;
+
+ offman->FreeBoxesUpdateCallback[offman->NumCallbacks] = FreeBoxCallback;
+ offman->devPrivates[offman->NumCallbacks].ptr = devPriv;
+ offman->NumCallbacks++;
+
+ SendCallFreeBoxCallbacks(offman);
+
+ return TRUE;
+}
+
+
+static FBAreaPtr
+AllocateArea(
+ FBManagerPtr offman,
+ int w, int h,
+ int granularity,
+ MoveAreaCallbackProcPtr moveCB,
+ RemoveAreaCallbackProcPtr removeCB,
+ pointer privData
+){
+ ScreenPtr pScreen = offman->pScreen;
+ FBLinkPtr link = NULL;
+ FBAreaPtr area = NULL;
+ RegionRec NewReg;
+ int i, x = 0, num;
+ BoxPtr boxp;
+
+ if(granularity <= 1) granularity = 0;
+
+ boxp = REGION_RECTS(offman->FreeBoxes);
+ num = REGION_NUM_RECTS(offman->FreeBoxes);
+
+ /* look through the free boxes */
+ for(i = 0; i < num; i++, boxp++) {
+ x = boxp->x1;
+ if(granularity) {
+ int tmp = x % granularity;
+ if(tmp) x += (granularity - tmp);
+ }
+
+ if(((boxp->y2 - boxp->y1) < h) || ((boxp->x2 - x) < w))
+ continue;
+
+ link = xalloc(sizeof(FBLink));
+ if(!link) return NULL;
+
+ area = &(link->area);
+ link->next = offman->UsedAreas;
+ offman->UsedAreas = link;
+ offman->NumUsedAreas++;
+ break;
+ }
+
+ /* try to boot a removeable one out if we are not expendable ourselves */
+ if(!area && !removeCB) {
+ link = offman->UsedAreas;
+
+ while(link) {
+ if(!link->area.RemoveAreaCallback) {
+ link = link->next;
+ continue;
+ }
+
+ boxp = &(link->area.box);
+ x = boxp->x1;
+ if(granularity) {
+ int tmp = x % granularity;
+ if(tmp) x += (granularity - tmp);
+ }
+
+ if(((boxp->y2 - boxp->y1) < h) || ((boxp->x2 - x) < w)) {
+ link = link->next;
+ continue;
+ }
+
+ /* bye, bye */
+ (*link->area.RemoveAreaCallback)(&link->area);
+ REGION_INIT(pScreen, &NewReg, &(link->area.box), 1);
+ REGION_UNION(pScreen, offman->FreeBoxes, offman->FreeBoxes, &NewReg);
+ REGION_UNINIT(pScreen, &NewReg);
+
+ area = &(link->area);
+ break;
+ }
+ }
+
+ if(area) {
+ area->pScreen = pScreen;
+ area->granularity = granularity;
+ area->box.x1 = x;
+ area->box.x2 = x + w;
+ area->box.y1 = boxp->y1;
+ area->box.y2 = boxp->y1 + h;
+ area->MoveAreaCallback = moveCB;
+ area->RemoveAreaCallback = removeCB;
+ area->devPrivate.ptr = privData;
+
+ REGION_INIT(pScreen, &NewReg, &(area->box), 1);
+ REGION_SUBTRACT(pScreen, offman->FreeBoxes, offman->FreeBoxes, &NewReg);
+ REGION_UNINIT(pScreen, &NewReg);
+ }
+
+ return area;
+}
+
+static FBAreaPtr
+localAllocateOffscreenArea(
+ ScreenPtr pScreen,
+ int w, int h,
+ int gran,
+ MoveAreaCallbackProcPtr moveCB,
+ RemoveAreaCallbackProcPtr removeCB,
+ pointer privData
+){
+ FBManagerPtr offman;
+ FBAreaPtr area = NULL;
+
+ offman = pScreen->devPrivates[xf86FBScreenIndex].ptr;
+
+ if((area = AllocateArea(offman, w, h, gran, moveCB, removeCB, privData)))
+ SendCallFreeBoxCallbacks(offman);
+
+ return area;
+}
+
+
+static void
+localFreeOffscreenArea(FBAreaPtr area)
+{
+ FBManagerPtr offman;
+ FBLinkPtr pLink, pLinkPrev = NULL;
+ RegionRec FreedRegion;
+ ScreenPtr pScreen;
+
+ pScreen = area->pScreen;
+ offman = pScreen->devPrivates[xf86FBScreenIndex].ptr;
+
+ pLink = offman->UsedAreas;
+ if(!pLink) return;
+
+ while(&(pLink->area) != area) {
+ pLinkPrev = pLink;
+ pLink = pLink->next;
+ if(!pLink) return;
+ }
+
+ /* put the area back into the pool */
+ REGION_INIT(pScreen, &FreedRegion, &(pLink->area.box), 1);
+ REGION_UNION(pScreen, offman->FreeBoxes, offman->FreeBoxes, &FreedRegion);
+ REGION_UNINIT(pScreen, &FreedRegion);
+
+ if(pLinkPrev)
+ pLinkPrev->next = pLink->next;
+ else offman->UsedAreas = pLink->next;
+
+ xfree(pLink);
+ offman->NumUsedAreas--;
+
+ SendCallFreeBoxCallbacks(offman);
+}
+
+
+
+static Bool
+localResizeOffscreenArea(
+ FBAreaPtr resize,
+ int w, int h
+){
+ FBManagerPtr offman;
+ ScreenPtr pScreen;
+ BoxRec OrigArea;
+ RegionRec FreedReg;
+ FBAreaPtr area = NULL;
+ FBLinkPtr pLink, newLink, pLinkPrev = NULL;
+
+ pScreen = resize->pScreen;
+ offman = pScreen->devPrivates[xf86FBScreenIndex].ptr;
+
+ /* find this link */
+ if(!(pLink = offman->UsedAreas))
+ return FALSE;
+
+ while(&(pLink->area) != resize) {
+ pLinkPrev = pLink;
+ pLink = pLink->next;
+ if(!pLink) return FALSE;
+ }
+
+ OrigArea.x1 = resize->box.x1;
+ OrigArea.x2 = resize->box.x2;
+ OrigArea.y1 = resize->box.y1;
+ OrigArea.y2 = resize->box.y2;
+
+ /* if it's smaller, this is easy */
+
+ if((w <= (resize->box.x2 - resize->box.x1)) &&
+ (h <= (resize->box.y2 - resize->box.y1))) {
+ RegionRec NewReg;
+
+ resize->box.x2 = resize->box.x1 + w;
+ resize->box.y2 = resize->box.y1 + h;
+
+ if((resize->box.y2 == OrigArea.y2) &&
+ (resize->box.x2 == OrigArea.x2))
+ return TRUE;
+
+ REGION_INIT(pScreen, &FreedReg, &OrigArea, 1);
+ REGION_INIT(pScreen, &NewReg, &(resize->box), 1);
+ REGION_SUBTRACT(pScreen, &FreedReg, &FreedReg, &NewReg);
+ REGION_UNION(pScreen, offman->FreeBoxes, offman->FreeBoxes, &FreedReg);
+ REGION_UNINIT(pScreen, &FreedReg);
+ REGION_UNINIT(pScreen, &NewReg);
+
+ SendCallFreeBoxCallbacks(offman);
+
+ return TRUE;
+ }
+
+
+ /* otherwise we remove the old region */
+
+ REGION_INIT(pScreen, &FreedReg, &OrigArea, 1);
+ REGION_UNION(pScreen, offman->FreeBoxes, offman->FreeBoxes, &FreedReg);
+
+ /* remove the old link */
+ if(pLinkPrev)
+ pLinkPrev->next = pLink->next;
+ else offman->UsedAreas = pLink->next;
+
+ /* and try to add a new one */
+
+ if((area = AllocateArea(offman, w, h, resize->granularity,
+ resize->MoveAreaCallback, resize->RemoveAreaCallback,
+ resize->devPrivate.ptr))) {
+
+ /* copy data over to our link and replace the new with old */
+ memcpy(resize, area, sizeof(FBArea));
+
+ pLinkPrev = NULL;
+ newLink = offman->UsedAreas;
+
+ while(&(newLink->area) != area) {
+ pLinkPrev = newLink;
+ newLink = newLink->next;
+ }
+
+ if(pLinkPrev)
+ pLinkPrev->next = newLink->next;
+ else offman->UsedAreas = newLink->next;
+
+ pLink->next = offman->UsedAreas;
+ offman->UsedAreas = pLink;
+
+ xfree(newLink);
+
+ /* AllocateArea added one but we really only exchanged one */
+ offman->NumUsedAreas--;
+ } else {
+ /* reinstate the old region */
+ REGION_SUBTRACT(pScreen, offman->FreeBoxes, offman->FreeBoxes, &FreedReg);
+ REGION_UNINIT(pScreen, &FreedReg);
+
+ pLink->next = offman->UsedAreas;
+ offman->UsedAreas = pLink;
+ return FALSE;
+ }
+
+
+ REGION_UNINIT(pScreen, &FreedReg);
+
+ SendCallFreeBoxCallbacks(offman);
+
+ return TRUE;
+}
+
+static Bool
+localQueryLargestOffscreenArea(
+ ScreenPtr pScreen,
+ int *width, int *height,
+ int granularity,
+ int preferences,
+ int severity
+){
+ FBManagerPtr offman;
+ RegionPtr newRegion = NULL;
+ BoxPtr pbox;
+ int nbox;
+ int x, w, h, area, oldArea;
+
+ *width = *height = oldArea = 0;
+
+ if(granularity <= 1) granularity = 0;
+
+ if((preferences < 0) || (preferences > 3))
+ return FALSE;
+
+ offman = pScreen->devPrivates[xf86FBScreenIndex].ptr;
+
+ if(severity < 0) severity = 0;
+ if(severity > 2) severity = 2;
+
+ switch(severity) {
+ case 2:
+ if(offman->NumUsedAreas) {
+ FBLinkPtr pLink;
+ RegionRec tmpRegion;
+ newRegion = REGION_CREATE(pScreen, NULL, 1);
+ REGION_COPY(pScreen, newRegion, offman->InitialBoxes);
+ pLink = offman->UsedAreas;
+
+ while(pLink) {
+ if(!pLink->area.RemoveAreaCallback) {
+ REGION_INIT(pScreen, &tmpRegion, &(pLink->area.box), 1);
+ REGION_SUBTRACT(pScreen, newRegion, newRegion, &tmpRegion);
+ REGION_UNINIT(pScreen, &tmpRegion);
+ }
+ pLink = pLink->next;
+ }
+
+ nbox = REGION_NUM_RECTS(newRegion);
+ pbox = REGION_RECTS(newRegion);
+ break;
+ }
+ case 1:
+ if(offman->NumUsedAreas) {
+ FBLinkPtr pLink;
+ RegionRec tmpRegion;
+ newRegion = REGION_CREATE(pScreen, NULL, 1);
+ REGION_COPY(pScreen, newRegion, offman->FreeBoxes);
+ pLink = offman->UsedAreas;
+
+ while(pLink) {
+ if(pLink->area.RemoveAreaCallback) {
+ REGION_INIT(pScreen, &tmpRegion, &(pLink->area.box), 1);
+ REGION_APPEND(pScreen, newRegion, &tmpRegion);
+ REGION_UNINIT(pScreen, &tmpRegion);
+ }
+ pLink = pLink->next;
+ }
+
+ nbox = REGION_NUM_RECTS(newRegion);
+ pbox = REGION_RECTS(newRegion);
+ break;
+ }
+ default:
+ nbox = REGION_NUM_RECTS(offman->FreeBoxes);
+ pbox = REGION_RECTS(offman->FreeBoxes);
+ break;
+ }
+
+ while(nbox--) {
+ x = pbox->x1;
+ if(granularity) {
+ int tmp = x % granularity;
+ if(tmp) x += (granularity - tmp);
+ }
+
+ w = pbox->x2 - x;
+ h = pbox->y2 - pbox->y1;
+ area = w * h;
+
+ if(w > 0) {
+ Bool gotIt = FALSE;
+ switch(preferences) {
+ case FAVOR_AREA_THEN_WIDTH:
+ if((area > oldArea) || ((area == oldArea) && (w > *width)))
+ gotIt = TRUE;
+ break;
+ case FAVOR_AREA_THEN_HEIGHT:
+ if((area > oldArea) || ((area == oldArea) && (h > *height)))
+ gotIt = TRUE;
+ break;
+ case FAVOR_WIDTH_THEN_AREA:
+ if((w > *width) || ((w == *width) && (area > oldArea)))
+ gotIt = TRUE;
+ break;
+ case FAVOR_HEIGHT_THEN_AREA:
+ if((h > *height) || ((h == *height) && (area > oldArea)))
+ gotIt = TRUE;
+ break;
+ }
+ if(gotIt) {
+ *width = w;
+ *height = h;
+ oldArea = area;
+ }
+ }
+ pbox++;
+ }
+
+ if(newRegion)
+ REGION_DESTROY(pScreen, newRegion);
+
+ return TRUE;
+}
+
+static Bool
+localPurgeUnlockedOffscreenAreas(ScreenPtr pScreen)
+{
+ FBManagerPtr offman;
+ FBLinkPtr pLink, tmp, pPrev = NULL;
+ RegionRec FreedRegion;
+ Bool anyUsed = FALSE;
+
+ offman = pScreen->devPrivates[xf86FBScreenIndex].ptr;
+
+ pLink = offman->UsedAreas;
+ if(!pLink) return TRUE;
+
+ while(pLink) {
+ if(pLink->area.RemoveAreaCallback) {
+ (*pLink->area.RemoveAreaCallback)(&pLink->area);
+
+ REGION_INIT(pScreen, &FreedRegion, &(pLink->area.box), 1);
+ REGION_APPEND(pScreen, offman->FreeBoxes, &FreedRegion);
+ REGION_UNINIT(pScreen, &FreedRegion);
+
+ if(pPrev)
+ pPrev->next = pLink->next;
+ else offman->UsedAreas = pLink->next;
+
+ tmp = pLink;
+ pLink = pLink->next;
+ xfree(tmp);
+ offman->NumUsedAreas--;
+ anyUsed = TRUE;
+ } else {
+ pPrev = pLink;
+ pLink = pLink->next;
+ }
+ }
+
+ if(anyUsed) {
+ REGION_VALIDATE(pScreen, offman->FreeBoxes, &anyUsed);
+ SendCallFreeBoxCallbacks(offman);
+ }
+
+ return TRUE;
+}
+
+static void
+LinearMoveCBWrapper(FBAreaPtr from, FBAreaPtr to)
+{
+ /* this will never get called */
+}
+
+static void
+LinearRemoveCBWrapper(FBAreaPtr area)
+{
+ FBManagerPtr offman;
+ FBLinearLinkPtr pLink, pLinkPrev = NULL;
+ ScreenPtr pScreen = area->pScreen;
+
+ offman = pScreen->devPrivates[xf86FBScreenIndex].ptr;
+
+ pLink = offman->LinearAreas;
+ if(!pLink) return;
+
+ while(pLink->area != area) {
+ pLinkPrev = pLink;
+ pLink = pLink->next;
+ if(!pLink) return;
+ }
+
+ /* give the user the callback it is expecting */
+ (*pLink->linear.RemoveLinearCallback)(&(pLink->linear));
+
+ if(pLinkPrev)
+ pLinkPrev->next = pLink->next;
+ else offman->LinearAreas = pLink->next;
+
+ xfree(pLink);
+}
+
+
+static FBLinearPtr
+localAllocateOffscreenLinear(
+ ScreenPtr pScreen,
+ int length,
+ int gran,
+ MoveLinearCallbackProcPtr moveCB,
+ RemoveLinearCallbackProcPtr removeCB,
+ pointer privData
+){
+ FBManagerPtr offman;
+ FBLinearLinkPtr link;
+ FBAreaPtr area;
+ FBLinearPtr linear = NULL;
+ BoxPtr extents;
+ int w, h, pitch;
+
+ offman = pScreen->devPrivates[xf86FBScreenIndex].ptr;
+
+ if(!(link = xalloc(sizeof(FBLinearLink))))
+ return NULL;
+
+#if 0
+ if(we have linear heap space) {
+ if(able to allocate some) {
+ link->area = NULL;
+ link->next = offman->LinearAreas;
+ offman->LinearAreas = link;
+ linear = link->linear;
+ linear->pScreen = pScreen;
+ linear->size = length;
+ linear->offset = ????;
+ linear->granularity = gran;
+ linear->MoveLinearAreaCallback = moveCB;
+ linear->RemoveLinearAreaCallback = removeCB;
+ linear->devPrivate.ptr = privData;
+ return linear;
+ } /* else fallthrough */
+ }
+#endif
+
+ extents = REGION_EXTENTS(pScreen, offman->InitialBoxes);
+ pitch = extents->x2 - extents->x1;
+
+ if(gran && ((gran > pitch) || (pitch % gran))) {
+ /* we can't match the specified alignment with XY allocations */
+ xfree(link);
+ return NULL;
+ }
+
+ if(length < pitch) { /* special case */
+ w = length;
+ h = 1;
+ } else {
+ w = pitch;
+ h = (length + pitch - 1) / pitch;
+ }
+
+ if((area = localAllocateOffscreenArea(pScreen, w, h, gran,
+ moveCB ? LinearMoveCBWrapper : NULL,
+ removeCB ? LinearRemoveCBWrapper : NULL,
+ privData)))
+ {
+ link->area = area;
+ link->next = offman->LinearAreas;
+ offman->LinearAreas = link;
+ linear = &(link->linear);
+ linear->pScreen = pScreen;
+ linear->size = h * w;
+ linear->offset = (pitch * area->box.y1) + area->box.x1;
+ linear->granularity = gran;
+ linear->MoveLinearCallback = moveCB;
+ linear->RemoveLinearCallback = removeCB;
+ linear->devPrivate.ptr = privData;
+ } else
+ xfree(link);
+
+ return linear;
+}
+
+
+static void
+localFreeOffscreenLinear(FBLinearPtr linear)
+{
+ FBManagerPtr offman;
+ FBLinearLinkPtr pLink, pLinkPrev = NULL;
+ ScreenPtr pScreen = linear->pScreen;
+
+ offman = pScreen->devPrivates[xf86FBScreenIndex].ptr;
+
+ pLink = offman->LinearAreas;
+ if(!pLink) return;
+
+ while(&(pLink->linear) != linear) {
+ pLinkPrev = pLink;
+ pLink = pLink->next;
+ if(!pLink) return;
+ }
+
+ if(pLink->area) { /* really an XY area */
+ localFreeOffscreenArea(pLink->area);
+ } else {
+ /* free the linear area */
+ }
+
+ if(pLinkPrev)
+ pLinkPrev->next = pLink->next;
+ else offman->LinearAreas = pLink->next;
+
+ xfree(pLink);
+}
+
+
+static Bool
+localResizeOffscreenLinear(FBLinearPtr resize, int length)
+{
+ FBManagerPtr offman;
+ FBLinearLinkPtr pLink, pLinkPrev = NULL;
+ ScreenPtr pScreen = resize->pScreen;
+
+ offman = pScreen->devPrivates[xf86FBScreenIndex].ptr;
+
+ pLink = offman->LinearAreas;
+ if(!pLink) return FALSE;
+
+ while(&(pLink->linear) != resize) {
+ pLinkPrev = pLink;
+ pLink = pLink->next;
+ if(!pLink) return FALSE;
+ }
+
+ /* This could actually be alot smarter and try to move allocations
+ from XY to linear when available. For now if it was XY, we keep
+ it XY */
+
+ if(pLink->area) { /* really an XY area */
+ BoxPtr extents;
+ int pitch, w, h;
+
+ extents = REGION_EXTENTS(pScreen, offman->InitialBoxes);
+ pitch = extents->x2 - extents->x1;
+
+ if(length < pitch) { /* special case */
+ w = length;
+ h = 1;
+ } else {
+ w = pitch;
+ h = (length + pitch - 1) / pitch;
+ }
+
+ if(localResizeOffscreenArea(pLink->area, w, h)) {
+ resize->size = h * w;
+ resize->offset = (pitch * pLink->area->box.y1) + pLink->area->box.x1;
+ return TRUE;
+ }
+ } else {
+ /* resize the linear area */
+ }
+
+ return FALSE;
+}
+
+
+static Bool
+localQueryLargestOffscreenLinear(
+ ScreenPtr pScreen,
+ int *size,
+ int gran,
+ int priority
+)
+{
+ int w, h;
+
+ *size = 0;
+
+ /* for now, we only look at XY space */
+ if(localQueryLargestOffscreenArea(pScreen, &w, &h, gran,
+ FAVOR_WIDTH_THEN_AREA, priority))
+ {
+ FBManagerPtr offman;
+ BoxPtr extents;
+
+ offman = pScreen->devPrivates[xf86FBScreenIndex].ptr;
+ extents = REGION_EXTENTS(pScreen, offman->InitialBoxes);
+ if((extents->x2 - extents->x1) == w)
+ *size = w * h;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+
+static FBManagerFuncs xf86FBManFuncs = {
+ localAllocateOffscreenArea,
+ localFreeOffscreenArea,
+ localResizeOffscreenArea,
+ localQueryLargestOffscreenArea,
+ localRegisterFreeBoxCallback,
+ localAllocateOffscreenLinear,
+ localFreeOffscreenLinear,
+ localResizeOffscreenLinear,
+ localQueryLargestOffscreenLinear,
+ localPurgeUnlockedOffscreenAreas
+ };
+
+
+static Bool
+xf86FBCloseScreen (int i, ScreenPtr pScreen)
+{
+ FBLinkPtr pLink, tmp;
+ FBLinearLinkPtr pLinearLink, tmp2;
+ FBManagerPtr offman =
+ (FBManagerPtr) pScreen->devPrivates[xf86FBScreenIndex].ptr;
+
+
+ pScreen->CloseScreen = offman->CloseScreen;
+
+ pLink = offman->UsedAreas;
+ while(pLink) {
+ tmp = pLink;
+ pLink = pLink->next;
+ xfree(tmp);
+ }
+
+ pLinearLink = offman->LinearAreas;
+ while(pLinearLink) {
+ tmp2 = pLinearLink;
+ pLinearLink = pLinearLink->next;
+ xfree(tmp2);
+ }
+
+ REGION_DESTROY(pScreen, offman->InitialBoxes);
+ REGION_DESTROY(pScreen, offman->FreeBoxes);
+
+ xfree(offman->FreeBoxesUpdateCallback);
+ xfree(offman->devPrivates);
+ xfree(offman);
+ pScreen->devPrivates[xf86FBScreenIndex].ptr = NULL;
+
+ return (*pScreen->CloseScreen) (i, pScreen);
+}
+
+Bool
+xf86InitFBManager(
+ ScreenPtr pScreen,
+ BoxPtr FullBox
+){
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ RegionRec ScreenRegion;
+ RegionRec FullRegion;
+ BoxRec ScreenBox;
+ Bool ret;
+
+ ScreenBox.x1 = 0;
+ ScreenBox.y1 = 0;
+ ScreenBox.x2 = pScrn->virtualX;
+ ScreenBox.y2 = pScrn->virtualY;
+
+ if((FullBox->x1 > ScreenBox.x1) || (FullBox->y1 > ScreenBox.y1) ||
+ (FullBox->x2 < ScreenBox.x2) || (FullBox->y2 < ScreenBox.y2)) {
+ return FALSE;
+ }
+
+ if (FullBox->y2 < FullBox->y1) return FALSE;
+ if (FullBox->x2 < FullBox->x2) return FALSE;
+
+ REGION_INIT(pScreen, &ScreenRegion, &ScreenBox, 1);
+ REGION_INIT(pScreen, &FullRegion, FullBox, 1);
+
+ REGION_SUBTRACT(pScreen, &FullRegion, &FullRegion, &ScreenRegion);
+
+ ret = xf86InitFBManagerRegion(pScreen, &FullRegion);
+
+ REGION_UNINIT(pScreen, &ScreenRegion);
+ REGION_UNINIT(pScreen, &FullRegion);
+
+ return ret;
+}
+
+Bool
+xf86InitFBManagerArea(
+ ScreenPtr pScreen,
+ int PixelArea,
+ int Verbosity
+)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ xRectangle Rect[3];
+ RegionPtr pRegion, pScreenRegion;
+ int nRect;
+ Bool ret = FALSE;
+
+ if (PixelArea < (pScrn->displayWidth * pScrn->virtualY))
+ return FALSE;
+
+ Rect[0].x = Rect[0].y = 0;
+ Rect[0].width = pScrn->displayWidth;
+ Rect[0].height = PixelArea / pScrn->displayWidth;
+ nRect = 1;
+
+ /* Add a possible partial scanline */
+ if ((Rect[1].height = Rect[1].width = PixelArea % pScrn->displayWidth)) {
+ Rect[1].x = 0;
+ Rect[1].y = Rect[0].height;
+ Rect[1].height = 1;
+ nRect++;
+ }
+
+ /* Factor out virtual resolution */
+ pRegion = RECTS_TO_REGION(pScreen, nRect, Rect, 0);
+ if (pRegion) {
+ if (!REGION_NAR(pRegion)) {
+ Rect[2].x = Rect[2].y = 0;
+ Rect[2].width = pScrn->virtualX;
+ Rect[2].height = pScrn->virtualY;
+
+ pScreenRegion = RECTS_TO_REGION(pScreen, 1, &Rect[2], 0);
+ if (pScreenRegion) {
+ if (!REGION_NAR(pScreenRegion)) {
+ REGION_SUBTRACT(pScreen, pRegion, pRegion, pScreenRegion);
+
+ ret = xf86InitFBManagerRegion(pScreen, pRegion);
+
+ if (ret && xf86GetVerbosity() >= Verbosity) {
+ int scrnIndex = pScrn->scrnIndex;
+
+ xf86DrvMsgVerb(scrnIndex, X_INFO, Verbosity,
+ "Largest offscreen areas (with overlaps):\n");
+
+ if (Rect[2].width < Rect[0].width) {
+ xf86DrvMsgVerb(scrnIndex, X_INFO, Verbosity,
+ "\t%d x %d rectangle at %d,0\n",
+ Rect[0].width - Rect[2].width,
+ Rect[0].height,
+ Rect[2].width);
+ }
+ if (Rect[2].width < Rect[1].width) {
+ xf86DrvMsgVerb(scrnIndex, X_INFO, Verbosity,
+ "\t%d x %d rectangle at %d,0\n",
+ Rect[1].width - Rect[2].width,
+ Rect[0].height + Rect[1].height,
+ Rect[2].width);
+ }
+ if (Rect[2].height < Rect[0].height) {
+ xf86DrvMsgVerb(scrnIndex, X_INFO, Verbosity,
+ "\t%d x %d rectangle at 0,%d\n",
+ Rect[0].width,
+ Rect[0].height - Rect[2].height,
+ Rect[2].height);
+ }
+ if (Rect[1].height) {
+ xf86DrvMsgVerb(scrnIndex, X_INFO, Verbosity,
+ "\t%d x %d rectangle at 0,%d\n",
+ Rect[1].width,
+ Rect[0].height - Rect[2].height +
+ Rect[1].height,
+ Rect[2].height);
+ }
+ }
+ }
+
+ REGION_DESTROY(pScreen, pScreenRegion);
+ }
+ }
+
+ REGION_DESTROY(pScreen, pRegion);
+ }
+
+ return ret;
+}
+
+Bool
+xf86InitFBManagerRegion(
+ ScreenPtr pScreen,
+ RegionPtr FullRegion
+){
+ FBManagerPtr offman;
+
+ if(REGION_NIL(FullRegion))
+ return FALSE;
+
+ if(xf86FBGeneration != serverGeneration) {
+ if((xf86FBScreenIndex = AllocateScreenPrivateIndex()) < 0)
+ return FALSE;
+ xf86FBGeneration = serverGeneration;
+ }
+
+ if(!xf86RegisterOffscreenManager(pScreen, &xf86FBManFuncs))
+ return FALSE;
+
+ offman = xalloc(sizeof(FBManager));
+ if(!offman) return FALSE;
+
+ pScreen->devPrivates[xf86FBScreenIndex].ptr = (pointer)offman;
+
+ offman->CloseScreen = pScreen->CloseScreen;
+ pScreen->CloseScreen = xf86FBCloseScreen;
+
+ offman->InitialBoxes = REGION_CREATE(pScreen, NULL, 1);
+ offman->FreeBoxes = REGION_CREATE(pScreen, NULL, 1);
+
+ REGION_COPY(pScreen, offman->InitialBoxes, FullRegion);
+ REGION_COPY(pScreen, offman->FreeBoxes, FullRegion);
+
+ offman->pScreen = pScreen;
+ offman->UsedAreas = NULL;
+ offman->LinearAreas = NULL;
+ offman->NumUsedAreas = 0;
+ offman->NumCallbacks = 0;
+ offman->FreeBoxesUpdateCallback = NULL;
+ offman->devPrivates = NULL;
+
+ return TRUE;
+}
+
+
+
+/* This is an implementation specific function and should
+ disappear after the next release. People should use the
+ real linear functions instead */
+
+FBAreaPtr
+xf86AllocateLinearOffscreenArea (
+ ScreenPtr pScreen,
+ int length,
+ int gran,
+ MoveAreaCallbackProcPtr moveCB,
+ RemoveAreaCallbackProcPtr removeCB,
+ pointer privData
+){
+ FBManagerFuncsPtr funcs;
+ FBManagerPtr offman;
+ BoxPtr extents;
+ int w, h;
+
+ if(xf86FBMangerIndex < 0)
+ return NULL;
+ if(!(funcs = (FBManagerFuncsPtr)pScreen->devPrivates[xf86FBMangerIndex].ptr))
+ return NULL;
+
+ offman = pScreen->devPrivates[xf86FBScreenIndex].ptr;
+
+ extents = REGION_EXTENTS(pScreen, offman->InitialBoxes);
+ w = extents->x2 - extents->x1;
+
+ if(gran && ((gran > w) || (w % gran))) {
+ /* we can't match the specified alignment with XY allocations */
+ return NULL;
+ }
+
+ if(length <= w) { /* special case */
+ h = 1;
+ w = length;
+ } else {
+ h = (length + w - 1) / w;
+ }
+
+ return (*funcs->AllocateOffscreenArea)(
+ pScreen, w, h, gran, moveCB, removeCB, privData);
+}
diff --git a/hw/xfree86/common/xf86fbman.h b/hw/xfree86/common/xf86fbman.h
new file mode 100644
index 000000000..673c7bc33
--- /dev/null
+++ b/hw/xfree86/common/xf86fbman.h
@@ -0,0 +1,193 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86fbman.h,v 1.12 2001/08/28 16:55:09 tsi Exp $ */
+
+#ifndef _XF86FBMAN_H
+#define _XF86FBMAN_H
+
+
+#include "scrnintstr.h"
+#include "regionstr.h"
+
+
+#define FAVOR_AREA_THEN_WIDTH 0
+#define FAVOR_AREA_THEN_HEIGHT 1
+#define FAVOR_WIDTH_THEN_AREA 2
+#define FAVOR_HEIGHT_THEN_AREA 3
+
+#define PRIORITY_LOW 0
+#define PRIORITY_NORMAL 1
+#define PRIORITY_EXTREME 2
+
+
+typedef struct _FBArea {
+ ScreenPtr pScreen;
+ BoxRec box;
+ int granularity;
+ void (*MoveAreaCallback)(struct _FBArea*, struct _FBArea*);
+ void (*RemoveAreaCallback)(struct _FBArea*);
+ DevUnion devPrivate;
+} FBArea, *FBAreaPtr;
+
+typedef struct _FBLinear {
+ ScreenPtr pScreen;
+ int size;
+ int offset;
+ int granularity;
+ void (*MoveLinearCallback)(struct _FBLinear*, struct _FBLinear*);
+ void (*RemoveLinearCallback)(struct _FBLinear*);
+ DevUnion devPrivate;
+} FBLinear, *FBLinearPtr;
+
+typedef void (*FreeBoxCallbackProcPtr)(ScreenPtr, RegionPtr, pointer);
+typedef void (*MoveAreaCallbackProcPtr)(FBAreaPtr, FBAreaPtr);
+typedef void (*RemoveAreaCallbackProcPtr)(FBAreaPtr);
+
+typedef void (*MoveLinearCallbackProcPtr)(FBLinearPtr, FBLinearPtr);
+typedef void (*RemoveLinearCallbackProcPtr)(FBLinearPtr);
+
+
+typedef struct {
+ FBAreaPtr (*AllocateOffscreenArea)(
+ ScreenPtr pScreen,
+ int w, int h,
+ int granularity,
+ MoveAreaCallbackProcPtr moveCB,
+ RemoveAreaCallbackProcPtr removeCB,
+ pointer privData);
+ void (*FreeOffscreenArea)(FBAreaPtr area);
+ Bool (*ResizeOffscreenArea)(FBAreaPtr area, int w, int h);
+ Bool (*QueryLargestOffscreenArea)(
+ ScreenPtr pScreen,
+ int *width, int *height,
+ int granularity,
+ int preferences,
+ int priority);
+ Bool (*RegisterFreeBoxCallback)(
+ ScreenPtr pScreen,
+ FreeBoxCallbackProcPtr FreeBoxCallback,
+ pointer devPriv);
+/* linear functions */
+ FBLinearPtr (*AllocateOffscreenLinear)(
+ ScreenPtr pScreen,
+ int size,
+ int granularity,
+ MoveLinearCallbackProcPtr moveCB,
+ RemoveLinearCallbackProcPtr removeCB,
+ pointer privData);
+ void (*FreeOffscreenLinear)(FBLinearPtr area);
+ Bool (*ResizeOffscreenLinear)(FBLinearPtr area, int size);
+ Bool (*QueryLargestOffscreenLinear)(
+ ScreenPtr pScreen,
+ int *size,
+ int granularity,
+ int priority);
+ Bool (*PurgeOffscreenAreas) (ScreenPtr);
+} FBManagerFuncs, *FBManagerFuncsPtr;
+
+
+Bool xf86RegisterOffscreenManager(
+ ScreenPtr pScreen,
+ FBManagerFuncsPtr funcs
+);
+
+Bool
+xf86InitFBManagerRegion(
+ ScreenPtr pScreen,
+ RegionPtr ScreenRegion
+);
+
+Bool
+xf86InitFBManagerArea(
+ ScreenPtr pScreen,
+ int PixalArea,
+ int Verbosity
+);
+
+Bool
+xf86InitFBManager(
+ ScreenPtr pScreen,
+ BoxPtr FullBox
+);
+
+Bool
+xf86FBManagerRunning(
+ ScreenPtr pScreen
+);
+
+FBAreaPtr
+xf86AllocateOffscreenArea (
+ ScreenPtr pScreen,
+ int w, int h,
+ int granularity,
+ MoveAreaCallbackProcPtr moveCB,
+ RemoveAreaCallbackProcPtr removeCB,
+ pointer privData
+);
+
+FBAreaPtr
+xf86AllocateLinearOffscreenArea (
+ ScreenPtr pScreen,
+ int length,
+ int granularity,
+ MoveAreaCallbackProcPtr moveCB,
+ RemoveAreaCallbackProcPtr removeCB,
+ pointer privData
+);
+
+FBLinearPtr
+xf86AllocateOffscreenLinear (
+ ScreenPtr pScreen,
+ int length,
+ int granularity,
+ MoveLinearCallbackProcPtr moveCB,
+ RemoveLinearCallbackProcPtr removeCB,
+ pointer privData
+);
+
+void xf86FreeOffscreenArea(FBAreaPtr area);
+void xf86FreeOffscreenLinear(FBLinearPtr area);
+
+Bool
+xf86ResizeOffscreenArea(
+ FBAreaPtr resize,
+ int w, int h
+);
+
+Bool
+xf86ResizeOffscreenLinear(
+ FBLinearPtr resize,
+ int size
+);
+
+
+Bool
+xf86RegisterFreeBoxCallback(
+ ScreenPtr pScreen,
+ FreeBoxCallbackProcPtr FreeBoxCallback,
+ pointer devPriv
+);
+
+Bool
+xf86PurgeUnlockedOffscreenAreas(
+ ScreenPtr pScreen
+);
+
+
+Bool
+xf86QueryLargestOffscreenArea(
+ ScreenPtr pScreen,
+ int *width, int *height,
+ int granularity,
+ int preferences,
+ int priority
+);
+
+Bool
+xf86QueryLargestOffscreenLinear(
+ ScreenPtr pScreen,
+ int *size,
+ int granularity,
+ int priority
+);
+
+
+#endif /* _XF86FBMAN_H */
diff --git a/hw/xfree86/common/xf86isaBus.c b/hw/xfree86/common/xf86isaBus.c
new file mode 100644
index 000000000..cfe6ed000
--- /dev/null
+++ b/hw/xfree86/common/xf86isaBus.c
@@ -0,0 +1,115 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86isaBus.c,v 3.5 2000/12/06 15:35:11 eich Exp $ */
+
+/*
+ * Copyright (c) 1997-1999 by The XFree86 Project, Inc.
+ */
+
+/*
+ * This file contains the interfaces to the bus-specific code
+ */
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "X.h"
+#include "os.h"
+#include "xf86.h"
+#include "xf86Priv.h"
+#include "xf86Resources.h"
+
+#include "xf86Bus.h"
+
+#define XF86_OS_PRIVS
+#define NEED_OS_RAC_PROTOS
+#include "xf86_OSproc.h"
+
+#include "xf86RAC.h"
+
+Bool isaSlotClaimed = FALSE;
+
+/*
+ * If the slot requested is already in use, return FALSE.
+ * Otherwise, claim the slot for the screen requesting it.
+ */
+
+int
+xf86ClaimIsaSlot(DriverPtr drvp, int chipset, GDevPtr dev, Bool active)
+{
+ EntityPtr p;
+ BusAccPtr pbap = xf86BusAccInfo;
+ int num;
+
+ num = xf86AllocateEntity();
+ p = xf86Entities[num];
+ p->driver = drvp;
+ p->chipset = chipset;
+ p->busType = BUS_ISA;
+ p->active = active;
+ p->inUse = FALSE;
+ xf86AddDevToEntity(num, dev);
+ p->access = xnfcalloc(1,sizeof(EntityAccessRec));
+ p->access->fallback = &AccessNULL;
+ p->access->pAccess = &AccessNULL;
+ p->busAcc = NULL;
+ while (pbap) {
+ if (pbap->type == BUS_ISA)
+ p->busAcc = pbap;
+ pbap = pbap->next;
+ }
+ isaSlotClaimed = TRUE;
+ return num;
+}
+
+/*
+ * Get the list of ISA "slots" claimed by a screen
+ *
+ * Note: The ISA implementation here assumes that only one ISA "slot" type
+ * can be claimed by any one screen. That means a return value other than
+ * 0 or 1 isn't useful.
+ */
+int
+xf86GetIsaInfoForScreen(int scrnIndex)
+{
+ int num = 0;
+ int i;
+ EntityPtr p;
+
+ for (i = 0; i < xf86Screens[scrnIndex]->numEntities; i++) {
+ p = xf86Entities[xf86Screens[scrnIndex]->entityList[i]];
+ if (p->busType == BUS_ISA) {
+ num++;
+ }
+ }
+ return num;
+}
+
+/*
+ * Parse a BUS ID string, and return True if it is a ISA bus id.
+ */
+
+Bool
+xf86ParseIsaBusString(const char *busID)
+{
+ /*
+ * The format assumed to be "isa" or "isa:"
+ */
+ return (StringToBusType(busID,NULL) == BUS_ISA);
+}
+
+
+/*
+ * xf86IsPrimaryIsa() -- return TRUE if primary device
+ * is ISA.
+ */
+
+Bool
+xf86IsPrimaryIsa(void)
+{
+ return ( primaryBus.type == BUS_ISA );
+}
+
+void
+isaConvertRange2Host(resRange *pRange)
+{
+ return;
+}
diff --git a/hw/xfree86/common/xf86noBus.c b/hw/xfree86/common/xf86noBus.c
new file mode 100644
index 000000000..a9efcdbc4
--- /dev/null
+++ b/hw/xfree86/common/xf86noBus.c
@@ -0,0 +1,48 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86noBus.c,v 1.1 2002/09/18 08:54:55 eich Exp $ */
+
+/*
+ * Copyright (c) 2000 by The XFree86 Project, Inc.
+ */
+
+/*
+ * This file contains the interfaces to the bus-specific code
+ */
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "X.h"
+#include "os.h"
+#include "xf86.h"
+#include "xf86Priv.h"
+#include "xf86Resources.h"
+
+#include "xf86Bus.h"
+
+#define XF86_OS_PRIVS
+#define NEED_OS_RAC_PROTOS
+#include "xf86_OSproc.h"
+
+#include "xf86RAC.h"
+
+int
+xf86ClaimNoSlot(DriverPtr drvp, int chipset, GDevPtr dev, Bool active)
+{
+ EntityPtr p;
+ int num;
+
+ num = xf86AllocateEntity();
+ p = xf86Entities[num];
+ p->driver = drvp;
+ p->chipset = 0;
+ p->busType = BUS_NONE;
+ p->active = active;
+ p->inUse = FALSE;
+ xf86AddDevToEntity(num, dev);
+ p->access = xnfcalloc(1,sizeof(EntityAccessRec));
+ p->access->fallback = &AccessNULL;
+ p->access->pAccess = &AccessNULL;
+ p->busAcc = NULL;
+
+ return num;
+}
diff --git a/hw/xfree86/common/xf86pciBus.c b/hw/xfree86/common/xf86pciBus.c
new file mode 100644
index 000000000..c40fc1016
--- /dev/null
+++ b/hw/xfree86/common/xf86pciBus.c
@@ -0,0 +1,3493 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86pciBus.c,v 3.68.2.1 2003/05/06 17:00:43 tsi Exp $ */
+/*
+ * Copyright (c) 1997-2002 by The XFree86 Project, Inc.
+ */
+
+/*
+ * This file contains the interfaces to the bus-specific code
+ */
+#define INCLUDE_DEPRECATED 1
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "X.h"
+#include "os.h"
+#include "Pci.h"
+#include "xf86.h"
+#include "xf86Priv.h"
+#include "xf86Resources.h"
+
+/* Bus-specific headers */
+#include "xf86PciData.h"
+
+#include "xf86Bus.h"
+
+#define XF86_OS_PRIVS
+#define NEED_OS_RAC_PROTOS
+#include "xf86_OSproc.h"
+
+#include "xf86RAC.h"
+
+/* Bus-specific globals */
+Bool pciSlotClaimed = FALSE;
+pciConfigPtr *xf86PciInfo = NULL; /* Full PCI probe info */
+pciVideoPtr *xf86PciVideoInfo = NULL; /* PCI probe for video hw */
+pciAccPtr * xf86PciAccInfo = NULL; /* PCI access related */
+
+/* pcidata globals */
+ScanPciSetupProcPtr xf86SetupPciIds = NULL;
+ScanPciCloseProcPtr xf86ClosePciIds = NULL;
+ScanPciFindByDeviceProcPtr xf86FindPciNamesByDevice = NULL;
+ScanPciFindBySubsysProcPtr xf86FindPciNamesBySubsys = NULL;
+ScanPciFindClassBySubsysProcPtr xf86FindPciClassBySubsys = NULL;
+ScanPciFindClassByDeviceProcPtr xf86FindPciClassByDevice = NULL;
+
+static resPtr pciAvoidRes = NULL;
+
+/* PCI buses */
+static PciBusPtr xf86PciBus = NULL;
+/* Bus-specific probe/sorting functions */
+
+/* PCI classes that get included in xf86PciVideoInfo */
+#define PCIINFOCLASSES(b,s) \
+ (((b) == PCI_CLASS_PREHISTORIC) || \
+ ((b) == PCI_CLASS_DISPLAY) || \
+ ((b) == PCI_CLASS_MULTIMEDIA && (s) == PCI_SUBCLASS_MULTIMEDIA_VIDEO) || \
+ ((b) == PCI_CLASS_PROCESSOR && (s) == PCI_SUBCLASS_PROCESSOR_COPROC))
+
+/*
+ * PCI classes that have messages printed always. The others are only
+ * have a message printed when the vendor/dev IDs are recognised.
+ */
+#define PCIALWAYSPRINTCLASSES(b,s) \
+ (((b) == PCI_CLASS_PREHISTORIC && (s) == PCI_SUBCLASS_PREHISTORIC_VGA) || \
+ ((b) == PCI_CLASS_DISPLAY) || \
+ ((b) == PCI_CLASS_MULTIMEDIA && (s) == PCI_SUBCLASS_MULTIMEDIA_VIDEO))
+
+/*
+ * PCI classes for which potentially destructive checking of the map sizes
+ * may be done. Any classes where this may be unsafe should be omitted
+ * from this list.
+ */
+#define PCINONSYSTEMCLASSES(b,s) PCIALWAYSPRINTCLASSES(b,s)
+
+/*
+ * PCI classes that use RAC
+ */
+#define PCISHAREDIOCLASSES(b,s) \
+ (((b) == PCI_CLASS_PREHISTORIC && (s) == PCI_SUBCLASS_PREHISTORIC_VGA) || \
+ ((b) == PCI_CLASS_DISPLAY && (s) == PCI_SUBCLASS_DISPLAY_VGA))
+
+#define PCI_MEM32_LENGTH_MAX 0xFFFFFFFF
+
+#undef MIN
+#define MIN(x,y) ((x<y)?x:y)
+
+#define B2M(tag,base) pciBusAddrToHostAddr(tag,PCI_MEM,base)
+#define B2I(tag,base) (base)
+#define B2H(tag,base,type) (((type & ResPhysMask) == ResMem) ? \
+ B2M(tag, base) : B2I(tag, base))
+#define M2B(tag,base) pciHostAddrToBusAddr(tag,PCI_IO,base)
+#define I2B(tag,base) (base)
+#define H2B(tag,base,type) (((type & ResPhysMask) == ResMem) ? \
+ M2B(tag, base) : I2B(tag, base))
+#define TAG(pvp) (pciTag(pvp->bus,pvp->device,pvp->func))
+#define SIZE(size) ((1 << size) - 1)
+#define PCI_SIZE(type,tag,size) (((type & ResPhysMask) == ResMem) \
+ ? pciBusAddrToHostAddr(tag,PCI_MEM_SIZE,size) \
+ : pciBusAddrToHostAddr(tag,PCI_IO_SIZE,size))
+#define PCI_M_RANGE(range,tag,begin,end,type) \
+ { \
+ RANGE(range, B2M(tag, begin), B2M(tag, end), \
+ RANGE_TYPE(type, xf86GetPciDomain(tag))); \
+ }
+#define PCI_I_RANGE(range,tag,begin,end,type) \
+ { \
+ RANGE(range, B2I(tag, begin), B2I(tag, end), \
+ RANGE_TYPE(type, xf86GetPciDomain(tag))); \
+ }
+#define PCI_X_RANGE(range,tag,begin,end,type) \
+{ if ((type & ResPhysMask) == ResMem) PCI_M_RANGE(range,tag,begin,end,type); \
+ else PCI_I_RANGE(range,tag,begin,end,type); }
+#define P_M_RANGE(range,tag,begin,size,type) \
+ PCI_M_RANGE(range,tag,begin,(begin + SIZE(size)),type)
+#define P_I_RANGE(range,tag,begin,size,type) \
+ PCI_I_RANGE(range,tag,begin,(begin + SIZE(size)),type)
+#define P_X_RANGE(range,tag,begin,size,type) \
+{ if ((type & ResPhysMask) == ResMem) P_M_RANGE(range,tag,begin,size,type); \
+ else P_I_RANGE(range,tag,begin,size,type); }
+#define PV_M_RANGE(range,pvp,i,type) \
+ P_M_RANGE(range,TAG(pvp),pvp->memBase[i],pvp->size[i],type)
+#define PV_B_RANGE(range,pvp,type) \
+ P_M_RANGE(range,TAG(pvp),pvp->biosBase,pvp->biosSize,type)
+#define PV_I_RANGE(range,pvp,i,type) \
+ P_I_RANGE(range,TAG(pvp),pvp->ioBase[i],pvp->size[i],type)
+
+static void getPciClassFlags(pciConfigPtr *pcrpp);
+static void pciConvertListToHost(int bus, int dev, int func, resPtr list);
+static PciBusPtr xf86GetPciBridgeInfo(void);
+
+void
+xf86FormatPciBusNumber(int busnum, char *buffer)
+{
+ /* 'buffer' should be at least 8 characters long */
+ if (busnum < 256)
+ sprintf(buffer, "%d", busnum);
+ else
+ sprintf(buffer, "%d@%d", busnum & 0x00ff, busnum >> 8);
+}
+
+static Bool
+IsBaseUnassigned(CARD32 base)
+{
+ CARD32 mask;
+
+ if (base & PCI_MAP_IO)
+ mask = ~PCI_MAP_IO_ATTR_MASK;
+ else
+ mask = ~PCI_MAP_MEMORY_ATTR_MASK;
+
+ base &= mask;
+ return (!base || (base == mask));
+}
+
+static void
+FindPCIVideoInfo(void)
+{
+ pciConfigPtr pcrp, *pcrpp;
+ int i = 0, j, k;
+ int num = 0;
+ pciVideoPtr info;
+ Bool mem64 = FALSE;
+
+ pcrpp = xf86PciInfo = xf86scanpci(0);
+ getPciClassFlags(pcrpp);
+
+ if (pcrpp == NULL) {
+ xf86PciVideoInfo = NULL;
+ return;
+ }
+ xf86PciBus = xf86GetPciBridgeInfo();
+
+ while ((pcrp = pcrpp[i])) {
+ int baseclass;
+ int subclass;
+
+ if (pcrp->listed_class & 0xffff) {
+ baseclass = (pcrp->listed_class >> 8) & 0xff;
+ subclass = pcrp->listed_class & 0xff;
+ } else {
+ baseclass = pcrp->pci_base_class;
+ subclass = pcrp->pci_sub_class;
+ }
+
+ if (PCIINFOCLASSES(baseclass, subclass)) {
+ num++;
+ xf86PciVideoInfo = xnfrealloc(xf86PciVideoInfo,
+ sizeof(pciVideoPtr) * (num + 1));
+ xf86PciVideoInfo[num] = NULL;
+ info = xf86PciVideoInfo[num - 1] = xnfalloc(sizeof(pciVideoRec));
+ info->validSize = FALSE;
+ info->vendor = pcrp->pci_vendor;
+ info->chipType = pcrp->pci_device;
+ info->chipRev = pcrp->pci_rev_id;
+ info->subsysVendor = pcrp->pci_subsys_vendor;
+ info->subsysCard = pcrp->pci_subsys_card;
+ info->bus = pcrp->busnum;
+ info->device = pcrp->devnum;
+ info->func = pcrp->funcnum;
+ info->class = baseclass;
+ info->subclass = pcrp->pci_sub_class;
+ info->interface = pcrp->pci_prog_if;
+ info->biosBase = PCIGETROM(pcrp->pci_baserom);
+ info->biosSize = pciGetBaseSize(pcrp->tag, 6, TRUE, NULL);
+ info->thisCard = pcrp;
+ info->validate = FALSE;
+#ifdef INCLUDE_XF86_NO_DOMAIN
+ if ((PCISHAREDIOCLASSES(baseclass, subclass))
+ && (pcrp->pci_command & PCI_CMD_IO_ENABLE) &&
+ (pcrp->pci_prog_if == 0)) {
+
+ /*
+ * Attempt to ensure that VGA is actually routed to this
+ * adapter on entry. This needs to be fixed when we finally
+ * grok host bridges (and multiple bus trees).
+ */
+ j = info->bus;
+ while (TRUE) {
+ PciBusPtr pBus = xf86PciBus;
+ while (pBus && j != pBus->secondary)
+ pBus = pBus->next;
+ if (!pBus || !(pBus->brcontrol & PCI_PCI_BRIDGE_VGA_EN))
+ break;
+ if (j == pBus->primary) {
+ if (primaryBus.type == BUS_NONE) {
+ /* assumption: primary adapter is always VGA */
+ primaryBus.type = BUS_PCI;
+ primaryBus.id.pci.bus = pcrp->busnum;
+ primaryBus.id.pci.device = pcrp->devnum;
+ primaryBus.id.pci.func = pcrp->funcnum;
+ } else if (primaryBus.type < BUS_last) {
+ xf86Msg(X_NOTICE,
+ "More than one primary device found\n");
+ primaryBus.type ^= (BusType)(-1);
+ }
+ break;
+ }
+ j = pBus->primary;
+ }
+ }
+#endif
+
+ for (j = 0; j < 6; j++) {
+ info->memBase[j] = 0;
+ info->ioBase[j] = 0;
+ if (PCINONSYSTEMCLASSES(baseclass, subclass)) {
+ info->size[j] =
+ pciGetBaseSize(pcrp->tag, j, TRUE, &info->validSize);
+ pcrp->minBasesize = info->validSize;
+ } else {
+ info->size[j] = pcrp->basesize[j];
+ info->validSize = pcrp->minBasesize;
+ }
+ info->type[j] = 0;
+ }
+
+ if (PCINONSYSTEMCLASSES(baseclass, subclass)) {
+ if (info->size[0] && IsBaseUnassigned(pcrp->pci_base0))
+ pcrp->pci_base0 = pciCheckForBrokenBase(pcrp->tag, 0);
+ if (info->size[1] && IsBaseUnassigned(pcrp->pci_base1))
+ pcrp->pci_base1 = pciCheckForBrokenBase(pcrp->tag, 1);
+ if (info->size[2] && IsBaseUnassigned(pcrp->pci_base2))
+ pcrp->pci_base2 = pciCheckForBrokenBase(pcrp->tag, 2);
+ if (info->size[3] && IsBaseUnassigned(pcrp->pci_base3))
+ pcrp->pci_base3 = pciCheckForBrokenBase(pcrp->tag, 3);
+ if (info->size[4] && IsBaseUnassigned(pcrp->pci_base4))
+ pcrp->pci_base4 = pciCheckForBrokenBase(pcrp->tag, 4);
+ if (info->size[5] && IsBaseUnassigned(pcrp->pci_base5))
+ pcrp->pci_base5 = pciCheckForBrokenBase(pcrp->tag, 5);
+ }
+
+ /*
+ * 64-bit base addresses are checked for and avoided.
+ * XXX Should deal with them on platforms that support them.
+ */
+ if (pcrp->pci_base0) {
+ if (pcrp->pci_base0 & PCI_MAP_IO) {
+ info->ioBase[0] = (memType)PCIGETIO(pcrp->pci_base0);
+ info->type[0] = pcrp->pci_base0 & PCI_MAP_IO_ATTR_MASK;
+ } else {
+ info->type[0] = pcrp->pci_base0 & PCI_MAP_MEMORY_ATTR_MASK;
+ info->memBase[0] = (memType)PCIGETMEMORY(pcrp->pci_base0);
+ if (PCI_MAP_IS64BITMEM(pcrp->pci_base0)) {
+ mem64 = TRUE;
+#if defined(LONG64) || defined(WORD64)
+ info->memBase[0] |=
+ (memType)PCIGETMEMORY64HIGH(pcrp->pci_base1) << 32;
+#else
+ if (pcrp->pci_base1)
+ info->memBase[0] = 0;
+#endif
+ }
+ }
+ }
+
+ if (pcrp->pci_base1 && !mem64) {
+ if (pcrp->pci_base1 & PCI_MAP_IO) {
+ info->ioBase[1] = (memType)PCIGETIO(pcrp->pci_base1);
+ info->type[1] = pcrp->pci_base1 & PCI_MAP_IO_ATTR_MASK;
+ } else {
+ info->type[1] = pcrp->pci_base1 & PCI_MAP_MEMORY_ATTR_MASK;
+ info->memBase[1] = (memType)PCIGETMEMORY(pcrp->pci_base1);
+ if (PCI_MAP_IS64BITMEM(pcrp->pci_base1)) {
+ mem64 = TRUE;
+#if defined(LONG64) || defined(WORD64)
+ info->memBase[1] |=
+ (memType)PCIGETMEMORY64HIGH(pcrp->pci_base2) << 32;
+#else
+ if (pcrp->pci_base2)
+ info->memBase[1] = 0;
+#endif
+ }
+ }
+ } else
+ mem64 = FALSE;
+
+ if (pcrp->pci_base2 && !mem64) {
+ if (pcrp->pci_base2 & PCI_MAP_IO) {
+ info->ioBase[2] = (memType)PCIGETIO(pcrp->pci_base2);
+ info->type[2] = pcrp->pci_base2 & PCI_MAP_IO_ATTR_MASK;
+ } else {
+ info->type[2] = pcrp->pci_base2 & PCI_MAP_MEMORY_ATTR_MASK;
+ info->memBase[2] = (memType)PCIGETMEMORY(pcrp->pci_base2);
+ if (PCI_MAP_IS64BITMEM(pcrp->pci_base2)) {
+ mem64 = TRUE;
+#if defined(LONG64) || defined(WORD64)
+ info->memBase[2] |=
+ (memType)PCIGETMEMORY64HIGH(pcrp->pci_base3) << 32;
+#else
+ if (pcrp->pci_base3)
+ info->memBase[2] = 0;
+#endif
+ }
+ }
+ } else
+ mem64 = FALSE;
+
+ if (pcrp->pci_base3 && !mem64) {
+ if (pcrp->pci_base3 & PCI_MAP_IO) {
+ info->ioBase[3] = (memType)PCIGETIO(pcrp->pci_base3);
+ info->type[3] = pcrp->pci_base3 & PCI_MAP_IO_ATTR_MASK;
+ } else {
+ info->type[3] = pcrp->pci_base3 & PCI_MAP_MEMORY_ATTR_MASK;
+ info->memBase[3] = (memType)PCIGETMEMORY(pcrp->pci_base3);
+ if (PCI_MAP_IS64BITMEM(pcrp->pci_base3)) {
+ mem64 = TRUE;
+#if defined(LONG64) || defined(WORD64)
+ info->memBase[3] |=
+ (memType)PCIGETMEMORY64HIGH(pcrp->pci_base4) << 32;
+#else
+ if (pcrp->pci_base4)
+ info->memBase[3] = 0;
+#endif
+ }
+ }
+ } else
+ mem64 = FALSE;
+
+ if (pcrp->pci_base4 && !mem64) {
+ if (pcrp->pci_base4 & PCI_MAP_IO) {
+ info->ioBase[4] = (memType)PCIGETIO(pcrp->pci_base4);
+ info->type[4] = pcrp->pci_base4 & PCI_MAP_IO_ATTR_MASK;
+ } else {
+ info->type[4] = pcrp->pci_base4 & PCI_MAP_MEMORY_ATTR_MASK;
+ info->memBase[4] = (memType)PCIGETMEMORY(pcrp->pci_base4);
+ if (PCI_MAP_IS64BITMEM(pcrp->pci_base4)) {
+ mem64 = TRUE;
+#if defined(LONG64) || defined(WORD64)
+ info->memBase[4] |=
+ (memType)PCIGETMEMORY64HIGH(pcrp->pci_base5) << 32;
+#else
+ if (pcrp->pci_base5)
+ info->memBase[4] = 0;
+#endif
+ }
+ }
+ } else
+ mem64 = FALSE;
+
+ if (pcrp->pci_base5 && !mem64) {
+ if (pcrp->pci_base5 & PCI_MAP_IO) {
+ info->ioBase[5] = (memType)PCIGETIO(pcrp->pci_base5);
+ info->type[5] = pcrp->pci_base5 & PCI_MAP_IO_ATTR_MASK;
+ } else {
+ info->type[5] = pcrp->pci_base5 & PCI_MAP_MEMORY_ATTR_MASK;
+ info->memBase[5] = (memType)PCIGETMEMORY(pcrp->pci_base5);
+ }
+ } else
+ mem64 = FALSE;
+ info->listed_class = pcrp->listed_class;
+ }
+ i++;
+ }
+
+ /* If we haven't found a primary device try a different heuristic */
+ if (primaryBus.type == BUS_NONE && num) {
+ for (i = 0; i < num; i++) {
+ info = xf86PciVideoInfo[i];
+ pcrp = info->thisCard;
+
+ if ((pcrp->pci_command & PCI_CMD_MEM_ENABLE) &&
+ (num == 1 ||
+ ((info->class == PCI_CLASS_DISPLAY) &&
+ (info->subclass == PCI_SUBCLASS_DISPLAY_MISC)))) {
+ if (primaryBus.type == BUS_NONE) {
+ primaryBus.type = BUS_PCI;
+ primaryBus.id.pci.bus = pcrp->busnum;
+ primaryBus.id.pci.device = pcrp->devnum;
+ primaryBus.id.pci.func = pcrp->funcnum;
+ } else {
+ xf86Msg(X_NOTICE,
+ "More than one possible primary device found\n");
+ primaryBus.type ^= (BusType)(-1);
+ }
+ }
+ }
+ }
+
+ /* Print a summary of the video devices found */
+ for (k = 0; k < num; k++) {
+ const char *vendorname = NULL, *chipname = NULL;
+ const char *prim = " ";
+ char busnum[8];
+ Bool memdone = FALSE, iodone = FALSE;
+
+ i = 0;
+ info = xf86PciVideoInfo[k];
+ xf86FormatPciBusNumber(info->bus, busnum);
+ xf86FindPciNamesByDevice(info->vendor, info->chipType,
+ NOVENDOR, NOSUBSYS,
+ &vendorname, &chipname, NULL, NULL);
+ if ((!vendorname || !chipname) &&
+ !PCIALWAYSPRINTCLASSES(info->class, info->subclass))
+ continue;
+ if (xf86IsPrimaryPci(info))
+ prim = "*";
+
+ xf86Msg(X_PROBED, "PCI:%s(%s:%d:%d) ", prim, busnum, info->device,
+ info->func);
+ if (vendorname)
+ xf86ErrorF("%s ", vendorname);
+ else
+ xf86ErrorF("unknown vendor (0x%04x) ", info->vendor);
+ if (chipname)
+ xf86ErrorF("%s ", chipname);
+ else
+ xf86ErrorF("unknown chipset (0x%04x) ", info->chipType);
+ xf86ErrorF("rev %d", info->chipRev);
+ for (i = 0; i < 6; i++) {
+ if (info->memBase[i] &&
+ (info->memBase[i] < (memType)(-1 << info->size[i]))) {
+ if (!memdone) {
+ xf86ErrorF(", Mem @ ");
+ memdone = TRUE;
+ } else
+ xf86ErrorF(", ");
+ xf86ErrorF("0x%08x/%d", info->memBase[i], info->size[i]);
+ }
+ }
+ for (i = 0; i < 6; i++) {
+ if (info->ioBase[i] &&
+ (info->ioBase[i] < (memType)(-1 << info->size[i]))) {
+ if (!iodone) {
+ xf86ErrorF(", I/O @ ");
+ iodone = TRUE;
+ } else
+ xf86ErrorF(", ");
+ xf86ErrorF("0x%04x/%d", info->ioBase[i], info->size[i]);
+ }
+ }
+ if (info->biosBase &&
+ (info->biosBase < (memType)(-1 << info->biosSize)))
+ xf86ErrorF(", BIOS @ 0x%08x/%d", info->biosBase, info->biosSize);
+ xf86ErrorF("\n");
+ }
+}
+
+/*
+ * fixPciSizeInfo() -- fix pci size info by testing it destructively
+ * (if not already done), fix pciVideoInfo and entry in the resource
+ * list.
+ */
+/*
+ * Note: once we have OS support to read the sizes GetBaseSize() will
+ * have to be wrapped by the OS layer. fixPciSizeInfo() should also
+ * be wrapped by the OS layer to do nothing if the size is always
+ * returned correctly by GetBaseSize(). It should however set validate
+ * in pciVideoRec if validation is required. ValidatePci() also needs
+ * to be wrapped by the OS layer. This may do nothing if the OS has
+ * already taken care of validation. fixPciResource() may be moved to
+ * OS layer with minimal changes. Once the wrapping layer is in place
+ * the common level and drivers should not reference these functions
+ * directly but thru the OS layer.
+ */
+
+static void
+fixPciSizeInfo(int entityIndex)
+{
+ pciVideoPtr pvp;
+ resPtr pAcc;
+ PCITAG tag;
+ int j;
+
+ if (! (pvp = xf86GetPciInfoForEntity(entityIndex))) return;
+ if (pvp->validSize) return;
+
+ tag = pciTag(pvp->bus,pvp->device,pvp->func);
+
+ for (j = 0; j < 6; j++) {
+ pAcc = Acc;
+ if (pvp->memBase[j])
+ while (pAcc) {
+ if (((pAcc->res_type & (ResPhysMask | ResBlock))
+ == (ResMem | ResBlock))
+ && (pAcc->block_begin == B2M(TAG(pvp),pvp->memBase[j]))
+ && (pAcc->block_end == B2M(TAG(pvp),pvp->memBase[j]
+ + SIZE(pvp->size[j])))) break;
+ pAcc = pAcc->next;
+ }
+ else if (pvp->ioBase[j])
+ while (pAcc) {
+ if (((pAcc->res_type & (ResPhysMask | ResBlock)) ==
+ (ResIo | ResBlock))
+ && (pAcc->block_begin == B2I(TAG(pvp),pvp->ioBase[j]))
+ && (pAcc->block_end == B2I(TAG(pvp),pvp->ioBase[j]
+ + SIZE(pvp->size[j])))) break;
+ pAcc = pAcc->next;
+ }
+ else continue;
+ pvp->size[j] = pciGetBaseSize(tag, j, TRUE, &pvp->validSize);
+ if (pAcc) {
+ pAcc->block_end = pvp->memBase[j] ?
+ B2M(TAG(pvp),pvp->memBase[j] + SIZE(pvp->size[j]))
+ : B2I(TAG(pvp),pvp->ioBase[j] + SIZE(pvp->size[j]));
+ pAcc->res_type &= ~ResEstimated;
+ pAcc->res_type |= ResBios;
+ }
+ }
+ if (pvp->biosBase) {
+ pAcc = Acc;
+ while (pAcc) {
+ if (((pAcc->res_type & (ResPhysMask | ResBlock)) ==
+ (ResMem | ResBlock))
+ && (pAcc->block_begin == B2M(TAG(pvp),pvp->biosBase))
+ && (pAcc->block_end == B2M(TAG(pvp),pvp->biosBase
+ + SIZE(pvp->biosSize)))) break;
+ pAcc = pAcc->next;
+ }
+ pvp->biosSize = pciGetBaseSize(tag, 6, TRUE, &pvp->validSize);
+ if (pAcc) {
+ pAcc->block_end = B2M(TAG(pvp),pvp->biosBase+SIZE(pvp->biosSize));
+ pAcc->res_type &= ~ResEstimated;
+ pAcc->res_type |= ResBios;
+ }
+ }
+}
+
+/*
+ * IO enable/disable related routines for PCI
+ */
+#define pArg ((pciArg*)arg)
+#define SETBITS PCI_CMD_IO_ENABLE
+static void
+pciIoAccessEnable(void* arg)
+{
+#ifdef DEBUG
+ ErrorF("pciIoAccessEnable: 0x%05lx\n", *(PCITAG *)arg);
+#endif
+ pArg->ctrl |= SETBITS | PCI_CMD_MASTER_ENABLE;
+ (*pArg->func)(pArg->tag, PCI_CMD_STAT_REG, pArg->ctrl);
+}
+
+static void
+pciIoAccessDisable(void* arg)
+{
+#ifdef DEBUG
+ ErrorF("pciIoAccessDisable: 0x%05lx\n", *(PCITAG *)arg);
+#endif
+ pArg->ctrl &= ~SETBITS;
+ (*pArg->func)(pArg->tag, PCI_CMD_STAT_REG, pArg->ctrl);
+}
+
+#undef SETBITS
+#define SETBITS (PCI_CMD_IO_ENABLE | PCI_CMD_MEM_ENABLE)
+static void
+pciIo_MemAccessEnable(void* arg)
+{
+#ifdef DEBUG
+ ErrorF("pciIo_MemAccessEnable: 0x%05lx\n", *(PCITAG *)arg);
+#endif
+ pArg->ctrl |= SETBITS | PCI_CMD_MASTER_ENABLE;
+ (*pArg->func)(pArg->tag, PCI_CMD_STAT_REG, pArg->ctrl);
+}
+
+static void
+pciIo_MemAccessDisable(void* arg)
+{
+#ifdef DEBUG
+ ErrorF("pciIo_MemAccessDisable: 0x%05lx\n", *(PCITAG *)arg);
+#endif
+ pArg->ctrl &= ~SETBITS;
+ (*pArg->func)(pArg->tag, PCI_CMD_STAT_REG, pArg->ctrl);
+}
+
+#undef SETBITS
+#define SETBITS (PCI_CMD_MEM_ENABLE)
+static void
+pciMemAccessEnable(void* arg)
+{
+#ifdef DEBUG
+ ErrorF("pciMemAccessEnable: 0x%05lx\n", *(PCITAG *)arg);
+#endif
+ pArg->ctrl |= SETBITS | PCI_CMD_MASTER_ENABLE;
+ (*pArg->func)(pArg->tag, PCI_CMD_STAT_REG, pArg->ctrl);
+}
+
+static void
+pciMemAccessDisable(void* arg)
+{
+#ifdef DEBUG
+ ErrorF("pciMemAccessDisable: 0x%05lx\n", *(PCITAG *)arg);
+#endif
+ pArg->ctrl &= ~SETBITS;
+ (*pArg->func)(pArg->tag, PCI_CMD_STAT_REG, pArg->ctrl);
+}
+#undef SETBITS
+#undef pArg
+
+
+/* move to OS layer */
+#define PCI_PCI_BRDG_CTRL_BASE (PCI_PCI_BRIDGE_CONTROL_REG & 0xFC)
+#define SHIFT_BITS ((PCI_PCI_BRIDGE_CONTROL_REG & 0x3) << 3)
+#define SETBITS (CARD32)((PCI_PCI_BRIDGE_VGA_EN) << SHIFT_BITS)
+static void
+pciBusAccessEnable(BusAccPtr ptr)
+{
+#ifdef DEBUG
+ ErrorF("pciBusAccessEnable: bus=%d\n", ptr->busdep.pci.bus);
+#endif
+ (*ptr->busdep.pci.func)(ptr->busdep.pci.acc, PCI_PCI_BRDG_CTRL_BASE,
+ SETBITS, SETBITS);
+}
+
+/* move to OS layer */
+static void
+pciBusAccessDisable(BusAccPtr ptr)
+{
+#ifdef DEBUG
+ ErrorF("pciBusAccessDisable: bus=%d\n", ptr->busdep.pci.bus);
+#endif
+ (*ptr->busdep.pci.func)(ptr->busdep.pci.acc, PCI_PCI_BRDG_CTRL_BASE,
+ SETBITS, 0);
+}
+#undef SETBITS
+#undef SHIFT_BITS
+
+/* move to OS layer */
+static void
+pciDrvBusAccessEnable(BusAccPtr ptr)
+{
+ int bus = ptr->busdep.pci.bus;
+
+#ifdef DEBUG
+ ErrorF("pciDrvBusAccessEnable: bus=%d\n", bus);
+#endif
+ (*pciBusInfo[bus]->funcs->pciControlBridge)(bus,
+ PCI_PCI_BRIDGE_VGA_EN,
+ PCI_PCI_BRIDGE_VGA_EN);
+}
+
+/* move to OS layer */
+static void
+pciDrvBusAccessDisable(BusAccPtr ptr)
+{
+ int bus = ptr->busdep.pci.bus;
+
+#ifdef DEBUG
+ ErrorF("pciDrvBusAccessDisable: bus=%d\n", bus);
+#endif
+ (*pciBusInfo[bus]->funcs->pciControlBridge)(bus,
+ PCI_PCI_BRIDGE_VGA_EN, 0);
+}
+
+
+static void
+pciSetBusAccess(BusAccPtr ptr)
+{
+#ifdef DEBUG
+ ErrorF("pciSetBusAccess: route VGA to bus %d\n", ptr->busdep.pci.bus);
+#endif
+
+ if (!ptr->primary && !ptr->current)
+ return;
+
+ if (ptr->current && ptr->current->disable_f)
+ (*ptr->current->disable_f)(ptr->current);
+ ptr->current = NULL;
+
+ /* walk down */
+ while (ptr->primary) { /* No enable for root bus */
+ if (ptr != ptr->primary->current) {
+ if (ptr->primary->current && ptr->primary->current->disable_f)
+ (*ptr->primary->current->disable_f)(ptr->primary->current);
+ if (ptr->enable_f)
+ (*ptr->enable_f)(ptr);
+ ptr->primary->current = ptr;
+ }
+ ptr = ptr->primary;
+ }
+}
+
+/* move to OS layer */
+static void
+savePciState(PCITAG tag, pciSavePtr ptr)
+{
+ int i;
+
+ ptr->command = pciReadLong(tag, PCI_CMD_STAT_REG);
+ for (i=0; i < 6; i++)
+ ptr->base[i] = pciReadLong(tag, PCI_CMD_BASE_REG + i*4);
+ ptr->biosBase = pciReadLong(tag, PCI_CMD_BIOS_REG);
+}
+
+/* move to OS layer */
+static void
+restorePciState(PCITAG tag, pciSavePtr ptr)
+{
+ int i;
+
+ /* disable card before setting anything */
+ pciSetBitsLong(tag, PCI_CMD_STAT_REG,
+ PCI_CMD_MEM_ENABLE | PCI_CMD_IO_ENABLE , 0);
+ pciWriteLong(tag,PCI_CMD_BIOS_REG, ptr->biosBase);
+ for (i=0; i<6; i++)
+ pciWriteLong(tag, PCI_CMD_BASE_REG + i*4, ptr->base[i]);
+ pciWriteLong(tag, PCI_CMD_STAT_REG, ptr->command);
+}
+
+/* move to OS layer */
+static void
+savePciBusState(BusAccPtr ptr)
+{
+ ptr->busdep.pci.save.control =
+ pciReadWord(ptr->busdep.pci.acc, PCI_PCI_BRIDGE_CONTROL_REG) &
+ ~PCI_PCI_BRIDGE_SECONDARY_RESET;
+ /* Allow master aborts to complete normally on non-root buses */
+ if (ptr->busdep.pci.save.control & PCI_PCI_BRIDGE_MASTER_ABORT_EN)
+ pciWriteWord(ptr->busdep.pci.acc, PCI_PCI_BRIDGE_CONTROL_REG,
+ ptr->busdep.pci.save.control
+ & ~PCI_PCI_BRIDGE_MASTER_ABORT_EN);
+}
+
+/* move to OS layer */
+static void
+restorePciBusState(BusAccPtr ptr)
+{
+ pciWriteWord(ptr->busdep.pci.acc, PCI_PCI_BRIDGE_CONTROL_REG,
+ ptr->busdep.pci.save.control);
+}
+
+/* move to OS layer */
+static void
+savePciDrvBusState(BusAccPtr ptr)
+{
+ int bus = ptr->busdep.pci.bus;
+
+ ptr->busdep.pci.save.control =
+ (*pciBusInfo[bus]->funcs->pciControlBridge)(bus, 0, 0);
+ /* Allow master aborts to complete normally on this bus */
+ (*pciBusInfo[bus]->funcs->pciControlBridge)(bus,
+ PCI_PCI_BRIDGE_MASTER_ABORT_EN,
+ 0);
+}
+
+/* move to OS layer */
+static void
+restorePciDrvBusState(BusAccPtr ptr)
+{
+ int bus = ptr->busdep.pci.bus;
+
+ (*pciBusInfo[bus]->funcs->pciControlBridge)(bus, (CARD16)(-1),
+ ptr->busdep.pci.save.control);
+}
+
+
+static void
+disablePciBios(PCITAG tag)
+{
+ pciSetBitsLong(tag, PCI_CMD_BIOS_REG, PCI_CMD_BIOS_ENABLE, 0);
+}
+
+/* ????? */
+static void
+correctPciSize(memType base, memType oldsize, memType newsize,
+ unsigned long type)
+{
+ pciConfigPtr pcrp, *pcrpp;
+ pciVideoPtr pvp, *pvpp;
+ CARD32 *basep;
+ int i;
+ int old_bits = 0, new_bits = 0;
+
+ if (oldsize + 1) while (oldsize & 1) {
+ old_bits ++;
+ oldsize >>= 1;
+ }
+ if (newsize + 1) while (newsize & 1) {
+ new_bits ++;
+ newsize >>= 1;
+ }
+
+ for (pcrpp = xf86PciInfo, pcrp = *pcrpp; pcrp; pcrp = *++(pcrpp)) {
+
+ /* Only process devices with type 0 headers */
+ if ((pcrp->pci_header_type & 0x7f) != 0)
+ continue;
+
+ basep = &pcrp->pci_base0;
+ for (i = 0; i < 6; i++) {
+ if (basep[i] && (pcrp->basesize[i] == old_bits)) {
+ if ((((type & ResPhysMask) == ResIo) &&
+ PCI_MAP_IS_IO(basep[i]) &&
+ B2I(pcrp->tag,PCIGETIO(basep[i]) == base)) ||
+ (((type & ResPhysMask) == ResMem) &&
+ PCI_MAP_IS_MEM(basep[i]) &&
+ (((!PCI_MAP_IS64BITMEM(basep[i])) &&
+ (B2M(pcrp->tag,PCIGETMEMORY(basep[i])) == base))
+#if defined(LONG64) || defined(WORD64)
+ ||
+ (B2M(pcrp->tag,PCIGETMEMORY64(basep[i])) == base)
+#endif
+ ))) {
+ pcrp->basesize[i] = new_bits;
+ break; /* to next device */
+ }
+ }
+ }
+ }
+
+ if (xf86PciVideoInfo) {
+ for (pvpp = xf86PciVideoInfo, pvp = *pvpp; pvp; pvp = *(++pvpp)) {
+
+ for (i = 0; i < 6; i++) {
+ if (pvp->size[i] == old_bits) {
+ if ((((type & ResPhysMask) == ResIo) && pvp->ioBase[i]
+ && (B2I(TAG(pvp),pvp->ioBase[i]) == base)) ||
+ (((type & ResPhysMask) == ResMem) && pvp->memBase[i]
+ && (B2M(TAG(pvp),pvp->memBase[i]) == base))) {
+ pvp->size[i] = new_bits;
+ break; /* to next device */
+ }
+ }
+ }
+ }
+ }
+}
+
+/* ????? */
+static void
+removeOverlapsWithBridges(int busIndex, resPtr target)
+{
+ PciBusPtr pbp;
+ resPtr tmp,bridgeRes = NULL;
+ resRange range = target->val;
+
+ if (!ResCanOverlap(&target->val))
+ return;
+
+ for (pbp=xf86PciBus; pbp; pbp = pbp->next) {
+ if (pbp->primary == busIndex) {
+ tmp = xf86DupResList(pbp->preferred_io);
+ bridgeRes = xf86JoinResLists(tmp,bridgeRes);
+ tmp = xf86DupResList(pbp->preferred_mem);
+ bridgeRes = xf86JoinResLists(tmp,bridgeRes);
+ tmp = xf86DupResList(pbp->preferred_pmem);
+ bridgeRes = xf86JoinResLists(tmp,bridgeRes);
+ }
+ }
+
+ RemoveOverlaps(target, bridgeRes, TRUE, TRUE);
+ if (range.rEnd > target->block_end) {
+ correctPciSize(range.rBegin, range.rEnd - range.rBegin,
+ target->block_end - target->block_begin,
+ target->res_type);
+ xf86MsgVerb(X_INFO, 3,
+ "PCI %s resource overlap reduced 0x%08x from 0x%08x to 0x%08x\n",
+ ((target->res_type & ResPhysMask) == ResMem) ? "Memory" : "I/O",
+ range.rBegin, range.rEnd, target->block_end);
+ }
+ xf86FreeResList(bridgeRes);
+}
+
+/* ????? */
+static void
+xf86GetPciRes(resPtr *activeRes, resPtr *inactiveRes)
+{
+ pciConfigPtr pcrp, *pcrpp;
+ pciVideoPtr pvp, *pvpp;
+ CARD32 *basep;
+ int i;
+ resPtr pRes, tmp;
+ resRange range;
+ long resMisc;
+
+ if (activeRes)
+ *activeRes = NULL;
+ if (inactiveRes)
+ *inactiveRes = NULL;
+
+ if (!activeRes || !inactiveRes || !xf86PciInfo)
+ return;
+
+ if (xf86PciVideoInfo)
+ for (pvpp = xf86PciVideoInfo, pvp = *pvpp; pvp; pvp = *(++pvpp)) {
+ resPtr *res;
+
+ if (PCINONSYSTEMCLASSES(pvp->class, pvp->subclass))
+ resMisc = ResBios;
+ else
+ resMisc = 0;
+
+ if (((pciConfigPtr)pvp->thisCard)->pci_command
+ & (PCI_CMD_IO_ENABLE | PCI_CMD_MEM_ENABLE))
+ res = activeRes;
+ else
+ res = inactiveRes;
+
+ if (!pvp->validSize)
+ resMisc |= ResEstimated;
+
+ for (i = 0; i < 6; i++) {
+ if (pvp->ioBase[i] &&
+ (pvp->ioBase[i] < (memType)(-1 << pvp->size[i]))) {
+ PV_I_RANGE(range,pvp,i,ResExcIoBlock | resMisc);
+ tmp = xf86AddResToList(NULL, &range, -1);
+ removeOverlapsWithBridges(pvp->bus,tmp);
+ *res = xf86JoinResLists(tmp,*res);
+ } else if (pvp->memBase[i] &&
+ (pvp->memBase[i] < (memType)(-1 << pvp->size[i]))) {
+ PV_M_RANGE(range, pvp,i, ResExcMemBlock | resMisc);
+ tmp = xf86AddResToList(NULL, &range, -1);
+ removeOverlapsWithBridges(pvp->bus,tmp);
+ *res = xf86JoinResLists(tmp,*res);
+ }
+ }
+ /* FIXME!!!: Don't use BIOS resources for overlap
+ * checking but reserve them!
+ */
+ if (pvp->biosBase &&
+ (pvp->biosBase < (memType)(-1 << pvp->biosSize))) {
+ PV_B_RANGE(range, pvp, ResExcMemBlock | resMisc);
+ tmp = xf86AddResToList(NULL, &range, -1);
+ removeOverlapsWithBridges(pvp->bus,tmp);
+ *res = xf86JoinResLists(tmp,*res);
+ }
+ }
+
+ for (pcrpp = xf86PciInfo, pcrp = *pcrpp; pcrp; pcrp = *++(pcrpp)) {
+ resPtr *res;
+ CARD8 baseclass, subclass;
+
+ if (pcrp->listed_class & 0x0ffff) {
+ baseclass = pcrp->listed_class >> 8;
+ subclass = pcrp->listed_class;
+ } else {
+ baseclass = pcrp->pci_base_class;
+ subclass = pcrp->pci_sub_class;
+ }
+
+ if (PCIINFOCLASSES(baseclass, subclass))
+ continue;
+
+ /* Only process devices with type 0 headers */
+ if ((pcrp->pci_header_type & 0x7f) != 0)
+ continue;
+
+ if (!pcrp->minBasesize)
+ resMisc = ResEstimated;
+ else
+ resMisc = 0;
+
+ /*
+ * Allow resources allocated to host bridges to overlap. Perhaps, this
+ * needs to be specific to AGP-capable chipsets. AGP "memory"
+ * sometimes gets allocated within the range routed to the AGP bus.
+ */
+ if ((baseclass == PCI_CLASS_BRIDGE) &&
+ (subclass == PCI_SUBCLASS_BRIDGE_HOST))
+ resMisc |= ResOverlap;
+
+ if ((pcrp->pci_command & (PCI_CMD_IO_ENABLE | PCI_CMD_MEM_ENABLE)))
+ res = activeRes;
+ else
+ res = inactiveRes;
+
+ basep = &pcrp->pci_base0;
+ for (i = 0; i < 6; i++) {
+ if (basep[i]) {
+ if (PCI_MAP_IS_IO(basep[i]))
+ P_I_RANGE(range,pcrp->tag,PCIGETIO(basep[i]),
+ pcrp->basesize[i], ResExcIoBlock | resMisc)
+ else if (!PCI_MAP_IS64BITMEM(basep[i]))
+ P_M_RANGE(range,pcrp->tag,PCIGETMEMORY(basep[i]),
+ pcrp->basesize[i], ResExcMemBlock | resMisc)
+ else {
+ i++;
+#if defined(LONG64) || defined(WORD64)
+ P_M_RANGE(range,pcrp->tag,PCIGETMEMORY64(basep[i-1]),
+ pcrp->basesize[i-1], ResExcMemBlock | resMisc)
+#else
+ continue;
+#endif
+ }
+ if (range.rBegin) { /* catch cases where PCI base is unset */
+ tmp = xf86AddResToList(NULL, &range, -1);
+ removeOverlapsWithBridges(pcrp->busnum,tmp);
+ *res = xf86JoinResLists(tmp,*res);
+ }
+ }
+ }
+ /* Ignore disabled non-video ROMs */
+ if ((res == activeRes) &&
+ (pcrp->pci_baserom & PCI_MAP_ROM_DECODE_ENABLE)) {
+ P_M_RANGE(range,pcrp->tag,PCIGETROM(pcrp->pci_baserom),
+ pcrp->basesize[6], ResExcMemBlock | resMisc);
+ if (range.rBegin) {
+ tmp = xf86AddResToList(NULL, &range, -1);
+ removeOverlapsWithBridges(pcrp->busnum,tmp);
+ *res = xf86JoinResLists(tmp,*res);
+ }
+ }
+ }
+
+ if (*activeRes) {
+ xf86MsgVerb(X_INFO, 3, "Active PCI resource ranges:\n");
+ xf86PrintResList(3, *activeRes);
+ }
+ if (*inactiveRes) {
+ xf86MsgVerb(X_INFO, 3, "Inactive PCI resource ranges:\n");
+ xf86PrintResList(3, *inactiveRes);
+ }
+
+ /*
+ * Adjust ranges based on the assumption that there are no real
+ * overlaps in the PCI base allocations. This assumption should be
+ * reasonable in most cases. It may be possible to refine the
+ * approximated PCI base sizes by considering bus mapping information
+ * from PCI-PCI bridges.
+ */
+
+ if (*activeRes) {
+ /* Check for overlaps */
+ for (pRes = *activeRes; pRes; pRes = pRes->next) {
+ if (ResCanOverlap(&pRes->val)) {
+ range = pRes->val;
+
+ RemoveOverlaps(pRes, *activeRes, TRUE, TRUE);
+ RemoveOverlaps(pRes, *inactiveRes, TRUE,
+ (xf86Info.estimateSizesAggressively > 0));
+
+ if (range.rEnd > pRes->block_end) {
+ correctPciSize(range.rBegin, range.rEnd - range.rBegin,
+ pRes->block_end - pRes->block_begin,
+ pRes->res_type);
+ xf86MsgVerb(X_INFO, 3,
+ "PCI %s resource overlap reduced 0x%08x"
+ " from 0x%08x to 0x%08x\n",
+ ((pRes->res_type & ResPhysMask) == ResMem) ?
+ "Memory" : "I/O",
+ range.rBegin, range.rEnd, pRes->block_end);
+ }
+ }
+ }
+ xf86MsgVerb(X_INFO, 3,
+ "Active PCI resource ranges after removing overlaps:\n");
+ xf86PrintResList(3, *activeRes);
+ }
+
+ if (*inactiveRes) {
+ /* Check for overlaps */
+ for (pRes = *inactiveRes; pRes; pRes = pRes->next) {
+ if (ResCanOverlap(&pRes->val)) {
+ range = pRes->val;
+
+ RemoveOverlaps(pRes, *activeRes, TRUE,
+ (xf86Info.estimateSizesAggressively > 1));
+ RemoveOverlaps(pRes, *inactiveRes, TRUE,
+ (xf86Info.estimateSizesAggressively > 1));
+
+ if (range.rEnd > pRes->block_end) {
+ correctPciSize(range.rBegin, range.rEnd - range.rBegin,
+ pRes->block_end - pRes->block_begin,
+ pRes->res_type);
+ xf86MsgVerb(X_INFO, 3,
+ "PCI %s resource overlap reduced 0x%08x"
+ " from 0x%08x to 0x%08x\n",
+ ((pRes->res_type & ResPhysMask) == ResMem) ?
+ "Memory" : "I/O",
+ range.rBegin, range.rEnd, pRes->block_end);
+ }
+
+ }
+ }
+ xf86MsgVerb(X_INFO, 3,
+ "Inactive PCI resource ranges after removing overlaps:\n");
+ xf86PrintResList(3, *inactiveRes);
+ }
+}
+
+resPtr
+ResourceBrokerInitPci(resPtr *osRes)
+{
+ resPtr activeRes, inactiveRes;
+ resPtr tmp;
+
+ /* Get bus-specific system resources (PCI) */
+ xf86GetPciRes(&activeRes, &inactiveRes);
+
+ /*
+ * Adjust OS-reported resource ranges based on the assumption that there
+ * are no overlaps with the PCI base allocations. This should be a good
+ * assumption because writes to PCI address space won't be routed directly
+ * to host memory.
+ */
+
+ for (tmp = *osRes; tmp; tmp = tmp->next)
+ RemoveOverlaps(tmp, activeRes, FALSE, TRUE);
+
+ xf86MsgVerb(X_INFO, 3, "OS-reported resource ranges after removing"
+ " overlaps with PCI:\n");
+ xf86PrintResList(3, *osRes);
+
+ pciAvoidRes = xf86AddRangesToList(pciAvoidRes,PciAvoid,-1);
+ for (tmp = pciAvoidRes; tmp; tmp = tmp->next)
+ RemoveOverlaps(tmp, activeRes, FALSE, TRUE);
+ tmp = xf86DupResList(*osRes);
+ pciAvoidRes = xf86JoinResLists(pciAvoidRes,tmp);
+
+ return (xf86JoinResLists(activeRes,inactiveRes));
+}
+
+
+/*
+ * PCI Resource modification
+ */
+static Bool
+fixPciResource(int prt, memType alignment, pciVideoPtr pvp, unsigned long type)
+{
+ int res_n;
+ memType *p_base;
+ int *p_size;
+ unsigned char p_type;
+ resPtr AccTmp = NULL;
+ resPtr orgAcc = NULL;
+ resPtr *pAcc = &AccTmp;
+ resPtr avoid = NULL;
+ resRange range;
+ resPtr resSize = NULL;
+ resPtr w_tmp, w = NULL, w_2nd = NULL;
+ PCITAG tag;
+ PciBusPtr pbp = xf86PciBus;
+ pciConfigPtr pcp;
+ resPtr tmp;
+
+ if (!pvp) return FALSE;
+ tag = pciTag(pvp->bus,pvp->device,pvp->func);
+ pcp = pvp->thisCard;
+
+ type &= ResAccMask;
+ if (!type) type = ResShared;
+ if (prt < 6) {
+ if (pvp->memBase[prt]) {
+ type |= ResMem;
+ res_n = prt;
+ p_base = &(pvp->memBase[res_n]);
+ p_size = &(pvp->size[res_n]);
+ p_type = pvp->type[res_n];
+ if (!PCI_MAP_IS64BITMEM(pvp->type[res_n])) {
+ PCI_M_RANGE(range,tag,0,0xffffffff,ResExcMemBlock);
+ resSize = xf86AddResToList(resSize,&range,-1);
+ }
+ } else if (pvp->ioBase[prt]){
+ type |= ResIo;
+ res_n = prt;
+ p_base = &(pvp->ioBase[res_n]);
+ p_size = &(pvp->size[res_n]);
+ p_type = pvp->type[res_n];
+ PCI_I_RANGE(range, tag, 0, 0xffffffff, ResExcIoBlock);
+ resSize = xf86AddResToList(resSize, &range, -1);
+ } else return FALSE;
+ } else if (prt == 6) {
+ type |= ResMem;
+ res_n = 0xff; /* special flag for bios rom */
+ p_base = &(pvp->biosBase);
+ p_size = &(pvp->biosSize);
+ /* XXX This should also include the PCI_MAP_MEMORY_TYPE_MASK part */
+ p_type = 0;
+ PCI_M_RANGE(range,tag,0,0xffffffff,ResExcMemBlock);
+ resSize = xf86AddResToList(resSize,&range,-1);
+ } else return FALSE;
+
+ if (! *p_base) return FALSE;
+
+ type |= (range.type & ResDomain) | ResBlock;
+
+ /* setup avoid: PciAvoid is bus range: convert later */
+ avoid = xf86DupResList(pciAvoidRes);
+
+ while (pbp) {
+ if (pbp->secondary == pvp->bus) {
+ if ((type & ResPhysMask) == ResMem) {
+ if (((p_type & PCI_MAP_MEMORY_CACHABLE)
+#if 0 /*EE*/
+ || (res_n == 0xff)/* bios should also be prefetchable */
+#endif
+ )) {
+ if (pbp->preferred_pmem)
+ w = xf86FindIntersectOfLists(pbp->preferred_pmem,
+ ResRange);
+ else if (pbp->pmem)
+ w = xf86FindIntersectOfLists(pbp->pmem,ResRange);
+
+ if (pbp->preferred_mem)
+ w_2nd = xf86FindIntersectOfLists(pbp->preferred_mem,
+ ResRange);
+ else if (pbp->mem)
+ w_2nd = xf86FindIntersectOfLists(pbp->mem,
+ ResRange);
+ } else {
+ if (pbp->preferred_mem)
+ w = xf86FindIntersectOfLists(pbp->preferred_mem,
+ ResRange);
+ else if (pbp->mem)
+ w = xf86FindIntersectOfLists(pbp->mem,ResRange);
+ }
+ } else {
+ if (pbp->preferred_io)
+ w = xf86FindIntersectOfLists(pbp->preferred_io,ResRange);
+ if (pbp->io)
+ w = xf86FindIntersectOfLists(pbp->io,ResRange);
+ }
+ } else if (pbp->primary == pvp->bus) {
+ if ((type & ResPhysMask) == ResMem) {
+ tmp = xf86DupResList(pbp->preferred_pmem);
+ avoid = xf86JoinResLists(avoid, tmp);
+ tmp = xf86DupResList(pbp->preferred_mem);
+ avoid = xf86JoinResLists(avoid, tmp);
+ } else {
+ tmp = xf86DupResList(pbp->preferred_io);
+ avoid = xf86JoinResLists(avoid, tmp);
+ }
+ }
+ pbp = pbp->next;
+ }
+
+ /* convert bus based entries in avoid list to host base */
+ pciConvertListToHost(pvp->bus,pvp->device,pvp->func, avoid);
+
+ if (!w)
+ w = xf86DupResList(ResRange);
+ xf86MsgVerb(X_INFO, 3, "window:\n");
+ xf86PrintResList(3, w);
+ xf86MsgVerb(X_INFO, 3, "resSize:\n");
+ xf86PrintResList(3, resSize);
+
+ if (resSize) {
+ w_tmp = w;
+ w = xf86FindIntersectOfLists(w,resSize);
+ xf86FreeResList(w_tmp);
+ if (w_2nd) {
+ w_tmp = w_2nd;
+ w_2nd = xf86FindIntersectOfLists(w_2nd,resSize);
+ xf86FreeResList(w_tmp);
+ }
+ xf86FreeResList(resSize);
+ }
+ xf86MsgVerb(X_INFO, 3, "window fixed:\n");
+ xf86PrintResList(3, w);
+
+ if (!alignment)
+ alignment = (1 << (*p_size)) - 1;
+
+ /* Access list holds bios resources -- remove this one */
+#ifdef NOTYET
+ AccTmp = xf86DupResList(Acc);
+ while ((*pAcc)) {
+ if ((((*pAcc)->res_type & (type & ~ResAccMask))
+ == (type & ~ResAccMask))
+ && ((*pAcc)->block_begin == (B2H(tag,(*p_base),type)))
+ && ((*pAcc)->block_end == (B2H(tag,
+ (*p_base)+SIZE(*p_size),type)))) {
+ resPtr acc_tmp = (*pAcc)->next;
+ xfree((*pAcc));
+ (*pAcc) = acc_tmp;
+ break;
+ } else
+ pAcc = &((*pAcc)->next);
+ }
+ /* check if we really need to fix anything */
+ P_X_RANGE(range,tag,(*p_base),(*p_base) + SIZE((*p_size)),type);
+ if (!ChkConflict(&range,avoid,SETUP)
+ && !ChkConflict(&range,AccTmp,SETUP)
+ && ((B2H(tag,(*p_base),type) & PCI_SIZE(type,tag,alignment)
+ == range->block_begin)
+ && ((xf86IsSubsetOf(range,w)
+ || (w_2nd && xf86IsSubsetOf(range,w_2n))))) {
+#ifdef DEBUG
+ ErrorF("nothing to fix\n");
+#endif
+ xf86FreeResList(AccTmp);
+ xf86FreeResList(w);
+ xf86FreeResList(w_2nd);
+ xf86FreeResList(avoid);
+ return TRUE;
+ }
+#ifdef DEBUG
+ ErrorF("removing old resource\n");
+#endif
+ orgAcc = Acc;
+ Acc = AccTmp;
+#else
+ orgAcc = xf86DupResList(Acc);
+ pAcc = &Acc;
+ while (*pAcc) {
+ if ((((*pAcc)->res_type & (ResTypeMask|ResExtMask)) ==
+ (type & ~ResAccMask))
+ && ((*pAcc)->block_begin == B2H(tag,(*p_base),type))
+ && ((*pAcc)->block_end == B2H(tag,(*p_base) + SIZE(*p_size),
+ type))) {
+#ifdef DEBUG
+ ErrorF("removing old resource\n");
+#endif
+ tmp = *pAcc;
+ *pAcc = (*pAcc)->next;
+ tmp->next = NULL;
+ xf86FreeResList(tmp);
+ break;
+ } else
+ pAcc = &((*pAcc)->next);
+ }
+#endif
+
+#ifdef DEBUG
+ ErrorF("base: 0x%lx alignment: 0x%lx host alignment: 0x%lx size[bit]: 0x%x\n",
+ (*p_base),alignment,PCI_SIZE(type,tag,alignment),(*p_size));
+ xf86MsgVerb(X_INFO, 3, "window:\n");
+ xf86PrintResList(3, w);
+ if (w_2nd)
+ xf86MsgVerb(X_INFO, 3, "2nd window:\n");
+ xf86PrintResList(3, w_2nd);
+ xf86ErrorFVerb(3,"avoid:\n");
+ xf86PrintResList(3,avoid);
+#endif
+ w_tmp = w;
+ while (w) {
+ if ((type & ResTypeMask) == (w->res_type & ResTypeMask)) {
+#ifdef DEBUG
+ ErrorF("block_begin: 0x%lx block_end: 0x%lx\n",w->block_begin,
+ w->block_end);
+#endif
+ range = xf86GetBlock(type,PCI_SIZE(type,tag,alignment + 1),
+ w->block_begin, w->block_end,
+ PCI_SIZE(type,tag,alignment),avoid);
+ if (range.type != ResEnd)
+ break;
+ }
+ w = w->next;
+ }
+ xf86FreeResList(w_tmp);
+ /* if unsuccessful and memory prefetchable try non-prefetchable */
+ if (range.type == ResEnd && w_2nd) {
+ w_tmp = w_2nd;
+ while (w_2nd) {
+ if ((type & ResTypeMask) == (w_2nd->res_type & ResTypeMask)) {
+#ifdef DEBUG
+ ErrorF("block_begin: 0x%lx block_end: 0x%lx\n",w_2nd->block_begin,
+ w_2nd->block_end);
+#endif
+ range = xf86GetBlock(type,PCI_SIZE(type,tag,alignment + 1),
+ w_2nd->block_begin, w_2nd->block_end,
+ PCI_SIZE(type,tag,alignment),avoid);
+ if (range.type != ResEnd)
+ break;
+ }
+ w_2nd = w_2nd->next;
+ }
+ xf86FreeResList(w_tmp);
+ }
+ xf86FreeResList(avoid);
+
+ if (range.type == ResEnd) {
+ xf86MsgVerb(X_ERROR,3,"Cannot find a replacement memory range\n");
+ xf86FreeResList(Acc);
+ Acc = orgAcc;
+ return FALSE;
+ }
+ xf86FreeResList(orgAcc);
+#ifdef DEBUG
+ ErrorF("begin: 0x%lx, end: 0x%lx\n",range.a,range.b);
+#endif
+
+ (*p_size) = 0;
+ while (alignment >> (*p_size))
+ (*p_size)++;
+ (*p_base) = H2B(tag,range.rBegin,type);
+#ifdef DEBUG
+ ErrorF("New PCI res %i base: 0x%lx, size: 0x%lx, type %s\n",
+ res_n,(*p_base),(1 << (*p_size)),
+ ((type & ResPhysMask) == ResMem) ? "Mem" : "Io");
+#endif
+ if (res_n != 0xff) {
+ if ((type & ResPhysMask) == ResMem)
+ pvp->memBase[prt] = range.rBegin;
+ else
+ pvp->ioBase[prt] = range.rBegin;
+ ((CARD32 *)(&(pcp->pci_base0)))[res_n] =
+ (CARD32)(*p_base) | (CARD32)(p_type);
+ pciWriteLong(tag, PCI_CMD_BASE_REG + res_n * sizeof(CARD32),
+ ((CARD32 *)(&(pcp->pci_base0)))[res_n]);
+ if (PCI_MAP_IS64BITMEM(p_type)) {
+#if defined(LONG64) || defined(WORD64)
+ ((CARD32 *)(&(pcp->pci_base0)))[res_n + 1] =
+ (CARD32)(*p_base >> 32);
+ pciWriteLong(tag, PCI_CMD_BASE_REG + (res_n + 1) * sizeof(CARD32),
+ ((CARD32 *)(&(pcp->pci_base0)))[res_n + 1]);
+#else
+ ((CARD32 *)(&(pcp->pci_base0)))[res_n + 1] = 0;
+ pciWriteLong(tag, PCI_CMD_BASE_REG + (res_n + 1) * sizeof(CARD32),
+ 0);
+#endif
+ }
+ } else {
+ pvp->biosBase = range.rBegin;
+ pcp->pci_baserom = (pciReadLong(tag,PCI_CMD_BIOS_REG) & 0x01) |
+ (CARD32)(*p_base);
+ pciWriteLong(tag, PCI_CMD_BIOS_REG, pcp->pci_baserom);
+ }
+ /* @@@ fake BIOS allocated resource */
+ range.type |= ResBios;
+ Acc = xf86AddResToList(Acc, &range,-1);
+
+ return TRUE;
+
+}
+
+Bool
+xf86FixPciResource(int entityIndex, int prt, memType alignment,
+ unsigned long type)
+{
+ pciVideoPtr pvp = xf86GetPciInfoForEntity(entityIndex);
+ return fixPciResource(prt, alignment, pvp, type);
+}
+
+resPtr
+xf86ReallocatePciResources(int entityIndex, resPtr pRes)
+{
+ pciVideoPtr pvp = xf86GetPciInfoForEntity(entityIndex);
+ resPtr pBad = NULL,pResTmp;
+ unsigned int prt = 0;
+ int i;
+
+ if (!pvp) return pRes;
+
+ while (pRes) {
+ switch (pRes->res_type & ResPhysMask) {
+ case ResMem:
+ if (pRes->block_begin == B2M(TAG(pvp),pvp->biosBase) &&
+ pRes->block_end == B2M(TAG(pvp),pvp->biosBase
+ + SIZE(pvp->biosSize)))
+ prt = 6;
+ else for (i = 0 ; i < 6; i++)
+ if ((pRes->block_begin == B2M(TAG(pvp),pvp->memBase[i]))
+ && (pRes->block_end == B2M(TAG(pvp),pvp->memBase[i]
+ + SIZE(pvp->size[i])))) {
+ prt = i;
+ break;
+ }
+ break;
+ case ResIo:
+ for (i = 0 ; i < 6; i++)
+ if (pRes->block_begin == B2I(TAG(pvp),pvp->ioBase[i])
+ && pRes->block_end == B2I(TAG(pvp),pvp->ioBase[i]
+ + SIZE(pvp->size[i]))) {
+ prt = i;
+ break;
+ }
+ break;
+ }
+
+ if (!prt) return pRes;
+
+ pResTmp = pRes->next;
+ if (! fixPciResource(prt, 0, pvp, pRes->res_type)) {
+ pRes->next = pBad;
+ pBad = pRes;
+ } else
+ xfree(pRes);
+
+ pRes = pResTmp;
+ }
+ return pBad;
+}
+
+/*
+ * BIOS releated
+ */
+memType
+getValidBIOSBase(PCITAG tag, int num)
+{
+ pciVideoPtr pvp = NULL;
+ PciBusPtr pbp;
+ resPtr m = NULL;
+ resPtr tmp, avoid, mem = NULL;
+ resRange range;
+ memType ret;
+ int n = 0;
+ int i;
+ CARD32 biosSize, alignment;
+
+ if (!xf86PciVideoInfo) return 0;
+
+ while ((pvp = xf86PciVideoInfo[n++])) {
+ if (pciTag(pvp->bus,pvp->device,pvp->func) == tag)
+ break;
+ }
+ if (!pvp) return 0;
+
+ biosSize = pvp->biosSize;
+ alignment = (1 << biosSize) - 1;
+ if (biosSize > 24)
+ biosSize = 24;
+
+ switch ((romBaseSource)num) {
+ case ROM_BASE_PRESET:
+ return 0; /* This should not happen */
+ case ROM_BASE_BIOS:
+ /* In some cases the BIOS base register contains the size mask */
+ if ((memType)(-1 << biosSize) == PCIGETROM(pvp->biosBase))
+ return 0;
+ /* Make sure we don't conflict with our own mem resources */
+ for (i = 0; i < 6; i++) {
+ if (!pvp->memBase[i])
+ continue;
+ P_M_RANGE(range,TAG(pvp),pvp->memBase[i],pvp->size[i],
+ ResExcMemBlock);
+ mem = xf86AddResToList(mem,&range,-1);
+ }
+ P_M_RANGE(range, TAG(pvp),pvp->biosBase,biosSize,ResExcMemBlock);
+ ret = pvp->biosBase;
+ break;
+ case ROM_BASE_MEM0:
+ case ROM_BASE_MEM1:
+ case ROM_BASE_MEM2:
+ case ROM_BASE_MEM3:
+ case ROM_BASE_MEM4:
+ case ROM_BASE_MEM5:
+ if (!pvp->memBase[num] || (pvp->size[num] < biosSize))
+ return 0;
+ P_M_RANGE(range, TAG(pvp),pvp->memBase[num],biosSize,
+ ResExcMemBlock);
+ ret = pvp->memBase[num];
+ break;
+ case ROM_BASE_FIND:
+ ret = 0;
+ break;
+ default:
+ return 0; /* This should not happen */
+ }
+
+ /* Now find the ranges for validation */
+ avoid = xf86DupResList(pciAvoidRes);
+ pbp = xf86PciBus;
+ while (pbp) {
+ if (pbp->secondary == pvp->bus) {
+ if (pbp->preferred_pmem)
+ tmp = xf86DupResList(pbp->preferred_pmem);
+ else
+ tmp = xf86DupResList(pbp->pmem);
+ m = xf86JoinResLists(m,tmp);
+ if (pbp->preferred_mem)
+ tmp = xf86DupResList(pbp->preferred_mem);
+ else
+ tmp = xf86DupResList(pbp->mem);
+ m = xf86JoinResLists(m,tmp);
+ tmp = m;
+ while (tmp) {
+ tmp->block_end = MIN(tmp->block_end,PCI_MEM32_LENGTH_MAX);
+ tmp = tmp->next;
+ }
+ } else if ((pbp->primary == pvp->bus) &&
+ (pbp->secondary >= 0) &&
+ (pbp->primary != pbp->secondary)) {
+ tmp = xf86DupResList(pbp->preferred_pmem);
+ avoid = xf86JoinResLists(avoid, tmp);
+ tmp = xf86DupResList(pbp->pmem);
+ avoid = xf86JoinResLists(avoid, tmp);
+ tmp = xf86DupResList(pbp->preferred_mem);
+ avoid = xf86JoinResLists(avoid, tmp);
+ tmp = xf86DupResList(pbp->mem);
+ avoid = xf86JoinResLists(avoid, tmp);
+ }
+ pbp = pbp->next;
+ }
+ pciConvertListToHost(pvp->bus,pvp->device,pvp->func, avoid);
+ if (mem)
+ pciConvertListToHost(pvp->bus,pvp->device,pvp->func, mem);
+
+ if (!ret) {
+ /* Return a possible window */
+ while (m) {
+ range = xf86GetBlock(RANGE_TYPE(ResExcMemBlock, xf86GetPciDomain(tag)),
+ PCI_SIZE(ResMem, TAG(pvp), 1 << biosSize),
+ m->block_begin, m->block_end,
+ PCI_SIZE(ResMem, TAG(pvp), alignment),
+ avoid);
+ if (range.type != ResEnd) {
+ ret = M2B(TAG(pvp), range.rBase);
+ break;
+ }
+ m = m->next;
+ }
+ } else {
+ if (!xf86IsSubsetOf(range, m) ||
+ ChkConflict(&range, avoid, SETUP)
+ || (mem && ChkConflict(&range, mem, SETUP)))
+ ret = 0;
+ }
+
+ xf86FreeResList(avoid);
+ xf86FreeResList(m);
+ return ret;
+}
+
+/*
+ * xf86Bus.c interface
+ */
+
+void
+xf86PciProbe(void)
+{
+ /*
+ * Initialise the pcidata entry points.
+ */
+#ifdef XFree86LOADER
+ xf86SetupPciIds = (ScanPciSetupProcPtr)LoaderSymbol("ScanPciSetupPciIds");
+ xf86ClosePciIds = (ScanPciCloseProcPtr)LoaderSymbol("ScanPciClosePciIds");
+ xf86FindPciNamesByDevice =
+ (ScanPciFindByDeviceProcPtr)LoaderSymbol("ScanPciFindPciNamesByDevice");
+ xf86FindPciNamesBySubsys =
+ (ScanPciFindBySubsysProcPtr)LoaderSymbol("ScanPciFindPciNamesBySubsys");
+ xf86FindPciClassBySubsys =
+ (ScanPciFindClassBySubsysProcPtr)LoaderSymbol("ScanPciFindPciClassBySubsys");
+ xf86FindPciClassByDevice =
+ (ScanPciFindClassByDeviceProcPtr)LoaderSymbol("ScanPciFindPciClassByDevice");
+#else
+ xf86SetupPciIds = ScanPciSetupPciIds;
+ xf86ClosePciIds = ScanPciClosePciIds;
+ xf86FindPciNamesByDevice = ScanPciFindPciNamesByDevice;
+ xf86FindPciNamesBySubsys = ScanPciFindPciNamesBySubsys;
+ xf86FindPciClassBySubsys = ScanPciFindPciClassBySubsys;
+ xf86FindPciClassByDevice = ScanPciFindPciClassByDevice;
+#endif
+
+ if (!xf86SetupPciIds())
+ FatalError("xf86SetupPciIds() failed\n");
+
+ FindPCIVideoInfo();
+}
+
+static void alignBridgeRanges(PciBusPtr PciBusBase, PciBusPtr primary);
+
+static void
+printBridgeInfo(PciBusPtr PciBus)
+{
+ char primary[8], secondary[8], subordinate[8], brbus[8];
+
+ xf86FormatPciBusNumber(PciBus->primary, primary);
+ xf86FormatPciBusNumber(PciBus->secondary, secondary);
+ xf86FormatPciBusNumber(PciBus->subordinate, subordinate);
+ xf86FormatPciBusNumber(PciBus->brbus, brbus);
+
+ xf86MsgVerb(X_INFO, 3, "Bus %s: bridge is at (%s:%d:%d), (%s,%s,%s),"
+ " BCTRL: 0x%04x (VGA_EN is %s)\n",
+ secondary, brbus, PciBus->brdev, PciBus->brfunc,
+ primary, secondary, subordinate, PciBus->brcontrol,
+ (PciBus->brcontrol & PCI_PCI_BRIDGE_VGA_EN) ?
+ "set" : "cleared");
+ if (PciBus->preferred_io) {
+ xf86MsgVerb(X_INFO, 3,
+ "Bus %s I/O range:\n", secondary);
+ xf86PrintResList(3, PciBus->preferred_io);
+ }
+ if (PciBus->preferred_mem) {
+ xf86MsgVerb(X_INFO, 3,
+ "Bus %s non-prefetchable memory range:\n", secondary);
+ xf86PrintResList(3, PciBus->preferred_mem);
+ }
+ if (PciBus->preferred_pmem) {
+ xf86MsgVerb(X_INFO, 3,
+ "Bus %s prefetchable memory range:\n", secondary);
+ xf86PrintResList(3, PciBus->preferred_pmem);
+ }
+}
+
+static PciBusPtr
+xf86GetPciBridgeInfo(void)
+{
+ const pciConfigPtr *pcrpp;
+ pciConfigPtr pcrp;
+ pciBusInfo_t *pBusInfo;
+ resRange range;
+ PciBusPtr PciBus, PciBusBase = NULL;
+ PciBusPtr *pnPciBus = &PciBusBase;
+ int MaxBus = 0;
+ int i, domain;
+ int primary, secondary, subordinate;
+ memType base, limit;
+
+ resPtr pciBusAccWindows = xf86PciBusAccWindowsFromOS();
+
+ if (xf86PciInfo == NULL)
+ return NULL;
+
+ /* Add each bridge */
+ for (pcrpp = xf86PciInfo, pcrp = *pcrpp; pcrp; pcrp = *(++pcrpp)) {
+ if (pcrp->busnum > MaxBus)
+ MaxBus = pcrp->busnum;
+ if ((pcrp->pci_base_class == PCI_CLASS_BRIDGE) ||
+ (((pcrp->listed_class >> 8) & 0xff) == PCI_CLASS_BRIDGE)) {
+ int sub_class;
+ sub_class = (pcrp->listed_class & 0xffff) ?
+ (pcrp->listed_class & 0xff) : pcrp->pci_sub_class;
+ domain = xf86GetPciDomain(pcrp->tag);
+
+ switch (sub_class) {
+ case PCI_SUBCLASS_BRIDGE_PCI:
+ /* something fishy about the header? If so: just ignore! */
+ if ((pcrp->pci_header_type & 0x7f) != 0x01) {
+ xf86MsgVerb(X_WARNING, 3, "PCI-PCI bridge at %x:%x:%x has"
+ " unexpected header: 0x%x",
+ pcrp->busnum, pcrp->devnum,
+ pcrp->funcnum, pcrp->pci_header_type);
+ break;
+ }
+
+ domain = pcrp->busnum & 0x0000FF00;
+ primary = pcrp->busnum;
+ secondary = domain | pcrp->pci_secondary_bus_number;
+ subordinate = domain | pcrp->pci_subordinate_bus_number;
+
+ /* Is this the correct bridge? If not, ignore it */
+ pBusInfo = pcrp->businfo;
+ if (pBusInfo && (pcrp != pBusInfo->bridge)) {
+ xf86MsgVerb(X_WARNING, 3, "PCI bridge mismatch for bus %x:"
+ " %x:%x:%x and %x:%x:%x\n", secondary,
+ pcrp->busnum, pcrp->devnum, pcrp->funcnum,
+ pBusInfo->bridge->busnum,
+ pBusInfo->bridge->devnum,
+ pBusInfo->bridge->funcnum);
+ break;
+ }
+
+ if (pBusInfo && pBusInfo->funcs->pciGetBridgeBusses)
+ (*pBusInfo->funcs->pciGetBridgeBusses)(secondary,
+ &primary,
+ &secondary,
+ &subordinate);
+
+ if (!pcrp->fakeDevice && (primary >= secondary)) {
+ xf86MsgVerb(X_WARNING, 3, "Misconfigured PCI bridge"
+ " %x:%x:%x (%x,%x)\n",
+ pcrp->busnum, pcrp->devnum, pcrp->funcnum,
+ primary, secondary);
+ break;
+ }
+
+ *pnPciBus = PciBus = xnfcalloc(1, sizeof(PciBusRec));
+ pnPciBus = &PciBus->next;
+
+ PciBus->primary = primary;
+ PciBus->secondary = secondary;
+ PciBus->subordinate = subordinate;
+
+ PciBus->brbus = pcrp->busnum;
+ PciBus->brdev = pcrp->devnum;
+ PciBus->brfunc = pcrp->funcnum;
+
+ PciBus->subclass = sub_class;
+ PciBus->interface = pcrp->pci_prog_if;
+
+ if (pBusInfo && pBusInfo->funcs->pciControlBridge)
+ PciBus->brcontrol =
+ (*pBusInfo->funcs->pciControlBridge)(secondary, 0, 0);
+ else
+ PciBus->brcontrol = pcrp->pci_bridge_control;
+
+ if (pBusInfo && pBusInfo->funcs->pciGetBridgeResources) {
+ (*pBusInfo->funcs->pciGetBridgeResources)(secondary,
+ (pointer *)&PciBus->preferred_io,
+ (pointer *)&PciBus->preferred_mem,
+ (pointer *)&PciBus->preferred_pmem);
+ break;
+ }
+
+ if ((pcrp->pci_command & PCI_CMD_IO_ENABLE) &&
+ (pcrp->pci_upper_io_base || pcrp->pci_io_base ||
+ pcrp->pci_upper_io_limit || pcrp->pci_io_limit)) {
+ base = (pcrp->pci_upper_io_base << 16) |
+ ((pcrp->pci_io_base & 0xf0u) << 8);
+ limit = (pcrp->pci_upper_io_limit << 16) |
+ ((pcrp->pci_io_limit & 0xf0u) << 8) | 0x0fff;
+ /*
+ * Deal with bridge ISA mode (256 wide ranges spaced 1K
+ * apart, but only in the first 64K).
+ */
+ if (pcrp->pci_bridge_control & PCI_PCI_BRIDGE_ISA_EN) {
+ while ((base <= (CARD16)(-1)) && (base <= limit)) {
+ PCI_I_RANGE(range, pcrp->tag,
+ base, base + (CARD8)(-1),
+ ResIo | ResBlock | ResExclusive);
+ PciBus->preferred_io =
+ xf86AddResToList(PciBus->preferred_io,
+ &range, -1);
+ base += 0x0400;
+ }
+ }
+ if (base <= limit) {
+ PCI_I_RANGE(range, pcrp->tag, base, limit,
+ ResIo | ResBlock | ResExclusive);
+ PciBus->preferred_io =
+ xf86AddResToList(PciBus->preferred_io, &range, -1);
+ }
+ }
+ if (pcrp->pci_command & PCI_CMD_MEM_ENABLE) {
+ /*
+ * The P2P spec requires these next two, but some bridges
+ * don't comply. Err on the side of caution, making the not
+ * so bold assumption that no bridge would ever re-route the
+ * bottom megabyte.
+ */
+ if (pcrp->pci_mem_base || pcrp->pci_mem_limit) {
+ base = pcrp->pci_mem_base & 0xfff0u;
+ limit = pcrp->pci_mem_limit & 0xfff0u;
+ if (base <= limit) {
+ PCI_M_RANGE(range, pcrp->tag,
+ base << 16, (limit << 16) | 0x0fffff,
+ ResMem | ResBlock | ResExclusive);
+ PciBus->preferred_mem =
+ xf86AddResToList(PciBus->preferred_mem, &range, -1);
+ }
+ }
+
+ if (pcrp->pci_prefetch_mem_base ||
+ pcrp->pci_prefetch_mem_limit ||
+ pcrp->pci_prefetch_upper_mem_base ||
+ pcrp->pci_prefetch_upper_mem_limit) {
+ base = pcrp->pci_prefetch_mem_base & 0xfff0u;
+ limit = pcrp->pci_prefetch_mem_limit & 0xfff0u;
+#if defined(LONG64) || defined(WORD64)
+ base |= (memType)pcrp->pci_prefetch_upper_mem_base << 16;
+ limit |= (memType)pcrp->pci_prefetch_upper_mem_limit << 16;
+#endif
+ if (base <= limit) {
+ PCI_M_RANGE(range, pcrp->tag,
+ base << 16, (limit << 16) | 0xfffff,
+ ResMem | ResBlock | ResExclusive);
+ PciBus->preferred_pmem =
+ xf86AddResToList(PciBus->preferred_pmem,
+ &range, -1);
+ }
+ }
+ }
+ break;
+
+ case PCI_SUBCLASS_BRIDGE_CARDBUS:
+ /* something fishy about the header? If so: just ignore! */
+ if ((pcrp->pci_header_type & 0x7f) != 0x02) {
+ xf86MsgVerb(X_WARNING, 3, "PCI-CardBus bridge at %x:%x:%x"
+ " has unexpected header: 0x%x",
+ pcrp->busnum, pcrp->devnum,
+ pcrp->funcnum, pcrp->pci_header_type);
+ break;
+ }
+
+ domain = pcrp->busnum & 0x0000FF00;
+ primary = pcrp->busnum;
+ secondary = domain | pcrp->pci_cb_cardbus_bus_number;
+ subordinate = domain | pcrp->pci_subordinate_bus_number;
+
+ /* Is this the correct bridge? If not, ignore it */
+ pBusInfo = pcrp->businfo;
+ if (pBusInfo && (pcrp != pBusInfo->bridge)) {
+ xf86MsgVerb(X_WARNING, 3, "CardBus bridge mismatch for bus"
+ " %x: %x:%x:%x and %x:%x:%x\n", secondary,
+ pcrp->busnum, pcrp->devnum, pcrp->funcnum,
+ pBusInfo->bridge->busnum,
+ pBusInfo->bridge->devnum,
+ pBusInfo->bridge->funcnum);
+ break;
+ }
+
+ if (pBusInfo && pBusInfo->funcs->pciGetBridgeBusses)
+ (*pBusInfo->funcs->pciGetBridgeBusses)(secondary,
+ &primary,
+ &secondary,
+ &subordinate);
+
+ if (primary >= secondary) {
+ if (pcrp->pci_cb_cardbus_bus_number != 0)
+ xf86MsgVerb(X_WARNING, 3, "Misconfigured CardBus"
+ " bridge %x:%x:%x (%x,%x)\n",
+ pcrp->busnum, pcrp->devnum, pcrp->funcnum,
+ primary, secondary);
+ break;
+ }
+
+ *pnPciBus = PciBus = xnfcalloc(1, sizeof(PciBusRec));
+ pnPciBus = &PciBus->next;
+
+ PciBus->primary = primary;
+ PciBus->secondary = secondary;
+ PciBus->subordinate = subordinate;
+
+ PciBus->brbus = pcrp->busnum;
+ PciBus->brdev = pcrp->devnum;
+ PciBus->brfunc = pcrp->funcnum;
+
+ PciBus->subclass = sub_class;
+ PciBus->interface = pcrp->pci_prog_if;
+
+ if (pBusInfo && pBusInfo->funcs->pciControlBridge)
+ PciBus->brcontrol =
+ (*pBusInfo->funcs->pciControlBridge)(secondary, 0, 0);
+ else
+ PciBus->brcontrol = pcrp->pci_bridge_control;
+
+ if (pBusInfo && pBusInfo->funcs->pciGetBridgeResources) {
+ (*pBusInfo->funcs->pciGetBridgeResources)(secondary,
+ (pointer *)&PciBus->preferred_io,
+ (pointer *)&PciBus->preferred_mem,
+ (pointer *)&PciBus->preferred_pmem);
+ break;
+ }
+
+ if (pcrp->pci_command & PCI_CMD_IO_ENABLE) {
+ if (pcrp->pci_cb_iobase0) {
+ base = PCI_CB_IOBASE(pcrp->pci_cb_iobase0);
+ limit = PCI_CB_IOLIMIT(pcrp->pci_cb_iolimit0);
+
+ /*
+ * Deal with bridge ISA mode (256-wide ranges spaced 1K
+ * apart (start to start), but only in the first 64K).
+ */
+ if (pcrp->pci_bridge_control & PCI_PCI_BRIDGE_ISA_EN) {
+ while ((base <= (CARD16)(-1)) &&
+ (base <= limit)) {
+ PCI_I_RANGE(range, pcrp->tag,
+ base, base + (CARD8)(-1),
+ ResIo | ResBlock | ResExclusive);
+ PciBus->preferred_io =
+ xf86AddResToList(PciBus->preferred_io,
+ &range, -1);
+ base += 0x0400;
+ }
+ }
+
+ if (base <= limit) {
+ PCI_I_RANGE(range, pcrp->tag, base, limit,
+ ResIo | ResBlock | ResExclusive);
+ PciBus->preferred_io =
+ xf86AddResToList(PciBus->preferred_io,
+ &range, -1);
+ }
+ }
+
+ if (pcrp->pci_cb_iobase1) {
+ base = PCI_CB_IOBASE(pcrp->pci_cb_iobase1);
+ limit = PCI_CB_IOLIMIT(pcrp->pci_cb_iolimit1);
+
+ /*
+ * Deal with bridge ISA mode (256-wide ranges spaced 1K
+ * apart (start to start), but only in the first 64K).
+ */
+ if (pcrp->pci_bridge_control & PCI_PCI_BRIDGE_ISA_EN) {
+ while ((base <= (CARD16)(-1)) &&
+ (base <= limit)) {
+ PCI_I_RANGE(range, pcrp->tag,
+ base, base + (CARD8)(-1),
+ ResIo | ResBlock | ResExclusive);
+ PciBus->preferred_io =
+ xf86AddResToList(PciBus->preferred_io,
+ &range, -1);
+ base += 0x0400;
+ }
+ }
+
+ if (base <= limit) {
+ PCI_I_RANGE(range, pcrp->tag, base, limit,
+ ResIo | ResBlock | ResExclusive);
+ PciBus->preferred_io =
+ xf86AddResToList(PciBus->preferred_io,
+ &range, -1);
+ }
+ }
+ }
+
+ if (pcrp->pci_command & PCI_CMD_MEM_ENABLE) {
+ if ((pcrp->pci_cb_membase0) &&
+ (pcrp->pci_cb_membase0 <= pcrp->pci_cb_memlimit0)) {
+ PCI_M_RANGE(range, pcrp->tag,
+ pcrp->pci_cb_membase0 & ~0x0fff,
+ pcrp->pci_cb_memlimit0 | 0x0fff,
+ ResMem | ResBlock | ResExclusive);
+ if (pcrp->pci_bridge_control &
+ PCI_CB_BRIDGE_CTL_PREFETCH_MEM0)
+ PciBus->preferred_pmem =
+ xf86AddResToList(PciBus->preferred_pmem,
+ &range, -1);
+ else
+ PciBus->preferred_mem =
+ xf86AddResToList(PciBus->preferred_mem,
+ &range, -1);
+ }
+ if ((pcrp->pci_cb_membase1) &&
+ (pcrp->pci_cb_membase1 <= pcrp->pci_cb_memlimit1)) {
+ PCI_M_RANGE(range, pcrp->tag,
+ pcrp->pci_cb_membase1 & ~0x0fff,
+ pcrp->pci_cb_memlimit1 | 0x0fff,
+ ResMem | ResBlock | ResExclusive);
+ if (pcrp->pci_bridge_control &
+ PCI_CB_BRIDGE_CTL_PREFETCH_MEM1)
+ PciBus->preferred_pmem =
+ xf86AddResToList(PciBus->preferred_pmem,
+ &range, -1);
+ else
+ PciBus->preferred_mem =
+ xf86AddResToList(PciBus->preferred_mem,
+ &range, -1);
+ }
+ }
+
+ break;
+
+ case PCI_SUBCLASS_BRIDGE_ISA:
+ case PCI_SUBCLASS_BRIDGE_EISA:
+ case PCI_SUBCLASS_BRIDGE_MC:
+ *pnPciBus = PciBus = xnfcalloc(1, sizeof(PciBusRec));
+ pnPciBus = &PciBus->next;
+ PciBus->primary = pcrp->busnum;
+ PciBus->secondary = PciBus->subordinate = -1;
+ PciBus->brbus = pcrp->busnum;
+ PciBus->brdev = pcrp->devnum;
+ PciBus->brfunc = pcrp->funcnum;
+ PciBus->subclass = sub_class;
+ PciBus->brcontrol = PCI_PCI_BRIDGE_VGA_EN;
+ break;
+
+ case PCI_SUBCLASS_BRIDGE_HOST:
+ /* Is this the correct bridge? If not, ignore bus info */
+ pBusInfo = pcrp->businfo;
+ if (pBusInfo == HOST_NO_BUS)
+ break;
+
+ secondary = 0;
+ if (pBusInfo) {
+ /* Find "secondary" bus segment */
+ while (pBusInfo != pciBusInfo[secondary])
+ secondary++;
+ if (pcrp != pBusInfo->bridge) {
+ xf86MsgVerb(X_WARNING, 3, "Host bridge mismatch for"
+ " bus %x: %x:%x:%x and %x:%x:%x\n",
+ pBusInfo->primary_bus,
+ pcrp->busnum, pcrp->devnum, pcrp->funcnum,
+ pBusInfo->bridge->busnum,
+ pBusInfo->bridge->devnum,
+ pBusInfo->bridge->funcnum);
+ pBusInfo = NULL;
+ }
+ }
+
+ *pnPciBus = PciBus = xnfcalloc(1, sizeof(PciBusRec));
+ pnPciBus = &PciBus->next;
+
+ PciBus->primary = -1;
+ PciBus->secondary = -1; /* to be set below */
+ PciBus->subordinate = pciNumBuses - 1;
+
+ if (pBusInfo) {
+ PciBus->primary = PciBus->secondary = secondary;
+ if (pBusInfo->funcs->pciGetBridgeBusses)
+ (*pBusInfo->funcs->pciGetBridgeBusses)
+ (secondary,
+ &PciBus->primary,
+ &PciBus->secondary,
+ &PciBus->subordinate);
+ }
+
+ PciBus->brbus = pcrp->busnum;
+ PciBus->brdev = pcrp->devnum;
+ PciBus->brfunc = pcrp->funcnum;
+
+ PciBus->subclass = sub_class;
+
+ if (pBusInfo && pBusInfo->funcs->pciControlBridge)
+ PciBus->brcontrol =
+ (*pBusInfo->funcs->pciControlBridge)(secondary, 0, 0);
+ else
+ PciBus->brcontrol = PCI_PCI_BRIDGE_VGA_EN;
+
+ if (pBusInfo && pBusInfo->funcs->pciGetBridgeResources) {
+ (*pBusInfo->funcs->pciGetBridgeResources)
+ (secondary,
+ (pointer *)&PciBus->preferred_io,
+ (pointer *)&PciBus->preferred_mem,
+ (pointer *)&PciBus->preferred_pmem);
+ break;
+ }
+
+ PciBus->preferred_io =
+ xf86ExtractTypeFromList(pciBusAccWindows,
+ RANGE_TYPE(ResIo, domain));
+ PciBus->preferred_mem =
+ xf86ExtractTypeFromList(pciBusAccWindows,
+ RANGE_TYPE(ResMem, domain));
+ PciBus->preferred_pmem =
+ xf86ExtractTypeFromList(pciBusAccWindows,
+ RANGE_TYPE(ResMem, domain));
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ for (i = 0; i <= MaxBus; i++) { /* find PCI buses not attached to bridge */
+ if (!pciBusInfo[i])
+ continue;
+ for (PciBus = PciBusBase; PciBus; PciBus = PciBus->next)
+ if (PciBus->secondary == i) break;
+ if (!PciBus) { /* We assume it's behind a HOST-PCI bridge */
+ /*
+ * Find the 'smallest' free HOST-PCI bridge, where 'small' is in
+ * the order of pciTag().
+ */
+ PCITAG minTag = 0xFFFFFFFF, tag;
+ PciBusPtr PciBusFound = NULL;
+ for (PciBus = PciBusBase; PciBus; PciBus = PciBus->next)
+ if ((PciBus->subclass == PCI_SUBCLASS_BRIDGE_HOST) &&
+ (PciBus->secondary == -1) &&
+ ((tag = pciTag(PciBus->brbus,PciBus->brdev,PciBus->brfunc))
+ < minTag) ) {
+ minTag = tag;
+ PciBusFound = PciBus;
+ }
+ if (PciBusFound)
+ PciBusFound->secondary = i;
+ else { /* if nothing found it may not be visible: create new */
+ /* Find a device on this bus */
+ domain = 0;
+ for (pcrpp = xf86PciInfo; (pcrp = *pcrpp); pcrpp++) {
+ if (pcrp->busnum == i) {
+ domain = xf86GetPciDomain(pcrp->tag);
+ break;
+ }
+ }
+ *pnPciBus = PciBus = xnfcalloc(1, sizeof(PciBusRec));
+ pnPciBus = &PciBus->next;
+ PciBus->primary = PciBus->secondary = i;
+ PciBus->subclass = PCI_SUBCLASS_BRIDGE_HOST;
+ PciBus->brcontrol = PCI_PCI_BRIDGE_VGA_EN;
+ PciBus->preferred_io =
+ xf86ExtractTypeFromList(pciBusAccWindows,
+ RANGE_TYPE(ResIo, domain));
+ PciBus->preferred_mem =
+ xf86ExtractTypeFromList(pciBusAccWindows,
+ RANGE_TYPE(ResMem, domain));
+ PciBus->preferred_pmem =
+ xf86ExtractTypeFromList(pciBusAccWindows,
+ RANGE_TYPE(ResMem, domain));
+ }
+ }
+ }
+
+ for (PciBus = PciBusBase; PciBus; PciBus = PciBus->next) {
+ if (PciBus->primary == PciBus->secondary) {
+ alignBridgeRanges(PciBusBase, PciBus);
+ }
+ }
+
+ for (PciBus = PciBusBase; PciBus; PciBus = PciBus->next) {
+ switch (PciBus->subclass) {
+ case PCI_SUBCLASS_BRIDGE_PCI:
+ if (PciBus->interface == PCI_IF_BRIDGE_PCI_SUBTRACTIVE)
+ xf86MsgVerb(X_INFO, 3, "Subtractive PCI-to-PCI bridge:\n");
+ else
+ xf86MsgVerb(X_INFO, 3, "PCI-to-PCI bridge:\n");
+ break;
+ case PCI_SUBCLASS_BRIDGE_CARDBUS:
+ xf86MsgVerb(X_INFO, 3, "PCI-to-CardBus bridge:\n");
+ break;
+ case PCI_SUBCLASS_BRIDGE_HOST:
+ xf86MsgVerb(X_INFO, 3, "Host-to-PCI bridge:\n");
+ break;
+ case PCI_SUBCLASS_BRIDGE_ISA:
+ xf86MsgVerb(X_INFO, 3, "PCI-to-ISA bridge:\n");
+ break;
+ case PCI_SUBCLASS_BRIDGE_EISA:
+ xf86MsgVerb(X_INFO, 3, "PCI-to-EISA bridge:\n");
+ break;
+ case PCI_SUBCLASS_BRIDGE_MC:
+ xf86MsgVerb(X_INFO, 3, "PCI-to-MCA bridge:\n");
+ break;
+ default:
+ break;
+ }
+ printBridgeInfo(PciBus);
+ }
+ xf86FreeResList(pciBusAccWindows);
+ return PciBusBase;
+}
+
+static void
+alignBridgeRanges(PciBusPtr PciBusBase, PciBusPtr primary)
+{
+ PciBusPtr PciBus;
+
+ for (PciBus = PciBusBase; PciBus; PciBus = PciBus->next) {
+ if ((PciBus != primary) && (PciBus->primary != -1)
+ && (PciBus->primary == primary->secondary)) {
+ resPtr tmp;
+ tmp = xf86FindIntersectOfLists(primary->preferred_io,
+ PciBus->preferred_io);
+ xf86FreeResList(PciBus->preferred_io);
+ PciBus->preferred_io = tmp;
+ tmp = xf86FindIntersectOfLists(primary->preferred_pmem,
+ PciBus->preferred_pmem);
+ xf86FreeResList(PciBus->preferred_pmem);
+ PciBus->preferred_pmem = tmp;
+ tmp = xf86FindIntersectOfLists(primary->preferred_mem,
+ PciBus->preferred_mem);
+ xf86FreeResList(PciBus->preferred_mem);
+ PciBus->preferred_mem = tmp;
+
+ /* Deal with subtractive decoding */
+ switch (PciBus->subclass) {
+ case PCI_SUBCLASS_BRIDGE_PCI:
+ if (PciBus->interface != PCI_IF_BRIDGE_PCI_SUBTRACTIVE)
+ break;
+ /* Fall through */
+#if 0 /* Not yet */
+ case PCI_SUBCLASS_BRIDGE_ISA:
+ case PCI_SUBCLASS_BRIDGE_EISA:
+ case PCI_SUBCLASS_BRIDGE_MC:
+#endif
+ if (!(PciBus->io = primary->io))
+ PciBus->io = primary->preferred_io;
+ if (!(PciBus->mem = primary->mem))
+ PciBus->mem = primary->preferred_mem;
+ if (!(PciBus->pmem = primary->pmem))
+ PciBus->pmem = primary->preferred_pmem;
+ default:
+ break;
+ }
+
+ alignBridgeRanges(PciBusBase, PciBus);
+ }
+ }
+}
+
+void
+ValidatePci(void)
+{
+ pciVideoPtr pvp, pvp1;
+ PciBusPtr pbp;
+ pciConfigPtr pcrp, *pcrpp;
+ CARD32 *basep;
+ resPtr Sys;
+ resPtr Fix;
+ resRange range;
+ int n = 0, m, i;
+
+ if (!xf86PciVideoInfo) return;
+
+ /*
+ * Mark all pciInfoRecs that need to be validated. These are
+ * the ones which have been assigned to a screen.
+ */
+ Sys = xf86DupResList(osRes);
+ for (i=0; i<xf86NumScreens; i++) {
+ for (m = 0; m < xf86Screens[i]->numEntities; m++)
+ if ((pvp = xf86GetPciInfoForEntity(xf86Screens[i]->entityList[m])))
+ pvp->validate = TRUE;
+ }
+
+ /*
+ * Collect all background PCI resources we need to validate against.
+ * These are all resources which don't belong to PCINONSYSTEMCLASSES
+ * and which have not been assigned to an entity.
+ */
+ /* First get the PCIINFOCLASSES */
+ m = 0;
+ while ((pvp = xf86PciVideoInfo[m++])) {
+ /* is it a PCINONSYSTEMCLASS? */
+ if (PCINONSYSTEMCLASSES(pvp->class, pvp->subclass))
+ continue;
+ /* has it an Entity assigned to it? */
+ for (i=0; i<xf86NumEntities; i++) {
+ EntityPtr p = xf86Entities[i];
+ if (p->busType != BUS_PCI)
+ continue;
+ if (p->pciBusId.bus == pvp->bus
+ && p->pciBusId.device == pvp->device
+ && p->pciBusId.func == pvp->func)
+ break;
+ }
+ if (i != xf86NumEntities) /* found an Entity for this one */
+ continue;
+
+ for (i = 0; i<6; i++) {
+ if (pvp->ioBase[i]) {
+ PV_I_RANGE(range,pvp,i,ResExcIoBlock);
+ Sys = xf86AddResToList(Sys,&range,-1);
+ } else if (pvp->memBase[i]) {
+ PV_M_RANGE(range,pvp,i,ResExcMemBlock);
+ Sys = xf86AddResToList(Sys,&range,-1);
+ }
+ }
+ }
+ for (pcrpp = xf86PciInfo, pcrp = *pcrpp; pcrp; pcrp = *++(pcrpp)) {
+
+ if (PCIINFOCLASSES(pcrp->pci_base_class, pcrp->pci_sub_class))
+ continue;
+
+ if ((pcrp->pci_header_type & 0x7f) ||
+ !(pcrp->pci_command & (PCI_CMD_IO_ENABLE | PCI_CMD_MEM_ENABLE)))
+ continue;
+
+ basep = &pcrp->pci_base0;
+ for (i = 0; i < 6; i++) {
+ if (basep[i]) {
+ if (PCI_MAP_IS_IO(basep[i])) {
+ if (!(pcrp->pci_command & PCI_CMD_IO_ENABLE))
+ continue;
+ P_I_RANGE(range, pcrp->tag, PCIGETIO(basep[i]),
+ pcrp->basesize[i], ResExcIoBlock)
+ } else if (!PCI_MAP_IS64BITMEM(basep[i])) {
+ if (!(pcrp->pci_command & PCI_CMD_MEM_ENABLE))
+ continue;
+ P_M_RANGE(range, pcrp->tag, PCIGETMEMORY(basep[i]),
+ pcrp->basesize[i], ResExcMemBlock)
+ } else {
+ i++;
+#if defined(LONG64) || defined(WORD64)
+ if (!(pcrp->pci_command & PCI_CMD_MEM_ENABLE))
+ continue;
+ P_M_RANGE(range, pcrp->tag, PCIGETMEMORY64(basep[i-1]),
+ pcrp->basesize[i-1], ResExcMemBlock)
+#else
+ continue;
+#endif
+ }
+ Sys = xf86AddResToList(Sys, &range, -1);
+ }
+ }
+ if ((pcrp->pci_baserom) &&
+ (pcrp->pci_command & PCI_CMD_MEM_ENABLE) &&
+ (pcrp->pci_baserom & PCI_MAP_ROM_DECODE_ENABLE)) {
+ P_M_RANGE(range,pcrp->tag,PCIGETROM(pcrp->pci_baserom),
+ pcrp->basesize[6],ResExcMemBlock);
+ Sys = xf86AddResToList(Sys, &range, -1);
+ }
+ }
+#ifdef DEBUG
+ xf86MsgVerb(X_INFO, 3,"Sys:\n");
+ xf86PrintResList(3,Sys);
+#endif
+
+ /*
+ * The order the video devices are listed in is
+ * just right: the lower buses come first.
+ * This way we attempt to fix a conflict of
+ * a lower bus device with a higher bus device
+ * where we have more room to find different
+ * resources.
+ */
+ while ((pvp = xf86PciVideoInfo[n++])) {
+ resPtr res_mp = NULL, res_m_io = NULL;
+ resPtr NonSys;
+ resPtr tmp, avoid = NULL;
+
+ if (!pvp->validate) continue;
+ NonSys = xf86DupResList(Sys);
+ m = n;
+ while ((pvp1 = xf86PciVideoInfo[m++])) {
+ if (!pvp1->validate) continue;
+ for (i = 0; i<6; i++) {
+ if (pvp1->ioBase[i]) {
+ PV_I_RANGE(range,pvp1,i,ResExcIoBlock);
+ NonSys = xf86AddResToList(NonSys,&range,-1);
+ } else if (pvp1->memBase[i]) {
+ PV_M_RANGE(range,pvp1,i,ResExcMemBlock);
+ NonSys = xf86AddResToList(NonSys,&range,-1);
+ }
+ }
+ }
+#ifdef DEBUG
+ xf86MsgVerb(X_INFO, 3,"NonSys:\n");
+ xf86PrintResList(3,NonSys);
+#endif
+ pbp = xf86PciBus;
+ while (pbp) {
+ if (pbp->secondary == pvp->bus) {
+ if (pbp->preferred_pmem) {
+ /* keep prefetchable separate */
+ res_mp =
+ xf86FindIntersectOfLists(pbp->preferred_pmem, ResRange);
+ }
+ if (pbp->pmem) {
+ res_mp = xf86FindIntersectOfLists(pbp->pmem, ResRange);
+ }
+ if (pbp->preferred_mem) {
+ res_m_io =
+ xf86FindIntersectOfLists(pbp->preferred_mem, ResRange);
+ }
+ if (pbp->mem) {
+ res_m_io = xf86FindIntersectOfLists(pbp->mem, ResRange);
+ }
+ if (pbp->preferred_io) {
+ res_m_io = xf86JoinResLists(res_m_io,
+ xf86FindIntersectOfLists(pbp->preferred_io, ResRange));
+ }
+ if (pbp->io) {
+ res_m_io = xf86JoinResLists(res_m_io,
+ xf86FindIntersectOfLists(pbp->preferred_io, ResRange));
+ }
+ } else if ((pbp->primary == pvp->bus) &&
+ (pbp->secondary >= 0) &&
+ (pbp->primary != pbp->secondary)) {
+ tmp = xf86DupResList(pbp->preferred_pmem);
+ avoid = xf86JoinResLists(avoid, tmp);
+ tmp = xf86DupResList(pbp->preferred_mem);
+ avoid = xf86JoinResLists(avoid, tmp);
+ tmp = xf86DupResList(pbp->preferred_io);
+ avoid = xf86JoinResLists(avoid, tmp);
+ }
+ pbp = pbp->next;
+ }
+ if (res_m_io == NULL)
+ res_m_io = xf86DupResList(ResRange);
+
+ pciConvertListToHost(pvp->bus,pvp->device,pvp->func, avoid);
+
+#ifdef DEBUG
+ xf86MsgVerb(X_INFO, 3,"avoid:\n");
+ xf86PrintResList(3,avoid);
+ xf86MsgVerb(X_INFO, 3,"prefetchable Memory:\n");
+ xf86PrintResList(3,res_mp);
+ xf86MsgVerb(X_INFO, 3,"MEM/IO:\n");
+ xf86PrintResList(3,res_m_io);
+#endif
+ Fix = NULL;
+ for (i = 0; i < 6; i++) {
+ int j;
+ resPtr own = NULL;
+ for (j = i+1; j < 6; j++) {
+ if (pvp->ioBase[j]) {
+ PV_I_RANGE(range,pvp,j,ResExcIoBlock);
+ own = xf86AddResToList(own,&range,-1);
+ } else if (pvp->memBase[j]) {
+ PV_M_RANGE(range,pvp,j,ResExcMemBlock);
+ own = xf86AddResToList(own,&range,-1);
+ }
+ }
+#ifdef DEBUG
+ xf86MsgVerb(X_INFO, 3, "own:\n");
+ xf86PrintResList(3, own);
+#endif
+ if (pvp->ioBase[i]) {
+ PV_I_RANGE(range,pvp,i,ResExcIoBlock);
+ if (xf86IsSubsetOf(range,res_m_io)
+ && ! ChkConflict(&range,own,SETUP)
+ && ! ChkConflict(&range,avoid,SETUP)
+ && ! ChkConflict(&range,NonSys,SETUP)) {
+ xf86FreeResList(own);
+ continue;
+ }
+ xf86MsgVerb(X_WARNING, 0,
+ "****INVALID IO ALLOCATION**** b: 0x%lx e: 0x%lx "
+ "correcting\a\n", range.rBegin,range.rEnd);
+#ifdef DEBUG
+ sleep(2);
+#endif
+ fixPciResource(i, 0, pvp, range.type);
+ } else if (pvp->memBase[i]) {
+ PV_M_RANGE(range,pvp,i,ResExcMemBlock);
+ if (pvp->type[i] & PCI_MAP_MEMORY_CACHABLE) {
+ if (xf86IsSubsetOf(range,res_mp)
+ && ! ChkConflict(&range,own,SETUP)
+ && ! ChkConflict(&range,avoid,SETUP)
+ && ! ChkConflict(&range,NonSys,SETUP)) {
+ xf86FreeResList(own);
+ continue;
+ }
+ }
+ if (xf86IsSubsetOf(range,res_m_io)
+ && ! ChkConflict(&range,own,SETUP)
+ && ! ChkConflict(&range,avoid,SETUP)
+ && ! ChkConflict(&range,NonSys,SETUP)) {
+ xf86FreeResList(own);
+ continue;
+ }
+ xf86MsgVerb(X_WARNING, 0,
+ "****INVALID MEM ALLOCATION**** b: 0x%lx e: 0x%lx "
+ "correcting\a\n", range.rBegin,range.rEnd);
+ if (ChkConflict(&range,own,SETUP)) {
+ xf86MsgVerb(X_INFO,3,"own\n");
+ xf86PrintResList(3,own);
+ }
+ if (ChkConflict(&range,avoid,SETUP)) {
+ xf86MsgVerb(X_INFO,3,"avoid\n");
+ xf86PrintResList(3,avoid);
+ }
+ if (ChkConflict(&range,NonSys,SETUP)) {
+ xf86MsgVerb(X_INFO,3,"NonSys\n");
+ xf86PrintResList(3,NonSys);
+ }
+
+#ifdef DEBUG
+ sleep(2);
+#endif
+ fixPciResource(i, 0, pvp, range.type);
+ }
+ xf86FreeResList(own);
+ }
+ xf86FreeResList(avoid);
+ xf86FreeResList(NonSys);
+ xf86FreeResList(res_mp);
+ xf86FreeResList(res_m_io);
+ }
+ xf86FreeResList(Sys);
+}
+
+resList
+GetImplicitPciResources(int entityIndex)
+{
+ pciVideoPtr pvp;
+ int i;
+ resList list = NULL;
+ int num = 0;
+
+ if (! (pvp = xf86GetPciInfoForEntity(entityIndex))) return NULL;
+
+ for (i = 0; i < 6; i++) {
+ if (pvp->ioBase[i]) {
+ list = xnfrealloc(list,sizeof(resRange) * (++num));
+ PV_I_RANGE(list[num - 1],pvp,i,ResShrIoBlock | ResBios);
+ } else if (pvp->memBase[i]) {
+ list = xnfrealloc(list,sizeof(resRange) * (++num));
+ PV_M_RANGE(list[num - 1],pvp,i,ResShrMemBlock | ResBios);
+ }
+ }
+#if 0
+ if (pvp->biosBase) {
+ list = xnfrealloc(list,sizeof(resRange) * (++num));
+ PV_B_RANGE(list[num - 1],pvp,ResShrMemBlock | ResBios);
+ }
+#endif
+ list = xnfrealloc(list,sizeof(resRange) * (++num));
+ list[num - 1].type = ResEnd;
+
+ return list;
+}
+
+void
+initPciState(void)
+{
+ int i = 0;
+ int j = 0;
+ pciVideoPtr pvp;
+ pciAccPtr pcaccp;
+
+ if (xf86PciAccInfo != NULL)
+ return;
+
+ if (xf86PciVideoInfo == NULL)
+ return;
+
+ while ((pvp = xf86PciVideoInfo[i]) != NULL) {
+ i++;
+ j++;
+ xf86PciAccInfo = xnfrealloc(xf86PciAccInfo,
+ sizeof(pciAccPtr) * (j + 1));
+ xf86PciAccInfo[j] = NULL;
+ pcaccp = xf86PciAccInfo[j - 1] = xnfalloc(sizeof(pciAccRec));
+ pcaccp->busnum = pvp->bus;
+ pcaccp->devnum = pvp->device;
+ pcaccp->funcnum = pvp->func;
+ pcaccp->arg.tag = pciTag(pvp->bus, pvp->device, pvp->func);
+ pcaccp->arg.func =
+ (WriteProcPtr)pciLongFunc(pcaccp->arg.tag,WRITE);
+ pcaccp->ioAccess.AccessDisable = pciIoAccessDisable;
+ pcaccp->ioAccess.AccessEnable = pciIoAccessEnable;
+ pcaccp->ioAccess.arg = &pcaccp->arg;
+ pcaccp->io_memAccess.AccessDisable = pciIo_MemAccessDisable;
+ pcaccp->io_memAccess.AccessEnable = pciIo_MemAccessEnable;
+ pcaccp->io_memAccess.arg = &pcaccp->arg;
+ pcaccp->memAccess.AccessDisable = pciMemAccessDisable;
+ pcaccp->memAccess.AccessEnable = pciMemAccessEnable;
+ pcaccp->memAccess.arg = &pcaccp->arg;
+ if (PCISHAREDIOCLASSES(pvp->class, pvp->subclass))
+ pcaccp->ctrl = TRUE;
+ else
+ pcaccp->ctrl = FALSE;
+ savePciState(pcaccp->arg.tag, &pcaccp->save);
+ pcaccp->arg.ctrl = pcaccp->save.command;
+ }
+}
+
+/*
+ * initPciBusState() - fill out the BusAccRec for a PCI bus.
+ * Theory: each bus is associated with one bridge connecting it
+ * to its parent bus. The address of a bridge is therefore stored
+ * in the BusAccRec of the bus it connects to. Each bus can
+ * have several bridges connecting secondary buses to it. Only one
+ * of these bridges can be open. Therefore the status of a bridge
+ * associated with a bus is stored in the BusAccRec of the parent
+ * the bridge connects to. The first member of the structure is
+ * a pointer to a function that open access to this bus. This function
+ * receives a pointer to the structure itself as argument. This
+ * design should be common to BusAccRecs of any type of buses we
+ * support. The remeinder of the structure is bus type specific.
+ * In this case it contains a pointer to the structure of the
+ * parent bus. Thus enabling access to a specific bus is simple:
+ * 1. Close any bridge going to secondary buses.
+ * 2. Climb down the ladder and enable any bridge on buses
+ * on the path from the CPU to this bus.
+ */
+
+void
+initPciBusState(void)
+{
+ BusAccPtr pbap, pbap_tmp;
+ PciBusPtr pbp = xf86PciBus;
+ pciBusInfo_t *pBusInfo;
+
+ while (pbp) {
+ pbap = xnfcalloc(1,sizeof(BusAccRec));
+ pbap->busdep.pci.bus = pbp->secondary;
+ pbap->busdep.pci.primary_bus = pbp->primary;
+ pbap->busdep_type = BUS_PCI;
+ pbap->busdep.pci.acc = PCITAG_SPECIAL;
+
+ if ((pbp->secondary >= 0) && (pbp->secondary < pciNumBuses) &&
+ (pBusInfo = pciBusInfo[pbp->secondary]) &&
+ pBusInfo->funcs->pciControlBridge) {
+ pbap->type = BUS_PCI;
+ pbap->save_f = savePciDrvBusState;
+ pbap->restore_f = restorePciDrvBusState;
+ pbap->set_f = pciSetBusAccess;
+ pbap->enable_f = pciDrvBusAccessEnable;
+ pbap->disable_f = pciDrvBusAccessDisable;
+ savePciDrvBusState(pbap);
+ } else switch (pbp->subclass) {
+ case PCI_SUBCLASS_BRIDGE_HOST:
+ pbap->type = BUS_PCI;
+ pbap->set_f = pciSetBusAccess;
+ break;
+ case PCI_SUBCLASS_BRIDGE_PCI:
+ case PCI_SUBCLASS_BRIDGE_CARDBUS:
+ pbap->type = BUS_PCI;
+ pbap->save_f = savePciBusState;
+ pbap->restore_f = restorePciBusState;
+ pbap->set_f = pciSetBusAccess;
+ pbap->enable_f = pciBusAccessEnable;
+ pbap->disable_f = pciBusAccessDisable;
+ pbap->busdep.pci.acc = pciTag(pbp->brbus,pbp->brdev,pbp->brfunc);
+ pbap->busdep.pci.func =
+ (SetBitsProcPtr)pciLongFunc(pbap->busdep.pci.acc,SET_BITS);
+ savePciBusState(pbap);
+ break;
+ case PCI_SUBCLASS_BRIDGE_ISA:
+ case PCI_SUBCLASS_BRIDGE_EISA:
+ case PCI_SUBCLASS_BRIDGE_MC:
+ pbap->type = BUS_ISA;
+ pbap->set_f = pciSetBusAccess;
+ break;
+ }
+ pbap->next = xf86BusAccInfo;
+ xf86BusAccInfo = pbap;
+ pbp = pbp->next;
+ }
+
+ pbap = xf86BusAccInfo;
+
+ while (pbap) {
+ pbap->primary = NULL;
+ if (pbap->busdep_type == BUS_PCI
+ && pbap->busdep.pci.primary_bus > -1) {
+ pbap_tmp = xf86BusAccInfo;
+ while (pbap_tmp) {
+ if (pbap_tmp->busdep_type == BUS_PCI &&
+ pbap_tmp->busdep.pci.bus == pbap->busdep.pci.primary_bus) {
+ /* Don't create loops */
+ if (pbap == pbap_tmp)
+ break;
+ pbap->primary = pbap_tmp;
+ break;
+ }
+ pbap_tmp = pbap_tmp->next;
+ }
+ }
+ pbap = pbap->next;
+ }
+}
+
+void
+PciStateEnter(void)
+{
+ pciAccPtr paccp;
+ int i = 0;
+
+ if (xf86PciAccInfo == NULL)
+ return;
+
+ while ((paccp = xf86PciAccInfo[i]) != NULL) {
+ i++;
+ if (!paccp->ctrl)
+ continue;
+ savePciState(paccp->arg.tag, &paccp->save);
+ restorePciState(paccp->arg.tag, &paccp->restore);
+ paccp->arg.ctrl = paccp->restore.command;
+ }
+}
+
+void
+PciBusStateEnter(void)
+{
+ BusAccPtr pbap = xf86BusAccInfo;
+
+ while (pbap) {
+ if (pbap->save_f)
+ pbap->save_f(pbap);
+ pbap = pbap->next;
+ }
+}
+
+void
+PciStateLeave(void)
+{
+ pciAccPtr paccp;
+ int i = 0;
+
+ if (xf86PciAccInfo == NULL)
+ return;
+
+ while ((paccp = xf86PciAccInfo[i]) != NULL) {
+ i++;
+ if (!paccp->ctrl)
+ continue;
+ savePciState(paccp->arg.tag, &paccp->restore);
+ restorePciState(paccp->arg.tag, &paccp->save);
+ }
+}
+
+void
+PciBusStateLeave(void)
+{
+ BusAccPtr pbap = xf86BusAccInfo;
+
+ while (pbap) {
+ if (pbap->restore_f)
+ pbap->restore_f(pbap);
+ pbap = pbap->next;
+ }
+}
+
+void
+DisablePciAccess(void)
+{
+ int i = 0;
+ pciAccPtr paccp;
+ if (xf86PciAccInfo == NULL)
+ return;
+
+ while ((paccp = xf86PciAccInfo[i]) != NULL) {
+ i++;
+ if (!paccp->ctrl) /* disable devices that are under control initially*/
+ continue;
+ pciIo_MemAccessDisable(paccp->io_memAccess.arg);
+ }
+}
+
+void
+DisablePciBusAccess(void)
+{
+ BusAccPtr pbap = xf86BusAccInfo;
+
+ while (pbap) {
+ if (pbap->disable_f)
+ pbap->disable_f(pbap);
+ if (pbap->primary)
+ pbap->primary->current = NULL;
+ pbap = pbap->next;
+ }
+}
+
+/*
+ * Public functions
+ */
+
+Bool
+xf86IsPciDevPresent(int bus, int dev, int func)
+{
+ int i = 0;
+ pciConfigPtr pcp;
+
+ while ((pcp = xf86PciInfo[i]) != NULL) {
+ if ((pcp->busnum == bus)
+ && (pcp->devnum == dev)
+ && (pcp->funcnum == func))
+ return TRUE;
+ i++;
+ }
+ return FALSE;
+}
+
+/*
+ * If the slot requested is already in use, return -1.
+ * Otherwise, claim the slot for the screen requesting it.
+ */
+
+int
+xf86ClaimPciSlot(int bus, int device, int func, DriverPtr drvp,
+ int chipset, GDevPtr dev, Bool active)
+{
+ EntityPtr p = NULL;
+ pciAccPtr *ppaccp = xf86PciAccInfo;
+ BusAccPtr pbap = xf86BusAccInfo;
+
+ int num;
+
+ if (xf86CheckPciSlot(bus, device, func)) {
+ num = xf86AllocateEntity();
+ p = xf86Entities[num];
+ p->driver = drvp;
+ p->chipset = chipset;
+ p->busType = BUS_PCI;
+ p->pciBusId.bus = bus;
+ p->pciBusId.device = device;
+ p->pciBusId.func = func;
+ p->active = active;
+ p->inUse = FALSE;
+ if (dev)
+ xf86AddDevToEntity(num, dev);
+ /* Here we initialize the access structure */
+ p->access = xnfcalloc(1,sizeof(EntityAccessRec));
+ while (ppaccp && *ppaccp) {
+ if ((*ppaccp)->busnum == bus
+ && (*ppaccp)->devnum == device
+ && (*ppaccp)->funcnum == func) {
+ p->access->fallback = &(*ppaccp)->io_memAccess;
+ p->access->pAccess = &(*ppaccp)->io_memAccess;
+ (*ppaccp)->ctrl = TRUE; /* mark control if not already */
+ break;
+ }
+ ppaccp++;
+ }
+ if (!ppaccp || !*ppaccp) {
+ p->access->fallback = &AccessNULL;
+ p->access->pAccess = &AccessNULL;
+ }
+
+ p->busAcc = NULL;
+ while (pbap) {
+ if (pbap->type == BUS_PCI && pbap->busdep.pci.bus == bus)
+ p->busAcc = pbap;
+ pbap = pbap->next;
+ }
+ fixPciSizeInfo(num);
+
+ /* in case bios is enabled disable it */
+ disablePciBios(pciTag(bus,device,func));
+ pciSlotClaimed = TRUE;
+
+ if (active) {
+ /* Map in this domain's I/O space */
+ p->domainIO = xf86MapDomainIO(-1, VIDMEM_MMIO,
+ pciTag(bus, device, func), 0, 1);
+ }
+
+ return num;
+ } else
+ return -1;
+}
+
+/*
+ * Get xf86PciVideoInfo for a driver.
+ */
+pciVideoPtr *
+xf86GetPciVideoInfo(void)
+{
+ return xf86PciVideoInfo;
+}
+
+/* --- Used by ATI driver, but also more generally useful */
+
+/*
+ * Get the full xf86scanpci data.
+ */
+pciConfigPtr *
+xf86GetPciConfigInfo(void)
+{
+ return xf86PciInfo;
+}
+
+/*
+ * Enable a device and route VGA to it. This is intended for a driver's
+ * Probe(), before creating EntityRec's. Only one device can be thus enabled
+ * at any one time, and should be disabled when the driver is done with it.
+ *
+ * The following special calls are also available:
+ *
+ * pvp == NULL && rt == NONE disable previously enabled device
+ * pvp != NULL && rt == NONE ensure device is disabled
+ * pvp == NULL && rt != NONE disable >all< subsequent calls to this function
+ * (done from xf86PostProbe())
+ * The last combination has been removed! To do this cleanly we have
+ * to implement stages and need to test at each stage dependent function
+ * if it is allowed to execute.
+ *
+ * The device represented by pvp may not have been previously claimed.
+ */
+void
+xf86SetPciVideo(pciVideoPtr pvp, resType rt)
+{
+ static BusAccPtr pbap = NULL;
+ static xf86AccessPtr pAcc = NULL;
+ static Bool DoneProbes = FALSE;
+ pciAccPtr pcaccp;
+ int i;
+
+ if (DoneProbes)
+ return;
+
+ /* Disable previous access */
+ if (pAcc) {
+ if (pAcc->AccessDisable)
+ (*pAcc->AccessDisable)(pAcc->arg);
+ pAcc = NULL;
+ }
+ if (pbap) {
+ while (pbap->primary) {
+ if (pbap->disable_f)
+ (*pbap->disable_f)(pbap);
+ pbap->primary->current = NULL;
+ pbap = pbap->primary;
+ }
+ pbap = NULL;
+ }
+
+ /* Check for xf86PostProbe's magic combo */
+ if (!pvp) {
+ if (rt != NONE)
+ DoneProbes = TRUE;
+ return;
+ }
+
+ /* Validate device */
+ if (!xf86PciVideoInfo || !xf86PciAccInfo || !xf86BusAccInfo)
+ return;
+
+ for (i = 0; pvp != xf86PciVideoInfo[i]; i++)
+ if (!xf86PciVideoInfo[i])
+ return;
+
+ /* Ignore request for claimed adapters */
+ if (!xf86CheckPciSlot(pvp->bus, pvp->device, pvp->func))
+ return;
+
+ /* Find pciAccRec structure */
+ for (i = 0; ; i++) {
+ if (!(pcaccp = xf86PciAccInfo[i]))
+ return;
+ if ((pvp->bus == pcaccp->busnum) &&
+ (pvp->device == pcaccp->devnum) &&
+ (pvp->func == pcaccp->funcnum))
+ break;
+ }
+
+ if (rt == NONE) {
+ /* This is a call to ensure the adapter is disabled */
+ if (pcaccp->io_memAccess.AccessDisable)
+ (*pcaccp->io_memAccess.AccessDisable)(pcaccp->io_memAccess.arg);
+ return;
+ }
+
+ /* Find BusAccRec structure */
+ for (pbap = xf86BusAccInfo; ; pbap = pbap->next) {
+ if (!pbap)
+ return;
+ if (pvp->bus == pbap->busdep.pci.bus)
+ break;
+ }
+
+ /* Route VGA */
+ if (pbap->set_f)
+ (*pbap->set_f)(pbap);
+
+ /* Enable device */
+ switch (rt) {
+ case IO:
+ pAcc = &pcaccp->ioAccess;
+ break;
+ case MEM_IO:
+ pAcc = &pcaccp->io_memAccess;
+ break;
+ case MEM:
+ pAcc = &pcaccp->memAccess;
+ break;
+ default: /* no compiler noise */
+ break;
+ }
+
+ if (pAcc && pAcc->AccessEnable)
+ (*pAcc->AccessEnable)(pAcc->arg);
+}
+
+/*
+ * Parse a BUS ID string, and return the PCI bus parameters if it was
+ * in the correct format for a PCI bus id.
+ */
+
+Bool
+xf86ParsePciBusString(const char *busID, int *bus, int *device, int *func)
+{
+ /*
+ * The format is assumed to be "bus[@domain]:device[:func]", where domain,
+ * bus, device and func are decimal integers. domain and func may be
+ * omitted and assumed to be zero, although doing this isn't encouraged.
+ */
+
+ char *p, *s, *d;
+ const char *id;
+ int i;
+
+ if (StringToBusType(busID, &id) != BUS_PCI)
+ return FALSE;
+
+ s = xstrdup(id);
+ p = strtok(s, ":");
+ if (p == NULL || *p == 0) {
+ xfree(s);
+ return FALSE;
+ }
+ d = strpbrk(p, "@");
+ if (d != NULL) {
+ *(d++) = 0;
+ for (i = 0; d[i] != 0; i++) {
+ if (!isdigit(d[i])) {
+ xfree(s);
+ return FALSE;
+ }
+ }
+ }
+ for (i = 0; p[i] != 0; i++) {
+ if (!isdigit(p[i])) {
+ xfree(s);
+ return FALSE;
+ }
+ }
+ *bus = atoi(p);
+ if (d != NULL && *d != 0)
+ *bus += atoi(d) << 8;
+ p = strtok(NULL, ":");
+ if (p == NULL || *p == 0) {
+ xfree(s);
+ return FALSE;
+ }
+ for (i = 0; p[i] != 0; i++) {
+ if (!isdigit(p[i])) {
+ xfree(s);
+ return FALSE;
+ }
+ }
+ *device = atoi(p);
+ *func = 0;
+ p = strtok(NULL, ":");
+ if (p == NULL || *p == 0) {
+ xfree(s);
+ return TRUE;
+ }
+ for (i = 0; p[i] != 0; i++) {
+ if (!isdigit(p[i])) {
+ xfree(s);
+ return FALSE;
+ }
+ }
+ *func = atoi(p);
+ xfree(s);
+ return TRUE;
+}
+
+/*
+ * Compare a BUS ID string with a PCI bus id. Return TRUE if they match.
+ */
+
+Bool
+xf86ComparePciBusString(const char *busID, int bus, int device, int func)
+{
+ int ibus, idevice, ifunc;
+
+ if (xf86ParsePciBusString(busID, &ibus, &idevice, &ifunc)) {
+ return bus == ibus && device == idevice && func == ifunc;
+ } else {
+ return FALSE;
+ }
+}
+
+/*
+ * xf86IsPrimaryPci() -- return TRUE if primary device
+ * is PCI and bus, dev and func numbers match.
+ */
+
+Bool
+xf86IsPrimaryPci(pciVideoPtr pPci)
+{
+ if (primaryBus.type != BUS_PCI) return FALSE;
+ return (pPci->bus == primaryBus.id.pci.bus &&
+ pPci->device == primaryBus.id.pci.device &&
+ pPci->func == primaryBus.id.pci.func);
+}
+
+/*
+ * xf86CheckPciGAType() -- return type of PCI graphics adapter.
+ */
+int
+xf86CheckPciGAType(pciVideoPtr pPci)
+{
+ int i = 0;
+ pciConfigPtr pcp;
+
+ while ((pcp = xf86PciInfo[i]) != NULL) {
+ if (pPci->bus == pcp->busnum && pPci->device == pcp->devnum
+ && pPci->func == pcp->funcnum) {
+ if (pcp->pci_base_class == PCI_CLASS_PREHISTORIC &&
+ pcp->pci_sub_class == PCI_SUBCLASS_PREHISTORIC_VGA)
+ return PCI_CHIP_VGA ;
+ if (pcp->pci_base_class == PCI_CLASS_DISPLAY &&
+ pcp->pci_sub_class == PCI_SUBCLASS_DISPLAY_VGA) {
+ if (pcp->pci_prog_if == 0)
+ return PCI_CHIP_VGA ;
+ if (pcp->pci_prog_if == 1)
+ return PCI_CHIP_8514;
+ }
+ return -1;
+ }
+ i++;
+ }
+ return -1;
+}
+
+/*
+ * xf86GetPciInfoForEntity() -- Get the pciVideoRec of entity.
+ */
+pciVideoPtr
+xf86GetPciInfoForEntity(int entityIndex)
+{
+ pciVideoPtr *ppPci;
+ EntityPtr p = xf86Entities[entityIndex];
+
+ if (entityIndex >= xf86NumEntities
+ || p->busType != BUS_PCI) return NULL;
+
+ for (ppPci = xf86PciVideoInfo; *ppPci != NULL; ppPci++) {
+ if (p->pciBusId.bus == (*ppPci)->bus &&
+ p->pciBusId.device == (*ppPci)->device &&
+ p->pciBusId.func == (*ppPci)->func)
+ return (*ppPci);
+ }
+ return NULL;
+}
+
+int
+xf86GetPciEntity(int bus, int dev, int func)
+{
+ int i;
+
+ for (i = 0; i < xf86NumEntities; i++) {
+ EntityPtr p = xf86Entities[i];
+ if (p->busType != BUS_PCI) continue;
+
+ if (p->pciBusId.bus == bus &&
+ p->pciBusId.device == dev &&
+ p->pciBusId.func == func)
+ return i;
+ }
+ return -1;
+}
+
+/*
+ * xf86CheckPciMemBase() checks that the memory base value matches one of the
+ * PCI base address register values for the given PCI device.
+ */
+Bool
+xf86CheckPciMemBase(pciVideoPtr pPci, memType base)
+{
+ int i;
+
+ for (i = 0; i < 6; i++)
+ if (base == pPci->memBase[i])
+ return TRUE;
+ return FALSE;
+}
+
+/*
+ * Check if the slot requested is free. If it is already in use, return FALSE.
+ */
+
+Bool
+xf86CheckPciSlot(int bus, int device, int func)
+{
+ int i;
+ EntityPtr p;
+
+ for (i = 0; i < xf86NumEntities; i++) {
+ p = xf86Entities[i];
+ /* Check if this PCI slot is taken */
+ if (p->busType == BUS_PCI && p->pciBusId.bus == bus &&
+ p->pciBusId.device == device && p->pciBusId.func == func)
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * This used to load the scanpci module. The pcidata module is now used
+ * (which the server always loads early). The main difference between the
+ * two modules is size, and the scanpci module should only ever be loaded
+ * when the X server is run with the -scanpci flag.
+ *
+ * To make sure that the required information is present in the pcidata
+ * module, add a PCI_VENDOR_* macro for the relevant vendor to xf86PciInfo.h,
+ * and add the class override data to ../etc/extrapci.ids.
+ */
+
+static void
+getPciClassFlags(pciConfigPtr *pcrpp)
+{
+ pciConfigPtr pcrp;
+ int i = 0;
+
+ if (!pcrpp)
+ return;
+ while ((pcrp = pcrpp[i])) {
+ if (!(pcrp->listed_class =
+ xf86FindPciClassBySubsys(pcrp->pci_subsys_vendor,
+ pcrp->pci_subsys_card))) {
+ pcrp->listed_class =
+ xf86FindPciClassByDevice(pcrp->pci_vendor, pcrp->pci_device);
+ }
+ i++;
+ }
+}
+
+/*
+ * xf86FindPciVendorDevice() xf86FindPciClass(): These functions
+ * are meant to be used by the pci bios emulation. Some bioses
+ * need to see if there are _other_ chips of the same type around
+ * so by setting pvp_exclude one pci device can be explicitely
+ * _excluded if required.
+ */
+pciVideoPtr
+xf86FindPciDeviceVendor(CARD16 vendorID, CARD16 deviceID,
+ char n, pciVideoPtr pvp_exclude)
+{
+ pciVideoPtr pvp, *ppvp;
+ n++;
+
+ for (ppvp = xf86PciVideoInfo, pvp =*ppvp; pvp ; pvp = *(++ppvp)) {
+ if (pvp == pvp_exclude) continue;
+ if ((pvp->vendor == vendorID) && (pvp->chipType == deviceID)) {
+ if (!(--n)) break;
+ }
+ }
+ return pvp;
+}
+
+pciVideoPtr
+xf86FindPciClass(CARD8 intf, CARD8 subClass, CARD16 class,
+ char n, pciVideoPtr pvp_exclude)
+{
+ pciVideoPtr pvp, *ppvp;
+ n++;
+
+ for (ppvp = xf86PciVideoInfo, pvp =*ppvp; pvp ; pvp = *(++ppvp)) {
+ if (pvp == pvp_exclude) continue;
+ if ((pvp->interface == intf) && (pvp->subclass == subClass)
+ && (pvp->class == class)) {
+ if (!(--n)) break;
+ }
+ }
+ return pvp;
+}
+
+/*
+ * This attempts to detect a multi-device card and sets up a list
+ * of pci tags of the devices of this card. On some of these
+ * cards the BIOS is not visible from all chipsets. We therefore
+ * need to use the BIOS from a chipset where it is visible.
+ * We do the following heuristics:
+ * If we detect only identical pci devices on a bus we assume it's
+ * a multi-device card. This assumption isn't true always, however.
+ * One might just use identical cards on a bus. We therefore don't
+ * detect this situation when we set up the PCI video info. Instead
+ * we wait until an attempt to read the BIOS fails.
+ */
+int
+pciTestMultiDeviceCard(int bus, int dev, int func, PCITAG** pTag)
+{
+ pciConfigPtr *ppcrp = xf86PciInfo;
+ pciConfigPtr pcrp = NULL;
+ int i,j;
+ Bool multicard = FALSE;
+ Bool multifunc = FALSE;
+ char str[256];
+ char *str1;
+
+ str1 = str;
+ if (!pTag)
+ return 0;
+
+ *pTag = NULL;
+
+ for (i=0; i < 8; i++) {
+ j = 0;
+
+ while (ppcrp[j]) {
+ if (ppcrp[j]->busnum == bus && ppcrp[j]->funcnum == i) {
+ pcrp = ppcrp[j];
+ break;
+ }
+ j++;
+ }
+
+ if (!pcrp) return 0;
+
+ /*
+ * we check all functions here: since multifunc devices need
+ * to implement func 0 we catch all devices on the bus when
+ * i = 0
+ */
+ if (pcrp->pci_header_type &0x80)
+ multifunc = TRUE;
+
+ j = 0;
+
+ while (ppcrp[j]) {
+ if (ppcrp[j]->busnum == bus && ppcrp[j]->funcnum == i
+ && ppcrp[j]->devnum != pcrp->devnum) {
+ /* don't test subsys ID here. It might be set by POST
+ - however some cards might not have been POSTed */
+ if (ppcrp[j]->pci_device_vendor != pcrp->pci_device_vendor
+ || ppcrp[j]->pci_header_type != pcrp->pci_header_type )
+ return 0;
+ else
+ multicard = TRUE;
+ }
+ j++;
+ }
+ if (!multifunc)
+ break;
+ }
+
+ if (!multicard)
+ return 0;
+
+ j = 0;
+ i = 0;
+ while (ppcrp[i]) {
+ if (ppcrp[i]->busnum == bus && ppcrp[i]->funcnum == func) {
+ str1 += sprintf(str1,"[%x:%x:%x]",ppcrp[i]->busnum,
+ ppcrp[i]->devnum,ppcrp[i]->funcnum);
+ *pTag = xnfrealloc(*pTag,sizeof(PCITAG) * (j + 1));
+ (*pTag)[j++] = pciTag(ppcrp[i]->busnum,
+ ppcrp[i]->devnum,ppcrp[i]->funcnum);
+ }
+ i++;
+ }
+ xf86MsgVerb(X_INFO,3,"Multi Device Card detected: %s\n",str);
+ return j;
+}
+
+static void
+pciTagConvertRange2Host(PCITAG tag, resRange *pRange)
+{
+ if (!(pRange->type & ResBus))
+ return;
+
+ switch(pRange->type & ResPhysMask) {
+ case ResMem:
+ switch(pRange->type & ResExtMask) {
+ case ResBlock:
+ pRange->rBegin = pciBusAddrToHostAddr(tag,PCI_MEM, pRange->rBegin);
+ pRange->rEnd = pciBusAddrToHostAddr(tag,PCI_MEM, pRange->rEnd);
+ break;
+ case ResSparse:
+ pRange->rBase = pciBusAddrToHostAddr(tag,PCI_MEM_SPARSE_BASE,
+ pRange->rBegin);
+ pRange->rMask = pciBusAddrToHostAddr(tag,PCI_MEM_SPARSE_MASK,
+ pRange->rEnd);
+ break;
+ }
+ break;
+ case ResIo:
+ switch(pRange->type & ResExtMask) {
+ case ResBlock:
+ pRange->rBegin = pciBusAddrToHostAddr(tag,PCI_IO, pRange->rBegin);
+ pRange->rEnd = pciBusAddrToHostAddr(tag,PCI_IO, pRange->rEnd);
+ break;
+ case ResSparse:
+ pRange->rBase = pciBusAddrToHostAddr(tag,PCI_IO_SPARSE_BASE
+ , pRange->rBegin);
+ pRange->rMask = pciBusAddrToHostAddr(tag,PCI_IO_SPARSE_MASK
+ , pRange->rEnd);
+ break;
+ }
+ break;
+ }
+
+ /* Set domain number */
+ pRange->type &= ~(ResDomain | ResBus);
+ pRange->type |= xf86GetPciDomain(tag) << 24;
+}
+
+static void
+pciConvertListToHost(int bus, int dev, int func, resPtr list)
+{
+ PCITAG tag = pciTag(bus,dev,func);
+ while (list) {
+ pciTagConvertRange2Host(tag, &list->val);
+ list = list->next;
+ }
+}
+
+static void
+updateAccessInfoStatusControlInfo(PCITAG tag, CARD32 ctrl)
+{
+ int i;
+
+ if (!xf86PciAccInfo)
+ return;
+
+ for (i = 0; xf86PciAccInfo[i] != NULL; i++) {
+ if (xf86PciAccInfo[i]->arg.tag == tag)
+ xf86PciAccInfo[i]->arg.ctrl = ctrl;
+ }
+}
+
+void
+pciConvertRange2Host(int entityIndex, resRange *pRange)
+{
+ PCITAG tag;
+ pciVideoPtr pvp;
+
+ pvp = xf86GetPciInfoForEntity(entityIndex);
+ if (!pvp) return;
+ tag = TAG(pvp);
+ pciTagConvertRange2Host(tag, pRange);
+}
+
+
+#ifdef INCLUDE_DEPRECATED
+void
+xf86EnablePciBusMaster(pciVideoPtr pPci, Bool enable)
+{
+ CARD32 temp;
+ PCITAG tag;
+
+ if (!pPci) return;
+
+ tag = pciTag(pPci->bus, pPci->device, pPci->func);
+ temp = pciReadLong(tag, PCI_CMD_STAT_REG);
+ if (enable) {
+ updateAccessInfoStatusControlInfo(tag, temp | PCI_CMD_MASTER_ENABLE);
+ pciWriteLong(tag, PCI_CMD_STAT_REG, temp | PCI_CMD_MASTER_ENABLE);
+ } else {
+ updateAccessInfoStatusControlInfo(tag, temp & ~PCI_CMD_MASTER_ENABLE);
+ pciWriteLong(tag, PCI_CMD_STAT_REG, temp & ~PCI_CMD_MASTER_ENABLE);
+ }
+}
+#endif /* INCLUDE_DEPRECATED */
diff --git a/hw/xfree86/common/xf86pciBus.h b/hw/xfree86/common/xf86pciBus.h
new file mode 100644
index 000000000..fbe3fbe62
--- /dev/null
+++ b/hw/xfree86/common/xf86pciBus.h
@@ -0,0 +1,72 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86pciBus.h,v 3.8 2002/09/16 16:55:33 tsi Exp $ */
+
+#ifndef _XF86_PCI_BUS_H
+#define _XF86_PCI_BUS_H
+
+#define PCITAG_SPECIAL pciTag(0xFF,0xFF,0xFF)
+
+typedef struct {
+ CARD32 command;
+ CARD32 base[6];
+ CARD32 biosBase;
+} pciSave, *pciSavePtr;
+
+typedef void (*SetBitsProcPtr)(PCITAG, int, CARD32, CARD32);
+typedef void (*WriteProcPtr)(PCITAG, int, CARD32);
+
+typedef struct {
+ PCITAG tag;
+ WriteProcPtr func;
+ CARD32 ctrl;
+} pciArg;
+
+typedef struct {
+ int busnum;
+ int devnum;
+ int funcnum;
+ pciArg arg;
+ xf86AccessRec ioAccess;
+ xf86AccessRec io_memAccess;
+ xf86AccessRec memAccess;
+ pciSave save;
+ pciSave restore;
+ Bool ctrl;
+} pciAccRec, *pciAccPtr;
+
+typedef union {
+ CARD16 control;
+} pciBridgesSave, *pciBridgesSavePtr;
+
+typedef struct pciBusRec {
+ int brbus, brdev, brfunc; /* ID of the bridge to this bus */
+ int primary, secondary, subordinate;
+ int subclass; /* bridge type */
+ int interface;
+ resPtr preferred_io; /* I/O range */
+ resPtr preferred_mem; /* non-prefetchable memory range */
+ resPtr preferred_pmem; /* prefetchable memory range */
+ resPtr io; /* for subtractive PCI-PCI bridges */
+ resPtr mem;
+ resPtr pmem;
+ int brcontrol; /* bridge_control byte */
+ struct pciBusRec *next;
+} PciBusRec, *PciBusPtr;
+
+void xf86PciProbe(void);
+void ValidatePci(void);
+resList GetImplicitPciResources(int entityIndex);
+void initPciState(void);
+void initPciBusState(void);
+void DisablePciAccess(void);
+void DisablePciBusAccess(void);
+void PciStateEnter(void);
+void PciBusStateEnter(void);
+void PciStateLeave(void);
+void PciBusStateLeave(void);
+resPtr ResourceBrokerInitPci(resPtr *osRes);
+void pciConvertRange2Host(int entityIndex, resRange *pRange);
+void isaConvertRange2Host(resRange *pRange);
+
+extern pciAccPtr * xf86PciAccInfo;
+
+#endif /* _XF86_PCI_BUS_H */
diff --git a/hw/xfree86/common/xf86sbusBus.c b/hw/xfree86/common/xf86sbusBus.c
new file mode 100644
index 000000000..87042cb14
--- /dev/null
+++ b/hw/xfree86/common/xf86sbusBus.c
@@ -0,0 +1,705 @@
+/*
+ * SBUS bus-specific code.
+ *
+ * Copyright (C) 2000 Jakub Jelinek (jakub@redhat.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * JAKUB JELINEK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86sbusBus.c,v 3.7 2001/10/28 03:33:19 tsi Exp $ */
+
+#include <ctype.h>
+#include <stdio.h>
+#include <unistd.h>
+#include "X.h"
+#include "os.h"
+#include "xf86.h"
+#include "xf86Priv.h"
+#include "xf86_OSlib.h"
+#include "xf86Resources.h"
+#include "xf86cmap.h"
+
+#include "xf86Bus.h"
+
+#include "xf86sbusBus.h"
+#include "xf86Sbus.h"
+
+Bool sbusSlotClaimed = FALSE;
+
+static int xf86nSbusInfo;
+
+static void
+CheckSbusDevice(const char *device, int fbNum)
+{
+ int fd, i;
+ struct fbgattr fbattr;
+ sbusDevicePtr psdp;
+
+ fd = open(device, O_RDONLY, 0);
+ if (fd < 0)
+ return;
+ memset(&fbattr, 0, sizeof(fbattr));
+ if (ioctl(fd, FBIOGATTR, &fbattr) < 0) {
+ if (ioctl(fd, FBIOGTYPE, &fbattr.fbtype) < 0) {
+ close(fd);
+ return;
+ }
+ }
+ close(fd);
+ for (i = 0; sbusDeviceTable[i].devId; i++)
+ if (sbusDeviceTable[i].fbType == fbattr.fbtype.fb_type)
+ break;
+ if (! sbusDeviceTable[i].devId)
+ return;
+ xf86SbusInfo = xnfrealloc(xf86SbusInfo, sizeof(psdp) * (++xf86nSbusInfo + 1));
+ xf86SbusInfo[xf86nSbusInfo] = NULL;
+ xf86SbusInfo[xf86nSbusInfo - 1] = psdp = xnfcalloc(sizeof (sbusDevice), 1);
+ psdp->devId = sbusDeviceTable[i].devId;
+ psdp->fbNum = fbNum;
+ psdp->device = xnfstrdup(device);
+ psdp->width = fbattr.fbtype.fb_width;
+ psdp->height = fbattr.fbtype.fb_height;
+ psdp->fd = -1;
+}
+
+void
+xf86SbusProbe(void)
+{
+ int i, useProm = 0;
+ char fbDevName[32];
+ sbusDevicePtr psdp, *psdpp;
+
+ xf86SbusInfo = xalloc(sizeof(psdp));
+ *xf86SbusInfo = NULL;
+ for (i = 0; i < 32; i++) {
+ sprintf(fbDevName, "/dev/fb%d", i);
+ CheckSbusDevice(fbDevName, i);
+ }
+ if (sparcPromInit() >= 0) {
+ useProm = 1;
+ sparcPromAssignNodes();
+ }
+ for (psdpp = xf86SbusInfo; (psdp = *psdpp); psdpp++) {
+ for (i = 0; sbusDeviceTable[i].devId; i++)
+ if (sbusDeviceTable[i].devId == psdp->devId)
+ psdp->descr = sbusDeviceTable[i].descr;
+ /*
+ * If we can use PROM information and found the PROM node for this
+ * device, we can tell more about the card.
+ */
+ if (useProm && psdp->node.node) {
+ char *prop, *promPath;
+ int len, chiprev, vmsize;
+
+ switch (psdp->devId) {
+ case SBUS_DEVICE_MGX:
+ prop = sparcPromGetProperty(&psdp->node, "fb_size", &len);
+ if (prop && len == 4 && *(int *)prop == 0x400000)
+ psdp->descr = "Quantum 3D MGXplus with 4M VRAM";
+ break;
+ case SBUS_DEVICE_CG6:
+ chiprev = 0;
+ vmsize = 0;
+ prop = sparcPromGetProperty(&psdp->node, "chiprev", &len);
+ if (prop && len == 4)
+ chiprev = *(int *)prop;
+ prop = sparcPromGetProperty(&psdp->node, "vmsize", &len);
+ if (prop && len == 4)
+ vmsize = *(int *)prop;
+ switch (chiprev) {
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ psdp->descr = "Sun Double width GX"; break;
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ psdp->descr = "Sun Single width GX"; break;
+ case 11:
+ switch (vmsize) {
+ case 2:
+ psdp->descr = "Sun Turbo GX with 1M VSIMM"; break;
+ case 4:
+ psdp->descr = "Sun Turbo GX Plus"; break;
+ default:
+ psdp->descr = "Sun Turbo GX"; break;
+ }
+ }
+ break;
+ case SBUS_DEVICE_CG14:
+ prop = sparcPromGetProperty(&psdp->node, "reg", &len);
+ vmsize = 0;
+ if (prop && !(len % 12) && len > 0)
+ vmsize = *(int *)(prop + len - 4);
+ switch (vmsize) {
+ case 0x400000:
+ psdp->descr = "Sun SX with 4M VSIMM"; break;
+ case 0x800000:
+ psdp->descr = "Sun SX with 8M VSIMM"; break;
+ }
+ break;
+ case SBUS_DEVICE_LEO:
+ prop = sparcPromGetProperty(&psdp->node, "model", &len);
+ if (prop && len > 0 && !strstr(prop, "501-2503"))
+ psdp->descr = "Sun Turbo ZX";
+ break;
+ case SBUS_DEVICE_TCX:
+ if (sparcPromGetBool(&psdp->node, "tcx-8-bit"))
+ psdp->descr = "Sun TCX (8bit)";
+ else
+ psdp->descr = "Sun TCX (S24)";
+ break;
+ case SBUS_DEVICE_FFB:
+ prop = sparcPromGetProperty(&psdp->node, "name", &len);
+ chiprev = 0;
+ prop = sparcPromGetProperty(&psdp->node, "board_type", &len);
+ if (prop && len == 4)
+ chiprev = *(int *)prop;
+ if (strstr (prop, "afb")) {
+ if (chiprev == 3)
+ psdp->descr = "Sun|Elite3D-M6 Horizontal";
+ } else {
+ switch (chiprev) {
+ case 0x08:
+ psdp->descr = "Sun FFB 67MHz Creator"; break;
+ case 0x0b:
+ psdp->descr = "Sun FFB 67MHz Creator 3D"; break;
+ case 0x1b:
+ psdp->descr = "Sun FFB 75MHz Creator 3D"; break;
+ case 0x20:
+ case 0x28:
+ psdp->descr = "Sun FFB2 Vertical Creator"; break;
+ case 0x23:
+ case 0x2b:
+ psdp->descr = "Sun FFB2 Vertical Creator 3D"; break;
+ case 0x30:
+ psdp->descr = "Sun FFB2+ Vertical Creator"; break;
+ case 0x33:
+ psdp->descr = "Sun FFB2+ Vertical Creator 3D"; break;
+ case 0x40:
+ case 0x48:
+ psdp->descr = "Sun FFB2 Horizontal Creator"; break;
+ case 0x43:
+ case 0x4b:
+ psdp->descr = "Sun FFB2 Horizontal Creator 3D"; break;
+ }
+ }
+ break;
+ }
+
+ xf86Msg(X_PROBED, "SBUS:(0x%08x) %s", psdp->node.node, psdp->descr);
+ promPath = sparcPromNode2Pathname (&psdp->node);
+ if (promPath) {
+ xf86ErrorF(" at %s", promPath);
+ xfree(promPath);
+ }
+ } else
+ xf86Msg(X_PROBED, "SBUS: %s", psdp->descr);
+ xf86ErrorF("\n");
+ }
+ if (useProm)
+ sparcPromClose();
+}
+
+/*
+ * Parse a BUS ID string, and return the SBUS bus parameters if it was
+ * in the correct format for a SBUS bus id.
+ */
+
+Bool
+xf86ParseSbusBusString(const char *busID, int *fbNum)
+{
+ /*
+ * The format is assumed to be one of:
+ * "fbN", e.g. "fb1", which means the device corresponding to /dev/fbN
+ * "nameN", e.g. "cgsix0", which means Nth instance of card NAME
+ * "/prompath", e.g. "/sbus@0,10001000/cgsix@3,0" which is PROM pathname
+ * to the device.
+ */
+
+ const char *id;
+ int i, len;
+
+ if (StringToBusType(busID, &id) != BUS_SBUS)
+ return FALSE;
+
+ if (*id != '/') {
+ if (!strncmp (id, "fb", 2)) {
+ if (!isdigit(id[2]))
+ return FALSE;
+ *fbNum = atoi(id + 2);
+ return TRUE;
+ } else {
+ sbusDevicePtr *psdpp;
+ int devId;
+
+ for (i = 0, len = 0; sbusDeviceTable[i].devId; i++) {
+ len = strlen(sbusDeviceTable[i].promName);
+ if (!strncmp (sbusDeviceTable[i].promName, id, len)
+ && isdigit(id[len]))
+ break;
+ }
+ devId = sbusDeviceTable[i].devId;
+ if (!devId) return FALSE;
+ i = atoi(id + len);
+ for (psdpp = xf86SbusInfo; *psdpp; ++psdpp) {
+ if ((*psdpp)->devId != devId)
+ continue;
+ if (!i) {
+ *fbNum = (*psdpp)->fbNum;
+ return TRUE;
+ }
+ i--;
+ }
+ }
+ return FALSE;
+ }
+
+ if (sparcPromInit() >= 0) {
+ i = sparcPromPathname2Node(id);
+ sparcPromClose();
+ if (i) {
+ sbusDevicePtr *psdpp;
+ for (psdpp = xf86SbusInfo; *psdpp; ++psdpp) {
+ if ((*psdpp)->node.node == i) {
+ *fbNum = (*psdpp)->fbNum;
+ return TRUE;
+ }
+ }
+ }
+ }
+ return FALSE;
+}
+
+/*
+ * Compare a BUS ID string with a SBUS bus id. Return TRUE if they match.
+ */
+
+Bool
+xf86CompareSbusBusString(const char *busID, int fbNum)
+{
+ int iFbNum;
+
+ if (xf86ParseSbusBusString(busID, &iFbNum)) {
+ return fbNum == iFbNum;
+ } else {
+ return FALSE;
+ }
+}
+
+/*
+ * Check if the slot requested is free. If it is already in use, return FALSE.
+ */
+
+Bool
+xf86CheckSbusSlot(int fbNum)
+{
+ int i;
+ EntityPtr p;
+
+ for (i = 0; i < xf86NumEntities; i++) {
+ p = xf86Entities[i];
+ /* Check if this SBUS slot is taken */
+ if (p->busType == BUS_SBUS && p->sbusBusId.fbNum == fbNum)
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/*
+ * If the slot requested is already in use, return -1.
+ * Otherwise, claim the slot for the screen requesting it.
+ */
+
+int
+xf86ClaimSbusSlot(sbusDevicePtr psdp, DriverPtr drvp,
+ GDevPtr dev, Bool active)
+{
+ EntityPtr p = NULL;
+
+ int num;
+
+ if (xf86CheckSbusSlot(psdp->fbNum)) {
+ num = xf86AllocateEntity();
+ p = xf86Entities[num];
+ p->driver = drvp;
+ p->chipset = -1;
+ p->busType = BUS_SBUS;
+ xf86AddDevToEntity(num, dev);
+ p->sbusBusId.fbNum = psdp->fbNum;
+ p->active = active;
+ p->inUse = FALSE;
+ /* Here we initialize the access structure */
+ p->access = xnfcalloc(1,sizeof(EntityAccessRec));
+ p->access->fallback = &AccessNULL;
+ p->access->pAccess = &AccessNULL;
+ sbusSlotClaimed = TRUE;
+ return num;
+ } else
+ return -1;
+}
+
+int
+xf86MatchSbusInstances(const char *driverName, int sbusDevId,
+ GDevPtr *devList, int numDevs, DriverPtr drvp,
+ int **foundEntities)
+{
+ int i,j;
+ sbusDevicePtr psdp, *psdpp;
+ int numClaimedInstances = 0;
+ int allocatedInstances = 0;
+ int numFound = 0;
+ GDevPtr devBus = NULL;
+ GDevPtr dev = NULL;
+ int *retEntities = NULL;
+ int useProm = 0;
+
+ struct Inst {
+ sbusDevicePtr sbus;
+ GDevPtr dev;
+ Bool claimed; /* BusID matches with a device section */
+ } *instances = NULL;
+
+ *foundEntities = NULL;
+ for (psdpp = xf86SbusInfo, psdp = *psdpp; psdp; psdp = *++psdpp) {
+ if (psdp->devId != sbusDevId)
+ continue;
+ if (psdp->fd == -2)
+ continue;
+ ++allocatedInstances;
+ instances = xnfrealloc(instances,
+ allocatedInstances * sizeof(struct Inst));
+ instances[allocatedInstances - 1].sbus = psdp;
+ instances[allocatedInstances - 1].dev = NULL;
+ instances[allocatedInstances - 1].claimed = FALSE;
+ numFound++;
+ }
+
+ /*
+ * This may be debatable, but if no SBUS devices with a matching vendor
+ * type is found, return zero now. It is probably not desirable to
+ * allow the config file to override this.
+ */
+ if (allocatedInstances <= 0) {
+ xfree(instances);
+ return 0;
+ }
+
+ if (xf86DoProbe) {
+ xfree(instances);
+ return numFound;
+ }
+
+ if (sparcPromInit() >= 0)
+ useProm = 1;
+
+ if (xf86DoConfigure && xf86DoConfigurePass1) {
+ GDevPtr pGDev;
+ int actualcards = 0;
+ for (i = 0; i < allocatedInstances; i++) {
+ actualcards++;
+ pGDev = xf86AddBusDeviceToConfigure(drvp->driverName, BUS_SBUS,
+ instances[i].sbus, -1);
+ if (pGDev) {
+ /*
+ * XF86Match???Instances() treat chipID and chipRev as
+ * overrides, so clobber them here.
+ */
+ pGDev->chipID = pGDev->chipRev = -1;
+ }
+ }
+ xfree(instances);
+ if (useProm)
+ sparcPromClose();
+ return actualcards;
+ }
+
+#ifdef DEBUG
+ ErrorF("%s instances found: %d\n", driverName, allocatedInstances);
+#endif
+
+ for (i = 0; i < allocatedInstances; i++) {
+ char *promPath = NULL;
+
+ psdp = instances[i].sbus;
+ devBus = NULL;
+ dev = NULL;
+ if (useProm && psdp->node.node)
+ promPath = sparcPromNode2Pathname(&psdp->node);
+
+ for (j = 0; j < numDevs; j++) {
+ if (devList[j]->busID && *devList[j]->busID) {
+ if (xf86CompareSbusBusString(devList[j]->busID, psdp->fbNum)) {
+ if (devBus)
+ xf86MsgVerb(X_WARNING,0,
+ "%s: More than one matching Device section for "
+ "instance (BusID: %s) found: %s\n",
+ driverName,devList[j]->identifier,
+ devList[j]->busID);
+ else
+ devBus = devList[j];
+ }
+ } else {
+ if (!dev && !devBus) {
+ if (promPath)
+ xf86Msg(X_PROBED, "Assigning device section with no busID to SBUS:%s\n",
+ promPath);
+ else
+ xf86Msg(X_PROBED, "Assigning device section with no busID to SBUS:fb%d\n",
+ psdp->fbNum);
+ dev = devList[j];
+ } else
+ xf86MsgVerb(X_WARNING, 0,
+ "%s: More than one matching Device section "
+ "found: %s\n", driverName, devList[j]->identifier);
+ }
+ }
+ if (devBus) dev = devBus; /* busID preferred */
+ if (!dev && psdp->fd != -2) {
+ if (promPath) {
+ xf86MsgVerb(X_WARNING, 0, "%s: No matching Device section "
+ "for instance (BusID SBUS:%s) found\n",
+ driverName, promPath);
+ } else
+ xf86MsgVerb(X_WARNING, 0, "%s: No matching Device section "
+ "for instance (BusID SBUS:fb%d) found\n",
+ driverName, psdp->fbNum);
+ } else if (dev) {
+ numClaimedInstances++;
+ instances[i].claimed = TRUE;
+ instances[i].dev = dev;
+ }
+ if (promPath)
+ xfree(promPath);
+ }
+
+#ifdef DEBUG
+ ErrorF("%s instances found: %d\n", driverName, numClaimedInstances);
+#endif
+
+ /*
+ * Of the claimed instances, check that another driver hasn't already
+ * claimed its slot.
+ */
+ numFound = 0;
+ for (i = 0; i < allocatedInstances && numClaimedInstances > 0; i++) {
+ if (!instances[i].claimed)
+ continue;
+ psdp = instances[i].sbus;
+ if (!xf86CheckSbusSlot(psdp->fbNum))
+ continue;
+
+#ifdef DEBUG
+ ErrorF("%s: card at fb%d %08x is claimed by a Device section\n",
+ driverName, psdp->fbNum, psdp->node.node);
+#endif
+
+ /* Allocate an entry in the lists to be returned */
+ numFound++;
+ retEntities = xnfrealloc(retEntities, numFound * sizeof(int));
+ retEntities[numFound - 1]
+ = xf86ClaimSbusSlot(psdp, drvp, instances[i].dev,instances[i].dev->active ?
+ TRUE : FALSE);
+ }
+ xfree(instances);
+ if (numFound > 0) {
+ *foundEntities = retEntities;
+ }
+
+ if (useProm)
+ sparcPromClose();
+
+ return numFound;
+}
+
+/*
+ * xf86GetSbusInfoForEntity() -- Get the sbusDevicePtr of entity.
+ */
+sbusDevicePtr
+xf86GetSbusInfoForEntity(int entityIndex)
+{
+ sbusDevicePtr *psdpp;
+ EntityPtr p = xf86Entities[entityIndex];
+
+ if (entityIndex >= xf86NumEntities
+ || p->busType != BUS_SBUS) return NULL;
+
+ for (psdpp = xf86SbusInfo; *psdpp != NULL; psdpp++) {
+ if (p->sbusBusId.fbNum == (*psdpp)->fbNum)
+ return (*psdpp);
+ }
+ return NULL;
+}
+
+int
+xf86GetEntityForSbusInfo(sbusDevicePtr psdp)
+{
+ int i;
+
+ for (i = 0; i < xf86NumEntities; i++) {
+ EntityPtr p = xf86Entities[i];
+ if (p->busType != BUS_SBUS) continue;
+
+ if (p->sbusBusId.fbNum == psdp->fbNum)
+ return i;
+ }
+ return -1;
+}
+
+void
+xf86SbusUseBuiltinMode(ScrnInfoPtr pScrn, sbusDevicePtr psdp)
+{
+ DisplayModePtr mode;
+
+ mode = xnfcalloc(sizeof(DisplayModeRec), 1);
+ mode->name = "current";
+ mode->next = mode;
+ mode->prev = mode;
+ mode->type = M_T_BUILTIN;
+ mode->Clock = 100000000;
+ mode->HDisplay = psdp->width;
+ mode->HSyncStart = psdp->width;
+ mode->HSyncEnd = psdp->width;
+ mode->HTotal = psdp->width;
+ mode->VDisplay = psdp->height;
+ mode->VSyncStart = psdp->height;
+ mode->VSyncEnd = psdp->height;
+ mode->VTotal = psdp->height;
+ mode->SynthClock = mode->Clock;
+ mode->CrtcHDisplay = mode->HDisplay;
+ mode->CrtcHSyncStart = mode->HSyncStart;
+ mode->CrtcHSyncEnd = mode->HSyncEnd;
+ mode->CrtcHTotal = mode->HTotal;
+ mode->CrtcVDisplay = mode->VDisplay;
+ mode->CrtcVSyncStart = mode->VSyncStart;
+ mode->CrtcVSyncEnd = mode->VSyncEnd;
+ mode->CrtcVTotal = mode->VTotal;
+ mode->CrtcHAdjusted = FALSE;
+ mode->CrtcVAdjusted = FALSE;
+ pScrn->modes = mode;
+ pScrn->virtualX = psdp->width;
+ pScrn->virtualY = psdp->height;
+}
+
+static int sbusPaletteIndex = -1;
+static unsigned long sbusPaletteGeneration = 0;
+typedef struct _sbusCmap {
+ sbusDevicePtr psdp;
+ CloseScreenProcPtr CloseScreen;
+ Bool origCmapValid;
+ unsigned char origRed[16];
+ unsigned char origGreen[16];
+ unsigned char origBlue[16];
+} sbusCmapRec, *sbusCmapPtr;
+
+#define SBUSCMAPPTR(pScreen) ((sbusCmapPtr)((pScreen)->devPrivates[sbusPaletteIndex].ptr))
+
+static void
+xf86SbusCmapLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
+ LOCO *colors, VisualPtr pVisual)
+{
+ int i, index;
+ sbusCmapPtr cmap;
+ struct fbcmap fbcmap;
+ unsigned char *data = ALLOCATE_LOCAL(numColors*3);
+
+ cmap = SBUSCMAPPTR(pScrn->pScreen);
+ if (!cmap) return;
+ fbcmap.count = 0;
+ fbcmap.index = indices[0];
+ fbcmap.red = data;
+ fbcmap.green = data + numColors;
+ fbcmap.blue = fbcmap.green + numColors;
+ for (i = 0; i < numColors; i++) {
+ index = indices[i];
+ if (fbcmap.count && index != fbcmap.index + fbcmap.count) {
+ ioctl (cmap->psdp->fd, FBIOPUTCMAP, &fbcmap);
+ fbcmap.count = 0;
+ fbcmap.index = index;
+ }
+ fbcmap.red[fbcmap.count] = colors[index].red;
+ fbcmap.green[fbcmap.count] = colors[index].green;
+ fbcmap.blue[fbcmap.count++] = colors[index].blue;
+ }
+ ioctl (cmap->psdp->fd, FBIOPUTCMAP, &fbcmap);
+ DEALLOCATE_LOCAL(data);
+}
+
+static Bool
+xf86SbusCmapCloseScreen(int i, ScreenPtr pScreen)
+{
+ sbusCmapPtr cmap;
+ struct fbcmap fbcmap;
+
+ cmap = SBUSCMAPPTR(pScreen);
+ if (cmap->origCmapValid) {
+ fbcmap.index = 0;
+ fbcmap.count = 16;
+ fbcmap.red = cmap->origRed;
+ fbcmap.green = cmap->origGreen;
+ fbcmap.blue = cmap->origBlue;
+ ioctl (cmap->psdp->fd, FBIOPUTCMAP, &fbcmap);
+ }
+ pScreen->CloseScreen = cmap->CloseScreen;
+ xfree (cmap);
+ return (*pScreen->CloseScreen) (i, pScreen);
+}
+
+Bool
+xf86SbusHandleColormaps(ScreenPtr pScreen, sbusDevicePtr psdp)
+{
+ sbusCmapPtr cmap;
+ struct fbcmap fbcmap;
+ unsigned char data[2];
+
+ if(sbusPaletteGeneration != serverGeneration) {
+ if((sbusPaletteIndex = AllocateScreenPrivateIndex()) < 0)
+ return FALSE;
+ sbusPaletteGeneration = serverGeneration;
+ }
+ cmap = xnfcalloc(1, sizeof(sbusCmapRec));
+ pScreen->devPrivates[sbusPaletteIndex].ptr = cmap;
+ cmap->psdp = psdp;
+ fbcmap.index = 0;
+ fbcmap.count = 16;
+ fbcmap.red = cmap->origRed;
+ fbcmap.green = cmap->origGreen;
+ fbcmap.blue = cmap->origBlue;
+ if (ioctl (psdp->fd, FBIOGETCMAP, &fbcmap) >= 0)
+ cmap->origCmapValid = TRUE;
+ fbcmap.index = 0;
+ fbcmap.count = 2;
+ fbcmap.red = data;
+ fbcmap.green = data;
+ fbcmap.blue = data;
+ if (pScreen->whitePixel == 0) {
+ data[0] = 255;
+ data[1] = 0;
+ } else {
+ data[0] = 0;
+ data[1] = 255;
+ }
+ ioctl (psdp->fd, FBIOPUTCMAP, &fbcmap);
+ cmap->CloseScreen = pScreen->CloseScreen;
+ pScreen->CloseScreen = xf86SbusCmapCloseScreen;
+ return xf86HandleColormaps(pScreen, 256, 8,
+ xf86SbusCmapLoadPalette, NULL, 0);
+}
diff --git a/hw/xfree86/common/xf86sbusBus.h b/hw/xfree86/common/xf86sbusBus.h
new file mode 100644
index 000000000..0816c63a1
--- /dev/null
+++ b/hw/xfree86/common/xf86sbusBus.h
@@ -0,0 +1,98 @@
+/*
+ * SBUS bus-specific declarations
+ *
+ * Copyright (C) 2000 Jakub Jelinek (jakub@redhat.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * JAKUB JELINEK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86sbusBus.h,v 3.5 2002/12/10 02:42:35 tsi Exp $ */
+
+#ifndef _XF86_SBUSBUS_H
+#define _XF86_SBUSBUS_H
+
+#include "xf86str.h"
+
+#define SBUS_DEVICE_BW2 0x0001
+#define SBUS_DEVICE_CG2 0x0002
+#define SBUS_DEVICE_CG3 0x0003
+#define SBUS_DEVICE_CG4 0x0004
+#define SBUS_DEVICE_CG6 0x0005
+#define SBUS_DEVICE_CG8 0x0006
+#define SBUS_DEVICE_CG12 0x0007
+#define SBUS_DEVICE_CG14 0x0008
+#define SBUS_DEVICE_LEO 0x0009
+#define SBUS_DEVICE_TCX 0x000a
+#define SBUS_DEVICE_FFB 0x000b
+#define SBUS_DEVICE_GT 0x000c
+#define SBUS_DEVICE_MGX 0x000d
+
+typedef struct sbus_prom_node {
+ int node;
+ /* Because of misdesigned openpromio */
+ int cookie[2];
+} sbusPromNode, *sbusPromNodePtr;
+
+typedef struct sbus_device {
+ int devId;
+ int fbNum;
+ int fd;
+ int width, height;
+ sbusPromNode node;
+ char *descr;
+ char *device;
+} sbusDevice, *sbusDevicePtr;
+
+extern struct sbus_devtable {
+ int devId;
+ int fbType;
+ char *promName;
+ char *descr;
+} sbusDeviceTable[];
+
+void xf86SbusProbe(void);
+extern sbusDevicePtr *xf86SbusInfo;
+
+int xf86MatchSbusInstances(const char *driverName, int sbusDevId,
+ GDevPtr *devList, int numDevs, DriverPtr drvp,
+ int **foundEntities);
+sbusDevicePtr xf86GetSbusInfoForEntity(int entityIndex);
+int xf86GetEntityForSbusInfo(sbusDevicePtr psdp);
+void xf86SbusUseBuiltinMode(ScrnInfoPtr pScrn, sbusDevicePtr psdp);
+pointer xf86MapSbusMem(sbusDevicePtr psdp, unsigned long offset,
+ unsigned long size);
+void xf86UnmapSbusMem(sbusDevicePtr psdp, pointer addr, unsigned long size);
+void xf86SbusHideOsHwCursor(sbusDevicePtr psdp);
+void xf86SbusSetOsHwCursorCmap(sbusDevicePtr psdp, int bg, int fg);
+Bool xf86SbusHandleColormaps(ScreenPtr pScreen, sbusDevicePtr psdp);
+
+extern int promRootNode;
+
+int promGetSibling(int node);
+int promGetChild(int node);
+char * promGetProperty(const char *prop, int *lenp);
+int promGetBool(const char *prop);
+
+int sparcPromInit(void);
+void sparcPromClose(void);
+char * sparcPromGetProperty(sbusPromNodePtr pnode, const char *prop, int *lenp);
+int sparcPromGetBool(sbusPromNodePtr pnode, const char *prop);
+void sparcPromAssignNodes(void);
+char * sparcPromNode2Pathname(sbusPromNodePtr pnode);
+int sparcPromPathname2Node(const char *pathName);
+
+#endif /* _XF86_SBUSBUS_H */
diff --git a/hw/xfree86/common/xf86str.h b/hw/xfree86/common/xf86str.h
new file mode 100644
index 000000000..2b6deed33
--- /dev/null
+++ b/hw/xfree86/common/xf86str.h
@@ -0,0 +1,1029 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86str.h,v 1.90 2002/11/25 14:04:56 eich Exp $ */
+
+/*
+ * Copyright (c) 1997-2000 by The XFree86 Project, Inc.
+ */
+
+/*
+ * This file contains definitions of the public XFree86 data structures/types.
+ * Any data structures that video drivers need to access should go here.
+ */
+
+#ifndef _XF86STR_H
+#define _XF86STR_H
+
+#include "misc.h"
+#include "input.h"
+#include "scrnintstr.h"
+#include "pixmapstr.h"
+#include "xf86Module.h"
+#include "xf86Opt.h"
+#include "xf86Pci.h"
+
+/*
+ * memType is of the size of the addressable memory (machine size)
+ * usually unsigned long.
+ */
+typedef unsigned long memType;
+
+/* Video mode flags */
+
+typedef enum {
+ V_PHSYNC = 0x0001,
+ V_NHSYNC = 0x0002,
+ V_PVSYNC = 0x0004,
+ V_NVSYNC = 0x0008,
+ V_INTERLACE = 0x0010,
+ V_DBLSCAN = 0x0020,
+ V_CSYNC = 0x0040,
+ V_PCSYNC = 0x0080,
+ V_NCSYNC = 0x0100,
+ V_HSKEW = 0x0200, /* hskew provided */
+ V_BCAST = 0x0400,
+ V_PIXMUX = 0x1000,
+ V_DBLCLK = 0x2000,
+ V_CLKDIV2 = 0x4000
+} ModeFlags;
+
+typedef enum {
+ INTERLACE_HALVE_V = 0x0001 /* Halve V values for interlacing */
+} CrtcAdjustFlags;
+
+/* Flags passed to ChipValidMode() */
+typedef enum {
+ MODECHECK_INITIAL = 0,
+ MODECHECK_FINAL = 1
+} ModeCheckFlags;
+
+/* These are possible return values for xf86CheckMode() and ValidMode() */
+typedef enum {
+ MODE_OK = 0, /* Mode OK */
+ MODE_HSYNC, /* hsync out of range */
+ MODE_VSYNC, /* vsync out of range */
+ MODE_H_ILLEGAL, /* mode has illegal horizontal timings */
+ MODE_V_ILLEGAL, /* mode has illegal horizontal timings */
+ MODE_BAD_WIDTH, /* requires an unsupported linepitch */
+ MODE_NOMODE, /* no mode with a maching name */
+ MODE_NO_INTERLACE, /* interlaced mode not supported */
+ MODE_NO_DBLESCAN, /* doublescan mode not supported */
+ MODE_NO_VSCAN, /* multiscan mode not supported */
+ MODE_MEM, /* insufficient video memory */
+ MODE_VIRTUAL_X, /* mode width too large for specified virtual size */
+ MODE_VIRTUAL_Y, /* mode height too large for specified virtual size */
+ MODE_MEM_VIRT, /* insufficient video memory given virtual size */
+ MODE_NOCLOCK, /* no fixed clock available */
+ MODE_CLOCK_HIGH, /* clock required is too high */
+ MODE_CLOCK_LOW, /* clock required is too low */
+ MODE_CLOCK_RANGE, /* clock/mode isn't in a ClockRange */
+ MODE_BAD_HVALUE, /* horizontal timing was out of range */
+ MODE_BAD_VVALUE, /* vertical timing was out of range */
+ MODE_BAD_VSCAN, /* VScan value out of range */
+ MODE_HSYNC_NARROW, /* horizontal sync too narrow */
+ MODE_HSYNC_WIDE, /* horizontal sync too wide */
+ MODE_HBLANK_NARROW, /* horizontal blanking too narrow */
+ MODE_HBLANK_WIDE, /* horizontal blanking too wide */
+ MODE_VSYNC_NARROW, /* vertical sync too narrow */
+ MODE_VSYNC_WIDE, /* vertical sync too wide */
+ MODE_VBLANK_NARROW, /* vertical blanking too narrow */
+ MODE_VBLANK_WIDE, /* vertical blanking too wide */
+ MODE_PANEL, /* exceeds panel dimensions */
+ MODE_INTERLACE_WIDTH, /* width too large for interlaced mode */
+ MODE_ONE_WIDTH, /* only one width is supported */
+ MODE_ONE_HEIGHT, /* only one height is supported */
+ MODE_ONE_SIZE, /* only one resolution is supported */
+ MODE_BAD = -2, /* unspecified reason */
+ MODE_ERROR = -1 /* error condition */
+} ModeStatus;
+
+# define M_T_BUILTIN 0x01 /* built-in mode */
+# define M_T_CLOCK_C (0x02 | M_T_BUILTIN) /* built-in mode - configure clock */
+# define M_T_CRTC_C (0x04 | M_T_BUILTIN) /* built-in mode - configure CRTC */
+# define M_T_CLOCK_CRTC_C (M_T_CLOCK_C | M_T_CRTC_C)
+ /* built-in mode - configure CRTC and clock */
+# define M_T_DEFAULT 0x10 /* (VESA) default modes */
+# define M_T_USERDEF 0x20 /* One of the modes from the config file */
+
+/* Video mode */
+typedef struct _DisplayModeRec {
+ struct _DisplayModeRec * prev;
+ struct _DisplayModeRec * next;
+ char * name; /* identifier for the mode */
+ ModeStatus status;
+ int type;
+
+ /* These are the values that the user sees/provides */
+ int Clock; /* pixel clock freq */
+ int HDisplay; /* horizontal timing */
+ int HSyncStart;
+ int HSyncEnd;
+ int HTotal;
+ int HSkew;
+ int VDisplay; /* vertical timing */
+ int VSyncStart;
+ int VSyncEnd;
+ int VTotal;
+ int VScan;
+ int Flags;
+
+ /* These are the values the hardware uses */
+ int ClockIndex;
+ int SynthClock; /* Actual clock freq to
+ * be programmed */
+ int CrtcHDisplay;
+ int CrtcHBlankStart;
+ int CrtcHSyncStart;
+ int CrtcHSyncEnd;
+ int CrtcHBlankEnd;
+ int CrtcHTotal;
+ int CrtcHSkew;
+ int CrtcVDisplay;
+ int CrtcVBlankStart;
+ int CrtcVSyncStart;
+ int CrtcVSyncEnd;
+ int CrtcVBlankEnd;
+ int CrtcVTotal;
+ Bool CrtcHAdjusted;
+ Bool CrtcVAdjusted;
+ int PrivSize;
+ INT32 * Private;
+ int PrivFlags;
+
+ float HSync, VRefresh;
+} DisplayModeRec, *DisplayModePtr;
+
+/* The monitor description */
+
+#define MAX_HSYNC 8
+#define MAX_VREFRESH 8
+
+typedef struct { float hi, lo; } range;
+
+typedef struct { CARD32 red, green, blue; } rgb;
+
+typedef struct { float red, green, blue; } Gamma;
+
+/* The permitted gamma range is 1 / GAMMA_MAX <= g <= GAMMA_MAX */
+#define GAMMA_MAX 10.0
+#define GAMMA_MIN (1.0 / GAMMA_MAX)
+#define GAMMA_ZERO (GAMMA_MIN / 100.0)
+
+typedef struct {
+ char * id;
+ char * vendor;
+ char * model;
+ int nHsync;
+ range hsync[MAX_HSYNC];
+ int nVrefresh;
+ range vrefresh[MAX_VREFRESH];
+ DisplayModePtr Modes; /* Start of the monitor's mode list */
+ DisplayModePtr Last; /* End of the monitor's mode list */
+ Gamma gamma; /* Gamma of the monitor */
+ int widthmm;
+ int heightmm;
+ pointer options;
+ pointer DDC;
+} MonRec, *MonPtr;
+
+/* the list of clock ranges */
+typedef struct x_ClockRange {
+ struct x_ClockRange *next;
+ int minClock;
+ int maxClock;
+ int clockIndex; /* -1 for programmable clocks */
+ Bool interlaceAllowed;
+ Bool doubleScanAllowed;
+ int ClockMulFactor;
+ int ClockDivFactor;
+ int PrivFlags;
+} ClockRange, *ClockRangePtr;
+
+/* Need to store the strategy with clockRange for VidMode extension */
+typedef struct x_ClockRanges {
+ struct x_ClockRanges *next;
+ int minClock;
+ int maxClock;
+ int clockIndex; /* -1 for programmable clocks */
+ Bool interlaceAllowed;
+ Bool doubleScanAllowed;
+ int ClockMulFactor;
+ int ClockDivFactor;
+ int PrivFlags;
+ int strategy;
+} ClockRanges, *ClockRangesPtr;
+
+/*
+ * The driver list struct. This contains the information required for each
+ * driver before a ScrnInfoRec has been allocated.
+ */
+typedef struct _DriverRec {
+ int driverVersion;
+ char * driverName;
+ void (*Identify)(int flags);
+ Bool (*Probe)(struct _DriverRec *drv, int flags);
+ const OptionInfoRec * (*AvailableOptions)(int chipid, int bustype);
+ pointer module;
+ int refCount;
+} DriverRec, *DriverPtr;
+
+#ifdef XFree86LOADER
+/*
+ * The optional module list struct. This allows modules exporting helping
+ * functions to configuration tools, the Xserver, or any other
+ * application/module interested in such information.
+ */
+typedef struct _ModuleInfoRec {
+ int moduleVersion;
+ char * moduleName;
+ pointer module;
+ int refCount;
+ const OptionInfoRec * (*AvailableOptions)(void *unused);
+ pointer unused[8]; /* leave some space for more fields */
+} ModuleInfoRec, *ModuleInfoPtr;
+#endif
+
+/*
+ * These are the private bus types. New types can be added here. Types
+ * required for the public interface should be added to xf86str.h, with
+ * function prototypes added to xf86.h.
+ */
+
+/* Tolerate prior #include <linux/input.h> */
+#if defined(linux) && defined(_INPUT_H)
+#undef BUS_NONE
+#undef BUS_ISA
+#undef BUS_PCI
+#undef BUS_SBUS
+#undef BUS_last
+#endif
+
+typedef enum {
+ BUS_NONE,
+ BUS_ISA,
+ BUS_PCI,
+ BUS_SBUS,
+ BUS_last /* Keep last */
+} BusType;
+
+typedef struct {
+ int bus;
+ int device;
+ int func;
+} PciBusId;
+
+typedef struct {
+ unsigned int dummy;
+} IsaBusId;
+
+typedef struct {
+ int fbNum;
+} SbusBusId;
+
+typedef struct _bus {
+ BusType type;
+ union {
+ IsaBusId isa;
+ PciBusId pci;
+ SbusBusId sbus;
+ } id;
+} BusRec, *BusPtr;
+
+#define MAXCLOCKS 128
+typedef enum {
+ DAC_BPP8 = 0,
+ DAC_BPP16,
+ DAC_BPP24,
+ DAC_BPP32,
+ MAXDACSPEEDS
+} DacSpeedIndex;
+
+typedef struct {
+ char * identifier;
+ char * vendor;
+ char * board;
+ char * chipset;
+ char * ramdac;
+ char * driver;
+ struct _confscreenrec * myScreenSection;
+ Bool claimed;
+ int dacSpeeds[MAXDACSPEEDS];
+ int numclocks;
+ int clock[MAXCLOCKS];
+ char * clockchip;
+ char * busID;
+ Bool active;
+ Bool inUse;
+ int videoRam;
+ int textClockFreq;
+ unsigned long BiosBase; /* Base address of video BIOS */
+ unsigned long MemBase; /* Frame buffer base address */
+ unsigned long IOBase;
+ int chipID;
+ int chipRev;
+ pointer options;
+ int irq;
+ int screen; /* For multi-CRTC cards */
+} GDevRec, *GDevPtr;
+
+typedef int (*FindIsaDevProc)(GDevPtr dev);
+
+typedef struct {
+ char * identifier;
+ char * driver;
+ pointer commonOptions;
+ pointer extraOptions;
+} IDevRec, *IDevPtr;
+
+typedef struct {
+ int vendor;
+ int chipType;
+ int chipRev;
+ int subsysVendor;
+ int subsysCard;
+ int bus;
+ int device;
+ int func;
+ int class;
+ int subclass;
+ int interface;
+ memType memBase[6];
+ memType ioBase[6];
+ int size[6];
+ unsigned char type[6];
+ memType biosBase;
+ int biosSize;
+ pointer thisCard;
+ Bool validSize;
+ Bool validate;
+ CARD32 listed_class;
+} pciVideoRec, *pciVideoPtr;
+
+typedef struct {
+ int frameX0;
+ int frameY0;
+ int virtualX;
+ int virtualY;
+ int depth;
+ int fbbpp;
+ rgb weight;
+ rgb blackColour;
+ rgb whiteColour;
+ int defaultVisual;
+ char ** modes;
+ pointer options;
+} DispRec, *DispPtr;
+
+typedef struct _confxvportrec {
+ char * identifier;
+ pointer options;
+} confXvPortRec, *confXvPortPtr;
+
+typedef struct _confxvadaptrec {
+ char * identifier;
+ int numports;
+ confXvPortPtr ports;
+ pointer options;
+} confXvAdaptorRec, *confXvAdaptorPtr;
+
+typedef struct _confscreenrec {
+ char * id;
+ int screennum;
+ int defaultdepth;
+ int defaultbpp;
+ int defaultfbbpp;
+ MonPtr monitor;
+ GDevPtr device;
+ int numdisplays;
+ DispPtr displays;
+ int numxvadaptors;
+ confXvAdaptorPtr xvadaptors;
+ pointer options;
+} confScreenRec, *confScreenPtr;
+
+typedef enum {
+ PosObsolete = -1,
+ PosAbsolute = 0,
+ PosRightOf,
+ PosLeftOf,
+ PosAbove,
+ PosBelow,
+ PosRelative
+} PositionType;
+
+typedef struct _screenlayoutrec {
+ confScreenPtr screen;
+ char * topname;
+ confScreenPtr top;
+ char * bottomname;
+ confScreenPtr bottom;
+ char * leftname;
+ confScreenPtr left;
+ char * rightname;
+ confScreenPtr right;
+ PositionType where;
+ int x;
+ int y;
+ char * refname;
+ confScreenPtr refscreen;
+} screenLayoutRec, *screenLayoutPtr;
+
+typedef struct _serverlayoutrec {
+ char * id;
+ screenLayoutPtr screens;
+ GDevPtr inactives;
+ IDevPtr inputs;
+ pointer options;
+} serverLayoutRec, *serverLayoutPtr;
+
+typedef struct _confdribufferrec {
+ int count;
+ int size;
+ enum {
+ XF86DRI_WC_HINT = 0x0001 /* Placeholder: not implemented */
+ } flags;
+} confDRIBufferRec, *confDRIBufferPtr;
+
+typedef struct _confdrirec {
+ int group;
+ int mode;
+ int bufs_count;
+ confDRIBufferRec *bufs;
+} confDRIRec, *confDRIPtr;
+
+/* These values should be adjusted when new fields are added to ScrnInfoRec */
+#define NUM_RESERVED_INTS 16
+#define NUM_RESERVED_POINTERS 15
+#define NUM_RESERVED_FUNCS 16
+
+typedef pointer (*funcPointer)(void);
+
+/* Flags for driver messages */
+typedef enum {
+ X_PROBED, /* Value was probed */
+ X_CONFIG, /* Value was given in the config file */
+ X_DEFAULT, /* Value is a default */
+ X_CMDLINE, /* Value was given on the command line */
+ X_NOTICE, /* Notice */
+ X_ERROR, /* Error message */
+ X_WARNING, /* Warning message */
+ X_INFO, /* Informational message */
+ X_NONE, /* No prefix */
+ X_NOT_IMPLEMENTED /* Not implemented */
+} MessageType;
+
+/* flags for depth 24 pixmap options */
+typedef enum {
+ Pix24DontCare = 0,
+ Pix24Use24,
+ Pix24Use32
+} Pix24Flags;
+
+/* Power management events: so far we only support APM */
+
+typedef enum {
+ XF86_APM_UNKNOWN = -1,
+ XF86_APM_SYS_STANDBY,
+ XF86_APM_SYS_SUSPEND,
+ XF86_APM_CRITICAL_SUSPEND,
+ XF86_APM_USER_STANDBY,
+ XF86_APM_USER_SUSPEND,
+ XF86_APM_STANDBY_RESUME,
+ XF86_APM_NORMAL_RESUME,
+ XF86_APM_CRITICAL_RESUME,
+ XF86_APM_LOW_BATTERY,
+ XF86_APM_POWER_STATUS_CHANGE,
+ XF86_APM_UPDATE_TIME,
+ XF86_APM_CAPABILITY_CHANGED,
+ XF86_APM_STANDBY_FAILED,
+ XF86_APM_SUSPEND_FAILED
+} pmEvent;
+
+typedef enum {
+ PM_WAIT,
+ PM_CONTINUE,
+ PM_FAILED,
+ PM_NONE
+} pmWait;
+
+/*
+ * The IO access enabler struct. This contains the address for
+ * the IOEnable/IODisable funcs for their specific bus along
+ * with a pointer to data needed by them
+ */
+typedef struct _AccessRec {
+ void (*AccessDisable)(void *arg);
+ void (*AccessEnable)(void *arg);
+ void *arg;
+} xf86AccessRec, *xf86AccessPtr;
+
+typedef struct {
+ xf86AccessPtr mem;
+ xf86AccessPtr io;
+ xf86AccessPtr io_mem;
+} xf86SetAccessFuncRec, *xf86SetAccessFuncPtr;
+
+/* bus-access-related types */
+typedef enum {
+ NONE,
+ IO,
+ MEM_IO,
+ MEM
+} resType;
+
+typedef struct _EntityAccessRec {
+ xf86AccessPtr fallback;
+ xf86AccessPtr pAccess;
+ resType rt;
+ pointer busAcc;
+ struct _EntityAccessRec *next;
+} EntityAccessRec, *EntityAccessPtr;
+
+typedef struct _CurrAccRec {
+ EntityAccessPtr pMemAccess;
+ EntityAccessPtr pIoAccess;
+} xf86CurrentAccessRec, *xf86CurrentAccessPtr;
+
+/* new RAC */
+
+/* Resource Type values */
+#define ResNone ((unsigned long)(-1))
+
+#define ResMem 0x0001
+#define ResIo 0x0002
+#define ResIrq 0x0003
+#define ResDma 0x0004
+#define ResPciCfg 0x000e /* PCI Configuration space */
+#define ResPhysMask 0x000F
+
+#define ResExclusive 0x0010
+#define ResShared 0x0020
+#define ResAny 0x0040
+#define ResAccMask 0x0070
+#define ResUnused 0x0080
+
+#define ResUnusedOpr 0x0100
+#define ResDisableOpr 0x0200
+#define ResOprMask 0x0300
+
+#define ResBlock 0x0400
+#define ResSparse 0x0800
+#define ResExtMask 0x0C00
+
+#define ResEstimated 0x001000
+#define ResInit 0x002000
+#define ResBios 0x004000
+#define ResMiscMask 0x00F000
+
+#define ResBus 0x010000
+#define ResOverlap 0x020000
+
+#if defined(__alpha__) && defined(linux)
+# define ResDomain 0x1ff000000ul
+#else
+# define ResDomain 0xff000000ul
+#endif
+#define ResTypeMask (ResPhysMask | ResDomain) /* For conflict check */
+
+#define ResEnd ResNone
+
+#define ResExcMemBlock (ResMem | ResExclusive | ResBlock)
+#define ResExcIoBlock (ResIo | ResExclusive | ResBlock)
+#define ResShrMemBlock (ResMem | ResShared | ResBlock)
+#define ResShrIoBlock (ResIo | ResShared | ResBlock)
+#define ResExcUusdMemBlock (ResMem | ResExclusive | ResUnused | ResBlock)
+#define ResExcUusdIoBlock (ResIo | ResExclusive | ResUnused | ResBlock)
+#define ResShrUusdMemBlock (ResMem | ResShared | ResUnused | ResBlock)
+#define ResShrUusdIoBlock (ResIo | ResShared | ResUnused | ResBlock)
+#define ResExcUusdMemSparse (ResMem | ResExclusive | ResUnused | ResSparse)
+#define ResExcUusdIoSparse (ResIo | ResExclusive | ResUnused | ResSparse)
+#define ResShrUusdMemSparse (ResMem | ResShared | ResUnused | ResSparse)
+#define ResShrUusdIoSparse (ResIo | ResShared | ResUnused | ResSparse)
+
+#define ResExcMemSparse (ResMem | ResExclusive | ResSparse)
+#define ResExcIoSparse (ResIo | ResExclusive | ResSparse)
+#define ResShrMemSparse (ResMem | ResShared | ResSparse)
+#define ResShrIoSparse (ResIo | ResShared | ResSparse)
+#define ResUusdMemSparse (ResMem | ResUnused | ResSparse)
+#define ResUusdIoSparse (ResIo | ResUnused | ResSparse)
+
+#define ResIsMem(r) (((r)->type & ResPhysMask) == ResMem)
+#define ResIsIo(r) (((r)->type & ResPhysMask) == ResIo)
+#define ResIsExclusive(r) (((r)->type & ResAccMask) == ResExclusive)
+#define ResIsShared(r) (((r)->type & ResAccMask) == ResShared)
+#define ResIsUnused(r) (((r)->type & ResAccMask) == ResUnused)
+#define ResIsBlock(r) (((r)->type & ResExtMask) == ResBlock)
+#define ResIsSparse(r) (((r)->type & ResExtMask) == ResSparse)
+#define ResIsEstimated(r) (((r)->type & ResMiscMask) == ResEstimated)
+#define ResCanOverlap(r) (ResIsEstimated(r) || ((r)->type & ResOverlap))
+
+typedef struct {
+ unsigned long type; /* shared, exclusive, unused etc. */
+ memType a;
+ memType b;
+} resRange, *resList;
+
+#define RANGE_TYPE(type, domain) \
+ (((unsigned long)(domain) << 24) | ((type) & ~ResBus))
+#define RANGE(r,u,v,t) {\
+ (r).a = (u);\
+ (r).b = (v);\
+ (r).type = (t);\
+ }
+
+#define rBase a
+#define rMask b
+#define rBegin a
+#define rEnd b
+
+/* resource record */
+typedef struct _resRec *resPtr;
+typedef struct _resRec {
+ resRange val;
+ int entityIndex; /* who owns the resource */
+ resPtr next;
+} resRec;
+
+#define sparse_base val.rBase
+#define sparse_mask val.rMask
+#define block_begin val.rBegin
+#define block_end val.rEnd
+#define res_type val.type
+
+typedef struct {
+ int numChipset;
+ resRange *resList;
+} IsaChipsets;
+
+typedef struct {
+ int numChipset;
+ int PCIid;
+ resRange *resList;
+} PciChipsets;
+
+/* Entity properties */
+typedef void (*EntityProc)(int entityIndex,pointer private);
+
+typedef struct _entityInfo {
+ int index;
+ BusRec location;
+ int chipset;
+ Bool active;
+ resPtr resources;
+ GDevPtr device;
+ DriverPtr driver;
+} EntityInfoRec, *EntityInfoPtr;
+
+/* server states */
+
+typedef enum {
+ SETUP,
+ OPERATING
+} xf86State;
+
+typedef enum {
+ NOTIFY_SETUP_TRANSITION,
+ NOTIFY_SETUP,
+ NOTIFY_OPERATING,
+ NOTIFY_OPERATING_TRANSITION,
+ NOTIFY_ENABLE,
+ NOTIFY_ENTER,
+ NOTIFY_LEAVE
+} xf86NotifyState;
+
+typedef void (*xf86StateChangeNotificationCallbackFunc)(xf86NotifyState state,pointer);
+
+/* DGA */
+
+typedef struct {
+ int num; /* A unique identifier for the mode (num > 0) */
+ DisplayModePtr mode;
+ int flags; /* DGA_CONCURRENT_ACCESS, etc... */
+ int imageWidth; /* linear accessible portion (pixels) */
+ int imageHeight;
+ int pixmapWidth; /* Xlib accessible portion (pixels) */
+ int pixmapHeight; /* both fields ignored if no concurrent access */
+ int bytesPerScanline;
+ int byteOrder; /* MSBFirst, LSBFirst */
+ int depth;
+ int bitsPerPixel;
+ unsigned long red_mask;
+ unsigned long green_mask;
+ unsigned long blue_mask;
+ short visualClass;
+ int viewportWidth;
+ int viewportHeight;
+ int xViewportStep; /* viewport position granularity */
+ int yViewportStep;
+ int maxViewportX; /* max viewport origin */
+ int maxViewportY;
+ int viewportFlags; /* types of page flipping possible */
+ int offset; /* offset into physical memory */
+ unsigned char *address; /* server's mapped framebuffer */
+ int reserved1;
+ int reserved2;
+} DGAModeRec, *DGAModePtr;
+
+typedef struct {
+ DGAModePtr mode;
+ PixmapPtr pPix;
+} DGADeviceRec, *DGADevicePtr;
+
+/*
+ * Flags for driver Probe() functions.
+ */
+#define PROBE_DEFAULT 0x00
+#define PROBE_DETECT 0x01
+#define PROBE_TRYHARD 0x02
+
+/*
+ * Driver entry point types
+ */
+typedef struct _ScrnInfoRec *ScrnInfoPtr;
+
+typedef Bool xf86ProbeProc (DriverPtr, int);
+typedef Bool xf86PreInitProc (ScrnInfoPtr, int);
+typedef Bool xf86ScreenInitProc (int, ScreenPtr, int, char**);
+typedef Bool xf86SwitchModeProc (int, DisplayModePtr, int);
+typedef void xf86AdjustFrameProc (int, int, int, int);
+typedef Bool xf86EnterVTProc (int, int);
+typedef void xf86LeaveVTProc (int, int);
+typedef void xf86FreeScreenProc (int, int);
+typedef int xf86ValidModeProc (int, DisplayModePtr, Bool, int);
+typedef void xf86EnableDisableFBAccessProc(int, Bool);
+typedef int xf86SetDGAModeProc (int, int, DGADevicePtr);
+typedef int xf86ChangeGammaProc (int, Gamma);
+typedef void xf86PointerMovedProc (int, int, int);
+typedef Bool xf86PMEventProc (int, pmEvent, Bool);
+
+/*
+ * ScrnInfoRec
+ *
+ * There is one of these for each screen, and it holds all the screen-specific
+ * information.
+ *
+ * Note: the size and layout must be kept the same across versions. New
+ * fields are to be added in place of the "reserved*" fields. No fields
+ * are to be dependent on compile-time defines.
+ */
+
+
+typedef struct _ScrnInfoRec {
+ int driverVersion;
+ char * driverName; /* canonical name used in */
+ /* the config file */
+ ScreenPtr pScreen; /* Pointer to the ScreenRec */
+ int scrnIndex; /* Number of this screen */
+ Bool configured; /* Is this screen valid */
+ int origIndex; /* initial number assigned to
+ * this screen before
+ * finalising the number of
+ * available screens */
+
+ /* Display-wide screenInfo values needed by this screen */
+ int imageByteOrder;
+ int bitmapScanlineUnit;
+ int bitmapScanlinePad;
+ int bitmapBitOrder;
+ int numFormats;
+ PixmapFormatRec formats[MAXFORMATS];
+ PixmapFormatRec fbFormat;
+
+ int bitsPerPixel; /* fb bpp */
+ Pix24Flags pixmap24; /* pixmap pref for depth 24 */
+ int depth; /* depth of default visual */
+ MessageType depthFrom; /* set from config? */
+ MessageType bitsPerPixelFrom; /* set from config? */
+ rgb weight; /* r/g/b weights */
+ rgb mask; /* rgb masks */
+ rgb offset; /* rgb offsets */
+ int rgbBits; /* Number of bits in r/g/b */
+ Gamma gamma; /* Gamma of the monitor */
+ int defaultVisual; /* default visual class */
+ int maxHValue; /* max horizontal timing */
+ int maxVValue; /* max vertical timing value */
+ int virtualX; /* Virtual width */
+ int virtualY; /* Virtual height */
+ int xInc; /* Horizontal timing increment */
+ MessageType virtualFrom; /* set from config? */
+ int displayWidth; /* memory pitch */
+ int frameX0; /* viewport position */
+ int frameY0;
+ int frameX1;
+ int frameY1;
+ int zoomLocked; /* Disallow mode changes */
+ DisplayModePtr modePool; /* list of compatible modes */
+ DisplayModePtr modes; /* list of actual modes */
+ DisplayModePtr currentMode; /* current mode
+ * This was previously
+ * overloaded with the modes
+ * field, which is a pointer
+ * into a circular list */
+ confScreenPtr confScreen; /* Screen config info */
+ MonPtr monitor; /* Monitor information */
+ DispPtr display; /* Display information */
+ int * entityList; /* List of device entities */
+ int numEntities;
+ int widthmm; /* physical display dimensions
+ * in mm */
+ int heightmm;
+ int xDpi; /* width DPI */
+ int yDpi; /* height DPI */
+ char * name; /* Name to prefix messages */
+ pointer driverPrivate; /* Driver private area */
+ DevUnion * privates; /* Other privates can hook in
+ * here */
+ DriverPtr drv; /* xf86DriverList[] entry */
+ pointer module; /* Pointer to module head */
+ int colorKey;
+ int overlayFlags;
+
+ /* Some of these may be moved out of here into the driver private area */
+
+ char * chipset; /* chipset name */
+ char * ramdac; /* ramdac name */
+ char * clockchip; /* clock name */
+ Bool progClock; /* clock is programmable */
+ int numClocks; /* number of clocks */
+ int clock[MAXCLOCKS]; /* list of clock frequencies */
+ int videoRam; /* amount of video ram (kb) */
+ unsigned long biosBase; /* Base address of video BIOS */
+ unsigned long memPhysBase; /* Physical address of FB */
+ unsigned long fbOffset; /* Offset of FB in the above */
+ IOADDRESS domainIOBase; /* Domain I/O base address */
+ int memClk; /* memory clock */
+ int textClockFreq; /* clock of text mode */
+ Bool flipPixels; /* swap default black/white */
+ pointer options;
+
+ int chipID;
+ int chipRev;
+ int racMemFlags;
+ int racIoFlags;
+ pointer access;
+ xf86CurrentAccessPtr CurrentAccess;
+ resType resourceType;
+ pointer busAccess;
+
+ /* Allow screens to be enabled/disabled individually */
+ Bool vtSema;
+ DevUnion pixmapPrivate; /* saved devPrivate from pixmap */
+
+ /* hw cursor moves at SIGIO time */
+ Bool silkenMouse;
+
+ /* Storage for clockRanges and adjustFlags for use with the VidMode ext */
+ ClockRangesPtr clockRanges;
+ int adjustFlags;
+
+ /*
+ * These can be used when the minor ABI version is incremented.
+ * The NUM_* parameters must be reduced appropriately to keep the
+ * structure size and alignment unchanged.
+ */
+ int reservedInt[NUM_RESERVED_INTS];
+
+ int * entityInstanceList;
+ pointer reservedPtr[NUM_RESERVED_POINTERS];
+
+ /*
+ * Driver entry points.
+ *
+ */
+
+ xf86ProbeProc *Probe;
+ xf86PreInitProc *PreInit;
+ xf86ScreenInitProc *ScreenInit;
+ xf86SwitchModeProc *SwitchMode;
+ xf86AdjustFrameProc *AdjustFrame;
+ xf86EnterVTProc *EnterVT;
+ xf86LeaveVTProc *LeaveVT;
+ xf86FreeScreenProc *FreeScreen;
+ xf86ValidModeProc *ValidMode;
+ xf86EnableDisableFBAccessProc *EnableDisableFBAccess;
+ xf86SetDGAModeProc *SetDGAMode;
+ xf86ChangeGammaProc *ChangeGamma;
+ xf86PointerMovedProc *PointerMoved;
+ xf86PMEventProc *PMEvent;
+
+ /*
+ * This can be used when the minor ABI version is incremented.
+ * The NUM_* parameter must be reduced appropriately to keep the
+ * structure size and alignment unchanged.
+ */
+ funcPointer reservedFuncs[NUM_RESERVED_FUNCS];
+
+} ScrnInfoRec;
+
+
+typedef struct {
+ Bool (*OpenFramebuffer)(
+ ScrnInfoPtr pScrn,
+ char **name,
+ unsigned char **mem,
+ int *size,
+ int *offset,
+ int *extra
+ );
+ void (*CloseFramebuffer)(ScrnInfoPtr pScrn);
+ Bool (*SetMode)(ScrnInfoPtr pScrn, DGAModePtr pMode);
+ void (*SetViewport)(ScrnInfoPtr pScrn, int x, int y, int flags);
+ int (*GetViewport)(ScrnInfoPtr pScrn);
+ void (*Sync)(ScrnInfoPtr);
+ void (*FillRect)(
+ ScrnInfoPtr pScrn,
+ int x, int y, int w, int h,
+ unsigned long color
+ );
+ void (*BlitRect)(
+ ScrnInfoPtr pScrn,
+ int srcx, int srcy,
+ int w, int h,
+ int dstx, int dsty
+ );
+ void (*BlitTransRect)(
+ ScrnInfoPtr pScrn,
+ int srcx, int srcy,
+ int w, int h,
+ int dstx, int dsty,
+ unsigned long color
+ );
+} DGAFunctionRec, *DGAFunctionPtr;
+
+typedef struct {
+ int token; /* id of the token */
+ const char * name; /* token name */
+} SymTabRec, *SymTabPtr;
+
+/* flags for xf86LookupMode */
+typedef enum {
+ LOOKUP_DEFAULT = 0, /* Use default mode lookup method */
+ LOOKUP_BEST_REFRESH, /* Pick modes with best refresh */
+ LOOKUP_CLOSEST_CLOCK, /* Pick modes with the closest clock */
+ LOOKUP_LIST_ORDER, /* Pick first useful mode in list */
+ LOOKUP_CLKDIV2 = 0x0100, /* Allow half clocks */
+ LOOKUP_OPTIONAL_TOLERANCES = 0x0200 /* Allow missing hsync/vrefresh */
+} LookupModeFlags;
+
+#define NoDepth24Support 0x00
+#define Support24bppFb 0x01 /* 24bpp framebuffer supported */
+#define Support32bppFb 0x02 /* 32bpp framebuffer supported */
+#define SupportConvert24to32 0x04 /* Can convert 24bpp pixmap to 32bpp */
+#define SupportConvert32to24 0x08 /* Can convert 32bpp pixmap to 24bpp */
+#define PreferConvert24to32 0x10 /* prefer 24bpp pixmap to 32bpp conv */
+#define PreferConvert32to24 0x20 /* prefer 32bpp pixmap to 24bpp conv */
+
+
+/* For DPMS */
+typedef void (*DPMSSetProcPtr)(ScrnInfoPtr, int, int);
+
+/* Input handler proc */
+typedef void (*InputHandlerProc)(int fd, pointer data);
+
+/* These are used by xf86GetClocks */
+#define CLK_REG_SAVE -1
+#define CLK_REG_RESTORE -2
+
+/* xf86Debug.c */
+#ifdef BUILDDEBUG
+typedef struct {
+ long sec;
+ long usec;
+} xf86TsRec, *xf86TsPtr;
+#endif
+
+/*
+ * misc constants
+ */
+#define INTERLACE_REFRESH_WEIGHT 1.5
+#define SYNC_TOLERANCE 0.01 /* 1 percent */
+#define CLOCK_TOLERANCE 2000 /* Clock matching tolerance (2MHz) */
+
+
+#define OVERLAY_8_32_DUALFB 0x00000001
+#define OVERLAY_8_24_DUALFB 0x00000002
+#define OVERLAY_8_16_DUALFB 0x00000004
+#define OVERLAY_8_32_PLANAR 0x00000008
+
+#if 0
+#define LD_RESOLV_IFDONE 0 /* only check if no more
+ delays pending */
+#define LD_RESOLV_NOW 1 /* finish one delay step */
+#define LD_RESOLV_FORCE 2 /* force checking... */
+#endif
+
+/* Values of xf86Info.mouseFlags */
+#define MF_CLEAR_DTR 1
+#define MF_CLEAR_RTS 2
+
+/* Action Events */
+typedef enum {
+ ACTION_TERMINATE = 0, /* Terminate Server */
+ ACTION_NEXT_MODE = 10, /* Switch to next video mode */
+ ACTION_PREV_MODE,
+ ACTION_DISABLEGRAB = 20, /* Cancel server/pointer/kbd grabs */
+ ACTION_CLOSECLIENT, /* Kill client holding grab */
+ ACTION_SWITCHSCREEN = 100, /* VT switch */
+ ACTION_SWITCHSCREEN_NEXT,
+ ACTION_SWITCHSCREEN_PREV
+} ActionEvent;
+
+#endif /* _XF86STR_H */
diff --git a/hw/xfree86/common/xf86xv.c b/hw/xfree86/common/xf86xv.c
new file mode 100644
index 000000000..c6a09121b
--- /dev/null
+++ b/hw/xfree86/common/xf86xv.c
@@ -0,0 +1,1935 @@
+/*
+
+ XFree86 Xv DDX written by Mark Vojkovich (markv@valinux.com)
+
+ Copyright (C) 1998, 1999 - The XFree86 Project Inc.
+
+*/
+
+/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86xv.c,v 1.33 2002/11/09 01:18:11 keithp Exp $ */
+
+#include "misc.h"
+#include "xf86.h"
+#include "xf86_OSproc.h"
+
+#include "X.h"
+#include "Xproto.h"
+#include "scrnintstr.h"
+#include "regionstr.h"
+#include "windowstr.h"
+#include "pixmapstr.h"
+#include "mivalidate.h"
+#include "validate.h"
+#include "resource.h"
+#include "gcstruct.h"
+#include "dixstruct.h"
+
+#include "Xv.h"
+#include "Xvproto.h"
+#include "xvdix.h"
+#ifdef XFree86LOADER
+#include "xvmodproc.h"
+#endif
+
+#include "xf86xv.h"
+
+
+/* XvScreenRec fields */
+
+static Bool xf86XVCloseScreen(int, ScreenPtr);
+static int xf86XVQueryAdaptors(ScreenPtr, XvAdaptorPtr *, int *);
+
+/* XvAdaptorRec fields */
+
+static int xf86XVAllocatePort(unsigned long, XvPortPtr, XvPortPtr*);
+static int xf86XVFreePort(XvPortPtr);
+static int xf86XVPutVideo(ClientPtr, DrawablePtr,XvPortPtr, GCPtr,
+ INT16, INT16, CARD16, CARD16,
+ INT16, INT16, CARD16, CARD16);
+static int xf86XVPutStill(ClientPtr, DrawablePtr,XvPortPtr, GCPtr,
+ INT16, INT16, CARD16, CARD16,
+ INT16, INT16, CARD16, CARD16);
+static int xf86XVGetVideo(ClientPtr, DrawablePtr,XvPortPtr, GCPtr,
+ INT16, INT16, CARD16, CARD16,
+ INT16, INT16, CARD16, CARD16);
+static int xf86XVGetStill(ClientPtr, DrawablePtr,XvPortPtr, GCPtr,
+ INT16, INT16, CARD16, CARD16,
+ INT16, INT16, CARD16, CARD16);
+static int xf86XVStopVideo(ClientPtr, XvPortPtr, DrawablePtr);
+static int xf86XVSetPortAttribute(ClientPtr, XvPortPtr, Atom, INT32);
+static int xf86XVGetPortAttribute(ClientPtr, XvPortPtr, Atom, INT32*);
+static int xf86XVQueryBestSize(ClientPtr, XvPortPtr, CARD8,
+ CARD16, CARD16,CARD16, CARD16,
+ unsigned int*, unsigned int*);
+static int xf86XVPutImage(ClientPtr, DrawablePtr, XvPortPtr, GCPtr,
+ INT16, INT16, CARD16, CARD16,
+ INT16, INT16, CARD16, CARD16,
+ XvImagePtr, unsigned char*, Bool,
+ CARD16, CARD16);
+static int xf86XVQueryImageAttributes(ClientPtr, XvPortPtr, XvImagePtr,
+ CARD16*, CARD16*, int*, int*);
+
+
+/* ScreenRec fields */
+
+static Bool xf86XVDestroyWindow(WindowPtr pWin);
+static void xf86XVWindowExposures(WindowPtr pWin, RegionPtr r1, RegionPtr r2);
+static void xf86XVClipNotify(WindowPtr pWin, int dx, int dy);
+
+/* ScrnInfoRec functions */
+
+static Bool xf86XVEnterVT(int, int);
+static void xf86XVLeaveVT(int, int);
+static void xf86XVAdjustFrame(int index, int x, int y, int flags);
+
+/* misc */
+
+static Bool xf86XVInitAdaptors(ScreenPtr, XF86VideoAdaptorPtr*, int);
+
+
+int XF86XVWindowIndex = -1;
+int XF86XvScreenIndex = -1;
+static unsigned long XF86XVGeneration = 0;
+static unsigned long PortResource = 0;
+
+#ifdef XFree86LOADER
+int (*XvGetScreenIndexProc)(void) = NULL;
+unsigned long (*XvGetRTPortProc)(void) = NULL;
+int (*XvScreenInitProc)(ScreenPtr) = NULL;
+#else
+int (*XvGetScreenIndexProc)(void) = XvGetScreenIndex;
+unsigned long (*XvGetRTPortProc)(void) = XvGetRTPort;
+int (*XvScreenInitProc)(ScreenPtr) = XvScreenInit;
+#endif
+
+
+#define GET_XV_SCREEN(pScreen) \
+ ((XvScreenPtr)((pScreen)->devPrivates[XF86XvScreenIndex].ptr))
+
+#define GET_XF86XV_SCREEN(pScreen) \
+ ((XF86XVScreenPtr)(GET_XV_SCREEN(pScreen)->devPriv.ptr))
+
+#define GET_XF86XV_WINDOW(pWin) \
+ ((XF86XVWindowPtr)((pWin)->devPrivates[XF86XVWindowIndex].ptr))
+
+static xf86XVInitGenericAdaptorPtr *GenDrivers = NULL;
+static int NumGenDrivers = 0;
+
+int
+xf86XVRegisterGenericAdaptorDriver(
+ xf86XVInitGenericAdaptorPtr InitFunc
+){
+ xf86XVInitGenericAdaptorPtr *newdrivers;
+
+ newdrivers = xrealloc(GenDrivers, sizeof(xf86XVInitGenericAdaptorPtr) *
+ (1 + NumGenDrivers));
+ if (!newdrivers)
+ return 0;
+ GenDrivers = newdrivers;
+
+ GenDrivers[NumGenDrivers++] = InitFunc;
+
+ return 1;
+}
+
+int
+xf86XVListGenericAdaptors(
+ ScrnInfoPtr pScrn,
+ XF86VideoAdaptorPtr **adaptors
+){
+ int i,j,n,num;
+ XF86VideoAdaptorPtr *DrivAdap,*new;
+
+ num = 0;
+ *adaptors = NULL;
+ for (i = 0; i < NumGenDrivers; i++) {
+ n = GenDrivers[i](pScrn,&DrivAdap);
+ if (0 == n)
+ continue;
+ new = xrealloc(*adaptors, sizeof(XF86VideoAdaptorPtr) * (num+n));
+ if (NULL == new)
+ continue;
+ *adaptors = new;
+ for (j = 0; j < n; j++, num++)
+ (*adaptors)[num] = DrivAdap[j];
+ }
+ return num;
+}
+
+XF86VideoAdaptorPtr
+xf86XVAllocateVideoAdaptorRec(ScrnInfoPtr pScrn)
+{
+ return xcalloc(1, sizeof(XF86VideoAdaptorRec));
+}
+
+void
+xf86XVFreeVideoAdaptorRec(XF86VideoAdaptorPtr ptr)
+{
+ xfree(ptr);
+}
+
+
+Bool
+xf86XVScreenInit(
+ ScreenPtr pScreen,
+ XF86VideoAdaptorPtr *adaptors,
+ int num
+){
+ ScrnInfoPtr pScrn;
+ XF86XVScreenPtr ScreenPriv;
+ XvScreenPtr pxvs;
+
+ if(num <= 0 ||
+ !XvGetScreenIndexProc || !XvGetRTPortProc || !XvScreenInitProc)
+ return FALSE;
+
+ if(XF86XVGeneration != serverGeneration) {
+ if((XF86XVWindowIndex = AllocateWindowPrivateIndex()) < 0)
+ return FALSE;
+ XF86XVGeneration = serverGeneration;
+ }
+
+ if(!AllocateWindowPrivate(pScreen,XF86XVWindowIndex,0))
+ return FALSE;
+
+ if(Success != (*XvScreenInitProc)(pScreen)) return FALSE;
+
+ XF86XvScreenIndex = (*XvGetScreenIndexProc)();
+ PortResource = (*XvGetRTPortProc)();
+
+ pxvs = GET_XV_SCREEN(pScreen);
+
+ /* Anyone initializing the Xv layer must provide these two.
+ The Xv di layer calls them without even checking if they exist! */
+
+ pxvs->ddCloseScreen = xf86XVCloseScreen;
+ pxvs->ddQueryAdaptors = xf86XVQueryAdaptors;
+
+ /* The Xv di layer provides us with a private hook so that we don't
+ have to allocate our own screen private. They also provide
+ a CloseScreen hook so that we don't have to wrap it. I'm not
+ sure that I appreciate that. */
+
+ ScreenPriv = xalloc(sizeof(XF86XVScreenRec));
+ pxvs->devPriv.ptr = (pointer)ScreenPriv;
+
+ if(!ScreenPriv) return FALSE;
+
+ pScrn = xf86Screens[pScreen->myNum];
+
+ ScreenPriv->videoGC = NULL; /* for the helper */
+
+ ScreenPriv->DestroyWindow = pScreen->DestroyWindow;
+ ScreenPriv->WindowExposures = pScreen->WindowExposures;
+ ScreenPriv->ClipNotify = pScreen->ClipNotify;
+ ScreenPriv->EnterVT = pScrn->EnterVT;
+ ScreenPriv->LeaveVT = pScrn->LeaveVT;
+ ScreenPriv->AdjustFrame = pScrn->AdjustFrame;
+
+ pScreen->DestroyWindow = xf86XVDestroyWindow;
+ pScreen->WindowExposures = xf86XVWindowExposures;
+ pScreen->ClipNotify = xf86XVClipNotify;
+ pScrn->EnterVT = xf86XVEnterVT;
+ pScrn->LeaveVT = xf86XVLeaveVT;
+ if(pScrn->AdjustFrame)
+ pScrn->AdjustFrame = xf86XVAdjustFrame;
+
+ if(!xf86XVInitAdaptors(pScreen, adaptors, num))
+ return FALSE;
+
+ return TRUE;
+}
+
+static void
+xf86XVFreeAdaptor(XvAdaptorPtr pAdaptor)
+{
+ int i;
+
+ if(pAdaptor->name)
+ xfree(pAdaptor->name);
+
+ if(pAdaptor->pEncodings) {
+ XvEncodingPtr pEncode = pAdaptor->pEncodings;
+
+ for(i = 0; i < pAdaptor->nEncodings; i++, pEncode++) {
+ if(pEncode->name) xfree(pEncode->name);
+ }
+ xfree(pAdaptor->pEncodings);
+ }
+
+ if(pAdaptor->pFormats)
+ xfree(pAdaptor->pFormats);
+
+ if(pAdaptor->pPorts) {
+ XvPortPtr pPort = pAdaptor->pPorts;
+ XvPortRecPrivatePtr pPriv;
+
+ for(i = 0; i < pAdaptor->nPorts; i++, pPort++) {
+ pPriv = (XvPortRecPrivatePtr)pPort->devPriv.ptr;
+ if(pPriv) {
+ if(pPriv->clientClip)
+ REGION_DESTROY(pAdaptor->pScreen, pPriv->clientClip);
+ if(pPriv->pCompositeClip && pPriv->FreeCompositeClip)
+ REGION_DESTROY(pAdaptor->pScreen, pPriv->pCompositeClip);
+ xfree(pPriv);
+ }
+ }
+ xfree(pAdaptor->pPorts);
+ }
+
+ if(pAdaptor->nAttributes) {
+ XvAttributePtr pAttribute = pAdaptor->pAttributes;
+
+ for(i = 0; i < pAdaptor->nAttributes; i++, pAttribute++) {
+ if(pAttribute->name) xfree(pAttribute->name);
+ }
+
+ xfree(pAdaptor->pAttributes);
+ }
+
+ if(pAdaptor->nImages)
+ xfree(pAdaptor->pImages);
+
+ if(pAdaptor->devPriv.ptr)
+ xfree(pAdaptor->devPriv.ptr);
+}
+
+static Bool
+xf86XVInitAdaptors(
+ ScreenPtr pScreen,
+ XF86VideoAdaptorPtr *infoPtr,
+ int number
+) {
+ XvScreenPtr pxvs = GET_XV_SCREEN(pScreen);
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ XF86VideoAdaptorPtr adaptorPtr;
+ XvAdaptorPtr pAdaptor, pa;
+ XvAdaptorRecPrivatePtr adaptorPriv;
+ int na, numAdaptor;
+ XvPortRecPrivatePtr portPriv;
+ XvPortPtr pPort, pp;
+ int numPort;
+ XF86AttributePtr attributePtr;
+ XvAttributePtr pAttribute, pat;
+ XF86VideoFormatPtr formatPtr;
+ XvFormatPtr pFormat, pf;
+ int numFormat, totFormat;
+ XF86VideoEncodingPtr encodingPtr;
+ XvEncodingPtr pEncode, pe;
+ XF86ImagePtr imagePtr;
+ XvImagePtr pImage, pi;
+ int numVisuals;
+ VisualPtr pVisual;
+ int i;
+
+ pxvs->nAdaptors = 0;
+ pxvs->pAdaptors = NULL;
+
+ if(!(pAdaptor = xcalloc(number, sizeof(XvAdaptorRec))))
+ return FALSE;
+
+ for(pa = pAdaptor, na = 0, numAdaptor = 0; na < number; na++, adaptorPtr++) {
+ adaptorPtr = infoPtr[na];
+
+ if(!adaptorPtr->StopVideo || !adaptorPtr->SetPortAttribute ||
+ !adaptorPtr->GetPortAttribute || !adaptorPtr->QueryBestSize)
+ continue;
+
+ /* client libs expect at least one encoding */
+ if(!adaptorPtr->nEncodings || !adaptorPtr->pEncodings)
+ continue;
+
+ pa->type = adaptorPtr->type;
+
+ if(!adaptorPtr->PutVideo && !adaptorPtr->GetVideo)
+ pa->type &= ~XvVideoMask;
+
+ if(!adaptorPtr->PutStill && !adaptorPtr->GetStill)
+ pa->type &= ~XvStillMask;
+
+ if(!adaptorPtr->PutImage || !adaptorPtr->QueryImageAttributes)
+ pa->type &= ~XvImageMask;
+
+ if(!adaptorPtr->PutVideo && !adaptorPtr->PutImage &&
+ !adaptorPtr->PutStill)
+ pa->type &= ~XvInputMask;
+
+ if(!adaptorPtr->GetVideo && !adaptorPtr->GetStill)
+ pa->type &= ~XvOutputMask;
+
+ if(!(adaptorPtr->type & (XvPixmapMask | XvWindowMask)))
+ continue;
+ if(!(adaptorPtr->type & (XvImageMask | XvVideoMask | XvStillMask)))
+ continue;
+
+ pa->pScreen = pScreen;
+ pa->ddAllocatePort = xf86XVAllocatePort;
+ pa->ddFreePort = xf86XVFreePort;
+ pa->ddPutVideo = xf86XVPutVideo;
+ pa->ddPutStill = xf86XVPutStill;
+ pa->ddGetVideo = xf86XVGetVideo;
+ pa->ddGetStill = xf86XVGetStill;
+ pa->ddStopVideo = xf86XVStopVideo;
+ pa->ddPutImage = xf86XVPutImage;
+ pa->ddSetPortAttribute = xf86XVSetPortAttribute;
+ pa->ddGetPortAttribute = xf86XVGetPortAttribute;
+ pa->ddQueryBestSize = xf86XVQueryBestSize;
+ pa->ddQueryImageAttributes = xf86XVQueryImageAttributes;
+ if((pa->name = xalloc(strlen(adaptorPtr->name) + 1)))
+ strcpy(pa->name, adaptorPtr->name);
+
+ if(adaptorPtr->nEncodings &&
+ (pEncode = xcalloc(adaptorPtr->nEncodings, sizeof(XvEncodingRec)))) {
+
+ for(pe = pEncode, encodingPtr = adaptorPtr->pEncodings, i = 0;
+ i < adaptorPtr->nEncodings; pe++, i++, encodingPtr++)
+ {
+ pe->id = encodingPtr->id;
+ pe->pScreen = pScreen;
+ if((pe->name = xalloc(strlen(encodingPtr->name) + 1)))
+ strcpy(pe->name, encodingPtr->name);
+ pe->width = encodingPtr->width;
+ pe->height = encodingPtr->height;
+ pe->rate.numerator = encodingPtr->rate.numerator;
+ pe->rate.denominator = encodingPtr->rate.denominator;
+ }
+ pa->nEncodings = adaptorPtr->nEncodings;
+ pa->pEncodings = pEncode;
+ }
+
+ if(adaptorPtr->nImages &&
+ (pImage = xcalloc(adaptorPtr->nImages, sizeof(XvImageRec)))) {
+
+ for(i = 0, pi = pImage, imagePtr = adaptorPtr->pImages;
+ i < adaptorPtr->nImages; i++, pi++, imagePtr++)
+ {
+ pi->id = imagePtr->id;
+ pi->type = imagePtr->type;
+ pi->byte_order = imagePtr->byte_order;
+ memcpy(pi->guid, imagePtr->guid, 16);
+ pi->bits_per_pixel = imagePtr->bits_per_pixel;
+ pi->format = imagePtr->format;
+ pi->num_planes = imagePtr->num_planes;
+ pi->depth = imagePtr->depth;
+ pi->red_mask = imagePtr->red_mask;
+ pi->green_mask = imagePtr->green_mask;
+ pi->blue_mask = imagePtr->blue_mask;
+ pi->y_sample_bits = imagePtr->y_sample_bits;
+ pi->u_sample_bits = imagePtr->u_sample_bits;
+ pi->v_sample_bits = imagePtr->v_sample_bits;
+ pi->horz_y_period = imagePtr->horz_y_period;
+ pi->horz_u_period = imagePtr->horz_u_period;
+ pi->horz_v_period = imagePtr->horz_v_period;
+ pi->vert_y_period = imagePtr->vert_y_period;
+ pi->vert_u_period = imagePtr->vert_u_period;
+ pi->vert_v_period = imagePtr->vert_v_period;
+ memcpy(pi->component_order, imagePtr->component_order, 32);
+ pi->scanline_order = imagePtr->scanline_order;
+ }
+ pa->nImages = adaptorPtr->nImages;
+ pa->pImages = pImage;
+ }
+
+ if(adaptorPtr->nAttributes &&
+ (pAttribute = xcalloc(adaptorPtr->nAttributes, sizeof(XvAttributeRec))))
+ {
+ for(pat = pAttribute, attributePtr = adaptorPtr->pAttributes, i = 0;
+ i < adaptorPtr->nAttributes; pat++, i++, attributePtr++)
+ {
+ pat->flags = attributePtr->flags;
+ pat->min_value = attributePtr->min_value;
+ pat->max_value = attributePtr->max_value;
+ if((pat->name = xalloc(strlen(attributePtr->name) + 1)))
+ strcpy(pat->name, attributePtr->name);
+ }
+ pa->nAttributes = adaptorPtr->nAttributes;
+ pa->pAttributes = pAttribute;
+ }
+
+
+ totFormat = adaptorPtr->nFormats;
+
+ if(!(pFormat = xcalloc(totFormat, sizeof(XvFormatRec)))) {
+ xf86XVFreeAdaptor(pa);
+ continue;
+ }
+ for(pf = pFormat, i = 0, numFormat = 0, formatPtr = adaptorPtr->pFormats;
+ i < adaptorPtr->nFormats; i++, formatPtr++)
+ {
+ numVisuals = pScreen->numVisuals;
+ pVisual = pScreen->visuals;
+
+ while(numVisuals--) {
+ if((pVisual->class == formatPtr->class) &&
+ (pVisual->nplanes == formatPtr->depth)) {
+
+ if(numFormat >= totFormat) {
+ void *moreSpace;
+ totFormat *= 2;
+ moreSpace = xrealloc(pFormat,
+ totFormat * sizeof(XvFormatRec));
+ if(!moreSpace) break;
+ pFormat = moreSpace;
+ pf = pFormat + numFormat;
+ }
+
+ pf->visual = pVisual->vid;
+ pf->depth = formatPtr->depth;
+
+ pf++;
+ numFormat++;
+ }
+ pVisual++;
+ }
+ }
+ pa->nFormats = numFormat;
+ pa->pFormats = pFormat;
+ if(!numFormat) {
+ xf86XVFreeAdaptor(pa);
+ continue;
+ }
+
+ if(!(adaptorPriv = xcalloc(1, sizeof(XvAdaptorRecPrivate)))) {
+ xf86XVFreeAdaptor(pa);
+ continue;
+ }
+
+ adaptorPriv->flags = adaptorPtr->flags;
+ adaptorPriv->PutVideo = adaptorPtr->PutVideo;
+ adaptorPriv->PutStill = adaptorPtr->PutStill;
+ adaptorPriv->GetVideo = adaptorPtr->GetVideo;
+ adaptorPriv->GetStill = adaptorPtr->GetStill;
+ adaptorPriv->StopVideo = adaptorPtr->StopVideo;
+ adaptorPriv->SetPortAttribute = adaptorPtr->SetPortAttribute;
+ adaptorPriv->GetPortAttribute = adaptorPtr->GetPortAttribute;
+ adaptorPriv->QueryBestSize = adaptorPtr->QueryBestSize;
+ adaptorPriv->QueryImageAttributes = adaptorPtr->QueryImageAttributes;
+ adaptorPriv->PutImage = adaptorPtr->PutImage;
+ adaptorPriv->ReputImage = adaptorPtr->ReputImage;
+
+ pa->devPriv.ptr = (pointer)adaptorPriv;
+
+ if(!(pPort = xcalloc(adaptorPtr->nPorts, sizeof(XvPortRec)))) {
+ xf86XVFreeAdaptor(pa);
+ continue;
+ }
+ for(pp = pPort, i = 0, numPort = 0;
+ i < adaptorPtr->nPorts; i++) {
+
+ if(!(pp->id = FakeClientID(0)))
+ continue;
+
+ if(!(portPriv = xcalloc(1, sizeof(XvPortRecPrivate))))
+ continue;
+
+ if(!AddResource(pp->id, PortResource, pp)) {
+ xfree(portPriv);
+ continue;
+ }
+
+ pp->pAdaptor = pa;
+ pp->pNotify = (XvPortNotifyPtr)NULL;
+ pp->pDraw = (DrawablePtr)NULL;
+ pp->client = (ClientPtr)NULL;
+ pp->grab.client = (ClientPtr)NULL;
+ pp->time = currentTime;
+ pp->devPriv.ptr = portPriv;
+
+ portPriv->pScrn = pScrn;
+ portPriv->AdaptorRec = adaptorPriv;
+ portPriv->DevPriv.ptr = adaptorPtr->pPortPrivates[i].ptr;
+
+ pp++;
+ numPort++;
+ }
+ pa->nPorts = numPort;
+ pa->pPorts = pPort;
+ if(!numPort) {
+ xf86XVFreeAdaptor(pa);
+ continue;
+ }
+
+ pa->base_id = pPort->id;
+
+ pa++;
+ numAdaptor++;
+ }
+
+ if(numAdaptor) {
+ pxvs->nAdaptors = numAdaptor;
+ pxvs->pAdaptors = pAdaptor;
+ } else {
+ xfree(pAdaptor);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/* Video should be clipped to the intersection of the window cliplist
+ and the client cliplist specified in the GC for which the video was
+ initialized. When we need to reclip a window, the GC that started
+ the video may not even be around anymore. That's why we save the
+ client clip from the GC when the video is initialized. We then
+ use xf86XVUpdateCompositeClip to calculate the new composite clip
+ when we need it. This is different from what DEC did. They saved
+ the GC and used it's clip list when they needed to reclip the window,
+ even if the client clip was different from the one the video was
+ initialized with. If the original GC was destroyed, they had to stop
+ the video. I like the new method better (MArk).
+
+ This function only works for windows. Will need to rewrite when
+ (if) we support pixmap rendering.
+*/
+
+static void
+xf86XVUpdateCompositeClip(XvPortRecPrivatePtr portPriv)
+{
+ RegionPtr pregWin, pCompositeClip;
+ WindowPtr pWin;
+ Bool freeCompClip = FALSE;
+
+ if(portPriv->pCompositeClip)
+ return;
+
+ pWin = (WindowPtr)portPriv->pDraw;
+
+ /* get window clip list */
+ if(portPriv->subWindowMode == IncludeInferiors) {
+ pregWin = NotClippedByChildren(pWin);
+ freeCompClip = TRUE;
+ } else
+ pregWin = &pWin->clipList;
+
+ if(!portPriv->clientClip) {
+ portPriv->pCompositeClip = pregWin;
+ portPriv->FreeCompositeClip = freeCompClip;
+ return;
+ }
+
+ pCompositeClip = REGION_CREATE(pWin->pScreen, NullBox, 1);
+ REGION_COPY(pWin->pScreen, pCompositeClip, portPriv->clientClip);
+ REGION_TRANSLATE(pWin->pScreen, pCompositeClip,
+ portPriv->pDraw->x + portPriv->clipOrg.x,
+ portPriv->pDraw->y + portPriv->clipOrg.y);
+ REGION_INTERSECT(pWin->pScreen, pCompositeClip, pregWin, pCompositeClip);
+
+ portPriv->pCompositeClip = pCompositeClip;
+ portPriv->FreeCompositeClip = TRUE;
+
+ if(freeCompClip) {
+ REGION_DESTROY(pWin->pScreen, pregWin);
+ }
+}
+
+/* Save the current clientClip and update the CompositeClip whenever
+ we have a fresh GC */
+
+static void
+xf86XVCopyClip(
+ XvPortRecPrivatePtr portPriv,
+ GCPtr pGC
+){
+ /* copy the new clip if it exists */
+ if((pGC->clientClipType == CT_REGION) && pGC->clientClip) {
+ if(!portPriv->clientClip)
+ portPriv->clientClip = REGION_CREATE(pGC->pScreen, NullBox, 1);
+ /* Note: this is in window coordinates */
+ REGION_COPY(pGC->pScreen, portPriv->clientClip, pGC->clientClip);
+ } else if(portPriv->clientClip) { /* free the old clientClip */
+ REGION_DESTROY(pGC->pScreen, portPriv->clientClip);
+ portPriv->clientClip = NULL;
+ }
+
+ /* get rid of the old clip list */
+ if(portPriv->pCompositeClip && portPriv->FreeCompositeClip) {
+ REGION_DESTROY(pWin->pScreen, portPriv->pCompositeClip);
+ }
+
+ portPriv->clipOrg = pGC->clipOrg;
+ portPriv->pCompositeClip = pGC->pCompositeClip;
+ portPriv->FreeCompositeClip = FALSE;
+ portPriv->subWindowMode = pGC->subWindowMode;
+}
+
+static int
+xf86XVRegetVideo(XvPortRecPrivatePtr portPriv)
+{
+ RegionRec WinRegion;
+ RegionRec ClipRegion;
+ BoxRec WinBox;
+ ScreenPtr pScreen;
+ int ret = Success;
+ Bool clippedAway = FALSE;
+
+ pScreen = portPriv->pDraw->pScreen;
+ xf86XVUpdateCompositeClip(portPriv);
+
+ /* translate the video region to the screen */
+ WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x;
+ WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y;
+ WinBox.x2 = WinBox.x1 + portPriv->drw_w;
+ WinBox.y2 = WinBox.y1 + portPriv->drw_h;
+
+ /* clip to the window composite clip */
+ REGION_INIT(pScreen, &WinRegion, &WinBox, 1);
+ REGION_INIT(pScreen, &ClipRegion, NullBox, 1);
+ REGION_INTERSECT(Screen, &ClipRegion, &WinRegion, portPriv->pCompositeClip);
+
+ /* that's all if it's totally obscured */
+ if(!REGION_NOTEMPTY(pScreen, &ClipRegion)) {
+ clippedAway = TRUE;
+ goto CLIP_VIDEO_BAILOUT;
+ }
+
+ if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) {
+ REGION_SUBTRACT(pScreen, &ClipRegion, &WinRegion, &ClipRegion);
+ }
+
+ ret = (*portPriv->AdaptorRec->GetVideo)(portPriv->pScrn,
+ portPriv->vid_x, portPriv->vid_y,
+ WinBox.x1, WinBox.y1,
+ portPriv->vid_w, portPriv->vid_h,
+ portPriv->drw_w, portPriv->drw_h,
+ &ClipRegion, portPriv->DevPriv.ptr);
+
+ if(ret == Success)
+ portPriv->isOn = XV_ON;
+
+CLIP_VIDEO_BAILOUT:
+
+ if((clippedAway || (ret != Success)) && portPriv->isOn == XV_ON) {
+ (*portPriv->AdaptorRec->StopVideo)(
+ portPriv->pScrn, portPriv->DevPriv.ptr, FALSE);
+ portPriv->isOn = XV_PENDING;
+ }
+
+ /* This clip was copied and only good for one shot */
+ if(!portPriv->FreeCompositeClip)
+ portPriv->pCompositeClip = NULL;
+
+ REGION_UNINIT(pScreen, &WinRegion);
+ REGION_UNINIT(pScreen, &ClipRegion);
+
+ return ret;
+}
+
+
+static int
+xf86XVReputVideo(XvPortRecPrivatePtr portPriv)
+{
+ RegionRec WinRegion;
+ RegionRec ClipRegion;
+ BoxRec WinBox;
+ ScreenPtr pScreen;
+ int ret = Success;
+ Bool clippedAway = FALSE;
+
+ pScreen = portPriv->pDraw->pScreen;
+
+ xf86XVUpdateCompositeClip(portPriv);
+
+ /* translate the video region to the screen */
+ WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x;
+ WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y;
+ WinBox.x2 = WinBox.x1 + portPriv->drw_w;
+ WinBox.y2 = WinBox.y1 + portPriv->drw_h;
+
+ /* clip to the window composite clip */
+ REGION_INIT(pScreen, &WinRegion, &WinBox, 1);
+ REGION_INIT(pScreen, &ClipRegion, NullBox, 1);
+ REGION_INTERSECT(Screen, &ClipRegion, &WinRegion, portPriv->pCompositeClip);
+
+ /* clip and translate to the viewport */
+ if(portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) {
+ RegionRec VPReg;
+ BoxRec VPBox;
+
+ VPBox.x1 = portPriv->pScrn->frameX0;
+ VPBox.y1 = portPriv->pScrn->frameY0;
+ VPBox.x2 = portPriv->pScrn->frameX1;
+ VPBox.y2 = portPriv->pScrn->frameY1;
+
+ REGION_INIT(pScreen, &VPReg, &VPBox, 1);
+ REGION_INTERSECT(Screen, &ClipRegion, &ClipRegion, &VPReg);
+ REGION_UNINIT(pScreen, &VPReg);
+ }
+
+ /* that's all if it's totally obscured */
+ if(!REGION_NOTEMPTY(pScreen, &ClipRegion)) {
+ clippedAway = TRUE;
+ goto CLIP_VIDEO_BAILOUT;
+ }
+
+ /* bailout if we have to clip but the hardware doesn't support it */
+ if(portPriv->AdaptorRec->flags & VIDEO_NO_CLIPPING) {
+ BoxPtr clipBox = REGION_RECTS(&ClipRegion);
+ if( (REGION_NUM_RECTS(&ClipRegion) != 1) ||
+ (clipBox->x1 != WinBox.x1) || (clipBox->x2 != WinBox.x2) ||
+ (clipBox->y1 != WinBox.y1) || (clipBox->y2 != WinBox.y2))
+ {
+ clippedAway = TRUE;
+ goto CLIP_VIDEO_BAILOUT;
+ }
+ }
+
+ if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) {
+ REGION_SUBTRACT(pScreen, &ClipRegion, &WinRegion, &ClipRegion);
+ }
+
+ ret = (*portPriv->AdaptorRec->PutVideo)(portPriv->pScrn,
+ portPriv->vid_x, portPriv->vid_y,
+ WinBox.x1, WinBox.y1,
+ portPriv->vid_w, portPriv->vid_h,
+ portPriv->drw_w, portPriv->drw_h,
+ &ClipRegion, portPriv->DevPriv.ptr);
+
+ if(ret == Success) portPriv->isOn = XV_ON;
+
+CLIP_VIDEO_BAILOUT:
+
+ if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
+ (*portPriv->AdaptorRec->StopVideo)(
+ portPriv->pScrn, portPriv->DevPriv.ptr, FALSE);
+ portPriv->isOn = XV_PENDING;
+ }
+
+ /* This clip was copied and only good for one shot */
+ if(!portPriv->FreeCompositeClip)
+ portPriv->pCompositeClip = NULL;
+
+ REGION_UNINIT(pScreen, &WinRegion);
+ REGION_UNINIT(pScreen, &ClipRegion);
+
+ return ret;
+}
+
+static int
+xf86XVReputImage(XvPortRecPrivatePtr portPriv)
+{
+ RegionRec WinRegion;
+ RegionRec ClipRegion;
+ BoxRec WinBox;
+ ScreenPtr pScreen;
+ int ret = Success;
+ Bool clippedAway = FALSE;
+
+ pScreen = portPriv->pDraw->pScreen;
+
+ xf86XVUpdateCompositeClip(portPriv);
+
+ /* translate the video region to the screen */
+ WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x;
+ WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y;
+ WinBox.x2 = WinBox.x1 + portPriv->drw_w;
+ WinBox.y2 = WinBox.y1 + portPriv->drw_h;
+
+ /* clip to the window composite clip */
+ REGION_INIT(pScreen, &WinRegion, &WinBox, 1);
+ REGION_INIT(pScreen, &ClipRegion, NullBox, 1);
+ REGION_INTERSECT(Screen, &ClipRegion, &WinRegion, portPriv->pCompositeClip);
+
+ /* clip and translate to the viewport */
+ if(portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) {
+ RegionRec VPReg;
+ BoxRec VPBox;
+
+ VPBox.x1 = portPriv->pScrn->frameX0;
+ VPBox.y1 = portPriv->pScrn->frameY0;
+ VPBox.x2 = portPriv->pScrn->frameX1;
+ VPBox.y2 = portPriv->pScrn->frameY1;
+
+ REGION_INIT(pScreen, &VPReg, &VPBox, 1);
+ REGION_INTERSECT(Screen, &ClipRegion, &ClipRegion, &VPReg);
+ REGION_UNINIT(pScreen, &VPReg);
+ }
+
+ /* that's all if it's totally obscured */
+ if(!REGION_NOTEMPTY(pScreen, &ClipRegion)) {
+ clippedAway = TRUE;
+ goto CLIP_VIDEO_BAILOUT;
+ }
+
+ /* bailout if we have to clip but the hardware doesn't support it */
+ if(portPriv->AdaptorRec->flags & VIDEO_NO_CLIPPING) {
+ BoxPtr clipBox = REGION_RECTS(&ClipRegion);
+ if( (REGION_NUM_RECTS(&ClipRegion) != 1) ||
+ (clipBox->x1 != WinBox.x1) || (clipBox->x2 != WinBox.x2) ||
+ (clipBox->y1 != WinBox.y1) || (clipBox->y2 != WinBox.y2))
+ {
+ clippedAway = TRUE;
+ goto CLIP_VIDEO_BAILOUT;
+ }
+ }
+
+ if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) {
+ REGION_SUBTRACT(pScreen, &ClipRegion, &WinRegion, &ClipRegion);
+ }
+
+ ret = (*portPriv->AdaptorRec->ReputImage)(portPriv->pScrn,
+ WinBox.x1, WinBox.y1,
+ &ClipRegion, portPriv->DevPriv.ptr);
+
+ portPriv->isOn = (ret == Success) ? XV_ON : XV_OFF;
+
+CLIP_VIDEO_BAILOUT:
+
+ if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
+ (*portPriv->AdaptorRec->StopVideo)(
+ portPriv->pScrn, portPriv->DevPriv.ptr, FALSE);
+ portPriv->isOn = XV_PENDING;
+ }
+
+ /* This clip was copied and only good for one shot */
+ if(!portPriv->FreeCompositeClip)
+ portPriv->pCompositeClip = NULL;
+
+ REGION_UNINIT(pScreen, &WinRegion);
+ REGION_UNINIT(pScreen, &ClipRegion);
+
+ return ret;
+}
+
+
+static int
+xf86XVReputAllVideo(WindowPtr pWin, pointer data)
+{
+ XF86XVWindowPtr WinPriv = GET_XF86XV_WINDOW(pWin);
+
+ while(WinPriv) {
+ if(WinPriv->PortRec->type == XvInputMask)
+ xf86XVReputVideo(WinPriv->PortRec);
+ else
+ xf86XVRegetVideo(WinPriv->PortRec);
+ WinPriv = WinPriv->next;
+ }
+
+ return WT_WALKCHILDREN;
+}
+
+static int
+xf86XVEnlistPortInWindow(WindowPtr pWin, XvPortRecPrivatePtr portPriv)
+{
+ XF86XVWindowPtr winPriv, PrivRoot;
+
+ winPriv = PrivRoot = GET_XF86XV_WINDOW(pWin);
+
+ /* Enlist our port in the window private */
+ while(winPriv) {
+ if(winPriv->PortRec == portPriv) /* we're already listed */
+ break;
+ winPriv = winPriv->next;
+ }
+
+ if(!winPriv) {
+ winPriv = xalloc(sizeof(XF86XVWindowRec));
+ if(!winPriv) return BadAlloc;
+ winPriv->PortRec = portPriv;
+ winPriv->next = PrivRoot;
+ pWin->devPrivates[XF86XVWindowIndex].ptr = (pointer)winPriv;
+ }
+ return Success;
+}
+
+
+static void
+xf86XVRemovePortFromWindow(WindowPtr pWin, XvPortRecPrivatePtr portPriv)
+{
+ XF86XVWindowPtr winPriv, prevPriv = NULL;
+
+ winPriv = GET_XF86XV_WINDOW(pWin);
+
+ while(winPriv) {
+ if(winPriv->PortRec == portPriv) {
+ if(prevPriv)
+ prevPriv->next = winPriv->next;
+ else
+ pWin->devPrivates[XF86XVWindowIndex].ptr =
+ (pointer)winPriv->next;
+ xfree(winPriv);
+ break;
+ }
+ prevPriv = winPriv;
+ winPriv = winPriv->next;
+ }
+ portPriv->pDraw = NULL;
+}
+
+/**** ScreenRec fields ****/
+
+static Bool
+xf86XVDestroyWindow(WindowPtr pWin)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen);
+ XF86XVWindowPtr tmp, WinPriv = GET_XF86XV_WINDOW(pWin);
+ int ret;
+
+ while(WinPriv) {
+ XvPortRecPrivatePtr pPriv = WinPriv->PortRec;
+
+ if(pPriv->isOn > XV_OFF) {
+ (*pPriv->AdaptorRec->StopVideo)(
+ pPriv->pScrn, pPriv->DevPriv.ptr, TRUE);
+ pPriv->isOn = XV_OFF;
+ }
+
+ pPriv->pDraw = NULL;
+ tmp = WinPriv;
+ WinPriv = WinPriv->next;
+ xfree(tmp);
+ }
+
+ pWin->devPrivates[XF86XVWindowIndex].ptr = NULL;
+
+ pScreen->DestroyWindow = ScreenPriv->DestroyWindow;
+ ret = (*pScreen->DestroyWindow)(pWin);
+ pScreen->DestroyWindow = xf86XVDestroyWindow;
+
+ return ret;
+}
+
+
+static void
+xf86XVWindowExposures(WindowPtr pWin, RegionPtr reg1, RegionPtr reg2)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen);
+ XF86XVWindowPtr WinPriv = GET_XF86XV_WINDOW(pWin);
+ XF86XVWindowPtr pPrev;
+ XvPortRecPrivatePtr pPriv;
+ Bool AreasExposed;
+
+ AreasExposed = (WinPriv && reg1 && REGION_NOTEMPTY(pScreen, reg1));
+
+ pScreen->WindowExposures = ScreenPriv->WindowExposures;
+ (*pScreen->WindowExposures)(pWin, reg1, reg2);
+ pScreen->WindowExposures = xf86XVWindowExposures;
+
+ /* filter out XClearWindow/Area */
+ if (!pWin->valdata) return;
+
+ pPrev = NULL;
+
+ while(WinPriv) {
+ pPriv = WinPriv->PortRec;
+
+ /* Reput anyone with a reput function */
+
+ switch(pPriv->type) {
+ case XvInputMask:
+ xf86XVReputVideo(pPriv);
+ break;
+ case XvOutputMask:
+ xf86XVRegetVideo(pPriv);
+ break;
+ default: /* overlaid still/image*/
+ if (pPriv->AdaptorRec->ReputImage)
+ xf86XVReputImage(pPriv);
+ else if(AreasExposed) {
+ XF86XVWindowPtr tmp;
+
+ if (pPriv->isOn == XV_ON) {
+ (*pPriv->AdaptorRec->StopVideo)(
+ pPriv->pScrn, pPriv->DevPriv.ptr, FALSE);
+ pPriv->isOn = XV_PENDING;
+ }
+ pPriv->pDraw = NULL;
+
+ if(!pPrev)
+ pWin->devPrivates[XF86XVWindowIndex].ptr =
+ (pointer)(WinPriv->next);
+ else
+ pPrev->next = WinPriv->next;
+ tmp = WinPriv;
+ WinPriv = WinPriv->next;
+ xfree(tmp);
+ continue;
+ }
+ break;
+ }
+ pPrev = WinPriv;
+ WinPriv = WinPriv->next;
+ }
+}
+
+
+static void
+xf86XVClipNotify(WindowPtr pWin, int dx, int dy)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen);
+ XF86XVWindowPtr WinPriv = GET_XF86XV_WINDOW(pWin);
+ XF86XVWindowPtr tmp, pPrev = NULL;
+ XvPortRecPrivatePtr pPriv;
+ Bool visible = (pWin->visibility == VisibilityUnobscured) ||
+ (pWin->visibility == VisibilityPartiallyObscured);
+
+ while(WinPriv) {
+ pPriv = WinPriv->PortRec;
+
+ if(pPriv->pCompositeClip && pPriv->FreeCompositeClip)
+ REGION_DESTROY(pScreen, pPriv->pCompositeClip);
+
+ pPriv->pCompositeClip = NULL;
+
+ /* Stop everything except images, but stop them too if the
+ window isn't visible. But we only remove the images. */
+
+ if(pPriv->type || !visible) {
+ if(pPriv->isOn == XV_ON) {
+ (*pPriv->AdaptorRec->StopVideo)(
+ pPriv->pScrn, pPriv->DevPriv.ptr, FALSE);
+ pPriv->isOn = XV_PENDING;
+ }
+
+ if(!pPriv->type) { /* overlaid still/image */
+ pPriv->pDraw = NULL;
+
+ if(!pPrev)
+ pWin->devPrivates[XF86XVWindowIndex].ptr =
+ (pointer)(WinPriv->next);
+ else
+ pPrev->next = WinPriv->next;
+ tmp = WinPriv;
+ WinPriv = WinPriv->next;
+ xfree(tmp);
+ continue;
+ }
+ }
+
+ pPrev = WinPriv;
+ WinPriv = WinPriv->next;
+ }
+
+ if(ScreenPriv->ClipNotify) {
+ pScreen->ClipNotify = ScreenPriv->ClipNotify;
+ (*pScreen->ClipNotify)(pWin, dx, dy);
+ pScreen->ClipNotify = xf86XVClipNotify;
+ }
+}
+
+
+
+/**** Required XvScreenRec fields ****/
+
+static Bool
+xf86XVCloseScreen(int i, ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ XvScreenPtr pxvs = GET_XV_SCREEN(pScreen);
+ XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen);
+ XvAdaptorPtr pa;
+ int c;
+
+ if(!ScreenPriv) return TRUE;
+
+ if(ScreenPriv->videoGC) {
+ FreeGC(ScreenPriv->videoGC, 0);
+ ScreenPriv->videoGC = NULL;
+ }
+
+ pScreen->DestroyWindow = ScreenPriv->DestroyWindow;
+ pScreen->WindowExposures = ScreenPriv->WindowExposures;
+ pScreen->ClipNotify = ScreenPriv->ClipNotify;
+
+ pScrn->EnterVT = ScreenPriv->EnterVT;
+ pScrn->LeaveVT = ScreenPriv->LeaveVT;
+ pScrn->AdjustFrame = ScreenPriv->AdjustFrame;
+
+ for(c = 0, pa = pxvs->pAdaptors; c < pxvs->nAdaptors; c++, pa++) {
+ xf86XVFreeAdaptor(pa);
+ }
+
+ if(pxvs->pAdaptors)
+ xfree(pxvs->pAdaptors);
+
+ xfree(ScreenPriv);
+
+
+ return TRUE;
+}
+
+
+static int
+xf86XVQueryAdaptors(
+ ScreenPtr pScreen,
+ XvAdaptorPtr *p_pAdaptors,
+ int *p_nAdaptors
+){
+ XvScreenPtr pxvs = GET_XV_SCREEN(pScreen);
+
+ *p_nAdaptors = pxvs->nAdaptors;
+ *p_pAdaptors = pxvs->pAdaptors;
+
+ return (Success);
+}
+
+
+/**** ScrnInfoRec fields ****/
+
+static Bool
+xf86XVEnterVT(int index, int flags)
+{
+ ScreenPtr pScreen = screenInfo.screens[index];
+ XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen);
+ Bool ret;
+
+ ret = (*ScreenPriv->EnterVT)(index, flags);
+
+ if(ret) WalkTree(pScreen, xf86XVReputAllVideo, 0);
+
+ return ret;
+}
+
+static void
+xf86XVLeaveVT(int index, int flags)
+{
+ ScreenPtr pScreen = screenInfo.screens[index];
+ XvScreenPtr pxvs = GET_XV_SCREEN(pScreen);
+ XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen);
+ XvAdaptorPtr pAdaptor;
+ XvPortPtr pPort;
+ XvPortRecPrivatePtr pPriv;
+ int i, j;
+
+ for(i = 0; i < pxvs->nAdaptors; i++) {
+ pAdaptor = &pxvs->pAdaptors[i];
+ for(j = 0; j < pAdaptor->nPorts; j++) {
+ pPort = &pAdaptor->pPorts[j];
+ pPriv = (XvPortRecPrivatePtr)pPort->devPriv.ptr;
+ if(pPriv->isOn > XV_OFF) {
+
+ (*pPriv->AdaptorRec->StopVideo)(
+ pPriv->pScrn, pPriv->DevPriv.ptr, TRUE);
+ pPriv->isOn = XV_OFF;
+
+ if(pPriv->pCompositeClip && pPriv->FreeCompositeClip)
+ REGION_DESTROY(pScreen, pPriv->pCompositeClip);
+
+ pPriv->pCompositeClip = NULL;
+
+ if(!pPriv->type && pPriv->pDraw) { /* still */
+ xf86XVRemovePortFromWindow((WindowPtr)pPriv->pDraw, pPriv);
+ }
+ }
+ }
+ }
+
+ (*ScreenPriv->LeaveVT)(index, flags);
+}
+
+static void
+xf86XVAdjustFrame(int index, int x, int y, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[index];
+ ScreenPtr pScreen = pScrn->pScreen;
+ XvScreenPtr pxvs = GET_XV_SCREEN(pScreen);
+ XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen);
+ WindowPtr pWin;
+ XvAdaptorPtr pa;
+ int c, i;
+
+ if(ScreenPriv->AdjustFrame) {
+ pScrn->AdjustFrame = ScreenPriv->AdjustFrame;
+ (*pScrn->AdjustFrame)(index, x, y, flags);
+ pScrn->AdjustFrame = xf86XVAdjustFrame;
+ }
+
+ for(c = pxvs->nAdaptors, pa = pxvs->pAdaptors; c > 0; c--, pa++) {
+ XvPortPtr pPort = pa->pPorts;
+ XvPortRecPrivatePtr pPriv;
+
+ for(i = pa->nPorts; i > 0; i--, pPort++) {
+ pPriv = (XvPortRecPrivatePtr)pPort->devPriv.ptr;
+
+ if(!pPriv->type && (pPriv->isOn == XV_ON)) { /* overlaid still/image */
+
+ if(pPriv->pCompositeClip && pPriv->FreeCompositeClip)
+ REGION_DESTROY(pScreen, pPriv->pCompositeClip);
+
+ pPriv->pCompositeClip = NULL;
+
+ pWin = (WindowPtr)pPriv->pDraw;
+
+ if ((pPriv->AdaptorRec->ReputImage) &&
+ ((pWin->visibility == VisibilityUnobscured) ||
+ (pWin->visibility == VisibilityPartiallyObscured)))
+ {
+ xf86XVReputImage(pPriv);
+ } else {
+ (*pPriv->AdaptorRec->StopVideo)(
+ pPriv->pScrn, pPriv->DevPriv.ptr, FALSE);
+ xf86XVRemovePortFromWindow(pWin, pPriv);
+ pPriv->isOn = XV_PENDING;
+ continue;
+ }
+ }
+ }
+ }
+}
+
+
+/**** XvAdaptorRec fields ****/
+
+static int
+xf86XVAllocatePort(
+ unsigned long port,
+ XvPortPtr pPort,
+ XvPortPtr *ppPort
+){
+ *ppPort = pPort;
+ return Success;
+}
+
+
+
+static int
+xf86XVFreePort(XvPortPtr pPort)
+{
+ return Success;
+}
+
+
+static int
+xf86XVPutVideo(
+ ClientPtr client,
+ DrawablePtr pDraw,
+ XvPortPtr pPort,
+ GCPtr pGC,
+ INT16 vid_x, INT16 vid_y,
+ CARD16 vid_w, CARD16 vid_h,
+ INT16 drw_x, INT16 drw_y,
+ CARD16 drw_w, CARD16 drw_h
+){
+ XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
+ int result;
+
+ /* No dumping video to pixmaps... For now anyhow */
+ if(pDraw->type != DRAWABLE_WINDOW) {
+ pPort->pDraw = (DrawablePtr)NULL;
+ return BadAlloc;
+ }
+
+ /* If we are changing windows, unregister our port in the old window */
+ if(portPriv->pDraw && (portPriv->pDraw != pDraw))
+ xf86XVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv);
+
+ /* Register our port with the new window */
+ result = xf86XVEnlistPortInWindow((WindowPtr)pDraw, portPriv);
+ if(result != Success) return result;
+
+ portPriv->pDraw = pDraw;
+ portPriv->type = XvInputMask;
+
+ /* save a copy of these parameters */
+ portPriv->vid_x = vid_x; portPriv->vid_y = vid_y;
+ portPriv->vid_w = vid_w; portPriv->vid_h = vid_h;
+ portPriv->drw_x = drw_x; portPriv->drw_y = drw_y;
+ portPriv->drw_w = drw_w; portPriv->drw_h = drw_h;
+
+ /* make sure we have the most recent copy of the clientClip */
+ xf86XVCopyClip(portPriv, pGC);
+
+ /* To indicate to the DI layer that we were successful */
+ pPort->pDraw = pDraw;
+
+ if(!portPriv->pScrn->vtSema) return Success; /* Success ? */
+
+ return(xf86XVReputVideo(portPriv));
+}
+
+static int
+xf86XVPutStill(
+ ClientPtr client,
+ DrawablePtr pDraw,
+ XvPortPtr pPort,
+ GCPtr pGC,
+ INT16 vid_x, INT16 vid_y,
+ CARD16 vid_w, CARD16 vid_h,
+ INT16 drw_x, INT16 drw_y,
+ CARD16 drw_w, CARD16 drw_h
+){
+ XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
+ ScreenPtr pScreen;
+ RegionRec WinRegion;
+ RegionRec ClipRegion;
+ BoxRec WinBox;
+ int ret = Success;
+ Bool clippedAway = FALSE;
+
+ if (pDraw->type != DRAWABLE_WINDOW)
+ return BadAlloc;
+
+ if(!portPriv->pScrn->vtSema) return Success; /* Success ? */
+
+ pScreen = pDraw->pScreen;
+
+ WinBox.x1 = pDraw->x + drw_x;
+ WinBox.y1 = pDraw->y + drw_y;
+ WinBox.x2 = WinBox.x1 + drw_w;
+ WinBox.y2 = WinBox.y1 + drw_h;
+
+ REGION_INIT(pScreen, &WinRegion, &WinBox, 1);
+ REGION_INIT(pScreen, &ClipRegion, NullBox, 1);
+ REGION_INTERSECT(pScreen, &ClipRegion, &WinRegion, pGC->pCompositeClip);
+
+ if(portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) {
+ RegionRec VPReg;
+ BoxRec VPBox;
+
+ VPBox.x1 = portPriv->pScrn->frameX0;
+ VPBox.y1 = portPriv->pScrn->frameY0;
+ VPBox.x2 = portPriv->pScrn->frameX1;
+ VPBox.y2 = portPriv->pScrn->frameY1;
+
+ REGION_INIT(pScreen, &VPReg, &VPBox, 1);
+ REGION_INTERSECT(Screen, &ClipRegion, &ClipRegion, &VPReg);
+ REGION_UNINIT(pScreen, &VPReg);
+ }
+
+ if(portPriv->pDraw) {
+ xf86XVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv);
+ }
+
+ if(!REGION_NOTEMPTY(pScreen, &ClipRegion)) {
+ clippedAway = TRUE;
+ goto PUT_STILL_BAILOUT;
+ }
+
+ if(portPriv->AdaptorRec->flags & VIDEO_NO_CLIPPING) {
+ BoxPtr clipBox = REGION_RECTS(&ClipRegion);
+ if( (REGION_NUM_RECTS(&ClipRegion) != 1) ||
+ (clipBox->x1 != WinBox.x1) || (clipBox->x2 != WinBox.x2) ||
+ (clipBox->y1 != WinBox.y1) || (clipBox->y2 != WinBox.y2))
+ {
+ clippedAway = TRUE;
+ goto PUT_STILL_BAILOUT;
+ }
+ }
+
+ if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) {
+ REGION_SUBTRACT(pScreen, &ClipRegion, &WinRegion, &ClipRegion);
+ }
+
+ ret = (*portPriv->AdaptorRec->PutStill)(portPriv->pScrn,
+ vid_x, vid_y, WinBox.x1, WinBox.y1,
+ vid_w, vid_h, drw_w, drw_h,
+ &ClipRegion, portPriv->DevPriv.ptr);
+
+ if((ret == Success) &&
+ (portPriv->AdaptorRec->flags & VIDEO_OVERLAID_STILLS)) {
+
+ xf86XVEnlistPortInWindow((WindowPtr)pDraw, portPriv);
+ portPriv->isOn = XV_ON;
+ portPriv->pDraw = pDraw;
+ portPriv->drw_x = drw_x; portPriv->drw_y = drw_y;
+ portPriv->drw_w = drw_w; portPriv->drw_h = drw_h;
+ portPriv->type = 0; /* no mask means it's transient and should
+ not be reput once it's removed */
+ pPort->pDraw = pDraw; /* make sure we can get stop requests */
+ }
+
+PUT_STILL_BAILOUT:
+
+ if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
+ (*portPriv->AdaptorRec->StopVideo)(
+ portPriv->pScrn, portPriv->DevPriv.ptr, FALSE);
+ portPriv->isOn = XV_PENDING;
+ }
+
+ REGION_UNINIT(pScreen, &WinRegion);
+ REGION_UNINIT(pScreen, &ClipRegion);
+
+ return ret;
+}
+
+static int
+xf86XVGetVideo(
+ ClientPtr client,
+ DrawablePtr pDraw,
+ XvPortPtr pPort,
+ GCPtr pGC,
+ INT16 vid_x, INT16 vid_y,
+ CARD16 vid_w, CARD16 vid_h,
+ INT16 drw_x, INT16 drw_y,
+ CARD16 drw_w, CARD16 drw_h
+){
+ XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
+ int result;
+
+ /* No pixmaps... For now anyhow */
+ if(pDraw->type != DRAWABLE_WINDOW) {
+ pPort->pDraw = (DrawablePtr)NULL;
+ return BadAlloc;
+ }
+
+ /* If we are changing windows, unregister our port in the old window */
+ if(portPriv->pDraw && (portPriv->pDraw != pDraw))
+ xf86XVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv);
+
+ /* Register our port with the new window */
+ result = xf86XVEnlistPortInWindow((WindowPtr)pDraw, portPriv);
+ if(result != Success) return result;
+
+ portPriv->pDraw = pDraw;
+ portPriv->type = XvOutputMask;
+
+ /* save a copy of these parameters */
+ portPriv->vid_x = vid_x; portPriv->vid_y = vid_y;
+ portPriv->vid_w = vid_w; portPriv->vid_h = vid_h;
+ portPriv->drw_x = drw_x; portPriv->drw_y = drw_y;
+ portPriv->drw_w = drw_w; portPriv->drw_h = drw_h;
+
+ /* make sure we have the most recent copy of the clientClip */
+ xf86XVCopyClip(portPriv, pGC);
+
+ /* To indicate to the DI layer that we were successful */
+ pPort->pDraw = pDraw;
+
+ if(!portPriv->pScrn->vtSema) return Success; /* Success ? */
+
+ return(xf86XVRegetVideo(portPriv));
+}
+
+static int
+xf86XVGetStill(
+ ClientPtr client,
+ DrawablePtr pDraw,
+ XvPortPtr pPort,
+ GCPtr pGC,
+ INT16 vid_x, INT16 vid_y,
+ CARD16 vid_w, CARD16 vid_h,
+ INT16 drw_x, INT16 drw_y,
+ CARD16 drw_w, CARD16 drw_h
+){
+ XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
+ ScreenPtr pScreen;
+ RegionRec WinRegion;
+ RegionRec ClipRegion;
+ BoxRec WinBox;
+ int ret = Success;
+ Bool clippedAway = FALSE;
+
+ if (pDraw->type != DRAWABLE_WINDOW)
+ return BadAlloc;
+
+ if(!portPriv->pScrn->vtSema) return Success; /* Success ? */
+
+ pScreen = pDraw->pScreen;
+
+ WinBox.x1 = pDraw->x + drw_x;
+ WinBox.y1 = pDraw->y + drw_y;
+ WinBox.x2 = WinBox.x1 + drw_w;
+ WinBox.y2 = WinBox.y1 + drw_h;
+
+ REGION_INIT(pScreen, &WinRegion, &WinBox, 1);
+ REGION_INIT(pScreen, &ClipRegion, NullBox, 1);
+ REGION_INTERSECT(pScreen, &ClipRegion, &WinRegion, pGC->pCompositeClip);
+
+ if(portPriv->pDraw) {
+ xf86XVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv);
+ }
+
+ if(!REGION_NOTEMPTY(pScreen, &ClipRegion)) {
+ clippedAway = TRUE;
+ goto GET_STILL_BAILOUT;
+ }
+
+ if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) {
+ REGION_SUBTRACT(pScreen, &ClipRegion, &WinRegion, &ClipRegion);
+ }
+
+ ret = (*portPriv->AdaptorRec->GetStill)(portPriv->pScrn,
+ vid_x, vid_y, WinBox.x1, WinBox.y1,
+ vid_w, vid_h, drw_w, drw_h,
+ &ClipRegion, portPriv->DevPriv.ptr);
+
+GET_STILL_BAILOUT:
+
+ if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
+ (*portPriv->AdaptorRec->StopVideo)(
+ portPriv->pScrn, portPriv->DevPriv.ptr, FALSE);
+ portPriv->isOn = XV_PENDING;
+ }
+
+ REGION_UNINIT(pScreen, &WinRegion);
+ REGION_UNINIT(pScreen, &ClipRegion);
+
+ return ret;
+}
+
+
+
+static int
+xf86XVStopVideo(
+ ClientPtr client,
+ XvPortPtr pPort,
+ DrawablePtr pDraw
+){
+ XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
+
+ if(pDraw->type != DRAWABLE_WINDOW)
+ return BadAlloc;
+
+ xf86XVRemovePortFromWindow((WindowPtr)pDraw, portPriv);
+
+ if(!portPriv->pScrn->vtSema) return Success; /* Success ? */
+
+ /* Must free resources. */
+
+ if(portPriv->isOn > XV_OFF) {
+ (*portPriv->AdaptorRec->StopVideo)(
+ portPriv->pScrn, portPriv->DevPriv.ptr, TRUE);
+ portPriv->isOn = XV_OFF;
+ }
+
+ return Success;
+}
+
+static int
+xf86XVSetPortAttribute(
+ ClientPtr client,
+ XvPortPtr pPort,
+ Atom attribute,
+ INT32 value
+){
+ XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
+
+ return((*portPriv->AdaptorRec->SetPortAttribute)(portPriv->pScrn,
+ attribute, value, portPriv->DevPriv.ptr));
+}
+
+
+static int
+xf86XVGetPortAttribute(
+ ClientPtr client,
+ XvPortPtr pPort,
+ Atom attribute,
+ INT32 *p_value
+){
+ XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
+
+ return((*portPriv->AdaptorRec->GetPortAttribute)(portPriv->pScrn,
+ attribute, p_value, portPriv->DevPriv.ptr));
+}
+
+
+
+static int
+xf86XVQueryBestSize(
+ ClientPtr client,
+ XvPortPtr pPort,
+ CARD8 motion,
+ CARD16 vid_w, CARD16 vid_h,
+ CARD16 drw_w, CARD16 drw_h,
+ unsigned int *p_w, unsigned int *p_h
+){
+ XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
+
+ (*portPriv->AdaptorRec->QueryBestSize)(portPriv->pScrn,
+ (Bool)motion, vid_w, vid_h, drw_w, drw_h,
+ p_w, p_h, portPriv->DevPriv.ptr);
+
+ return Success;
+}
+
+
+static int
+xf86XVPutImage(
+ ClientPtr client,
+ DrawablePtr pDraw,
+ XvPortPtr pPort,
+ GCPtr pGC,
+ INT16 src_x, INT16 src_y,
+ CARD16 src_w, CARD16 src_h,
+ INT16 drw_x, INT16 drw_y,
+ CARD16 drw_w, CARD16 drw_h,
+ XvImagePtr format,
+ unsigned char* data,
+ Bool sync,
+ CARD16 width, CARD16 height
+){
+ XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
+ ScreenPtr pScreen;
+ RegionRec WinRegion;
+ RegionRec ClipRegion;
+ BoxRec WinBox;
+ int ret = Success;
+ Bool clippedAway = FALSE;
+
+ if (pDraw->type != DRAWABLE_WINDOW)
+ return BadAlloc;
+
+ if(!portPriv->pScrn->vtSema) return Success; /* Success ? */
+
+ pScreen = pDraw->pScreen;
+
+ WinBox.x1 = pDraw->x + drw_x;
+ WinBox.y1 = pDraw->y + drw_y;
+ WinBox.x2 = WinBox.x1 + drw_w;
+ WinBox.y2 = WinBox.y1 + drw_h;
+
+ REGION_INIT(pScreen, &WinRegion, &WinBox, 1);
+ REGION_INIT(pScreen, &ClipRegion, NullBox, 1);
+ REGION_INTERSECT(pScreen, &ClipRegion, &WinRegion, pGC->pCompositeClip);
+
+ if(portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) {
+ RegionRec VPReg;
+ BoxRec VPBox;
+
+ VPBox.x1 = portPriv->pScrn->frameX0;
+ VPBox.y1 = portPriv->pScrn->frameY0;
+ VPBox.x2 = portPriv->pScrn->frameX1 + 1;
+ VPBox.y2 = portPriv->pScrn->frameY1 + 1;
+
+ REGION_INIT(pScreen, &VPReg, &VPBox, 1);
+ REGION_INTERSECT(Screen, &ClipRegion, &ClipRegion, &VPReg);
+ REGION_UNINIT(pScreen, &VPReg);
+ }
+
+ if(portPriv->pDraw) {
+ xf86XVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv);
+ }
+
+ if(!REGION_NOTEMPTY(pScreen, &ClipRegion)) {
+ clippedAway = TRUE;
+ goto PUT_IMAGE_BAILOUT;
+ }
+
+ if(portPriv->AdaptorRec->flags & VIDEO_NO_CLIPPING) {
+ BoxPtr clipBox = REGION_RECTS(&ClipRegion);
+ if( (REGION_NUM_RECTS(&ClipRegion) != 1) ||
+ (clipBox->x1 != WinBox.x1) || (clipBox->x2 != WinBox.x2) ||
+ (clipBox->y1 != WinBox.y1) || (clipBox->y2 != WinBox.y2))
+ {
+ clippedAway = TRUE;
+ goto PUT_IMAGE_BAILOUT;
+ }
+ }
+
+ if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) {
+ REGION_SUBTRACT(pScreen, &ClipRegion, &WinRegion, &ClipRegion);
+ }
+
+ ret = (*portPriv->AdaptorRec->PutImage)(portPriv->pScrn,
+ src_x, src_y, WinBox.x1, WinBox.y1,
+ src_w, src_h, drw_w, drw_h, format->id, data, width, height,
+ sync, &ClipRegion, portPriv->DevPriv.ptr);
+
+ if((ret == Success) &&
+ (portPriv->AdaptorRec->flags & VIDEO_OVERLAID_IMAGES)) {
+
+ xf86XVEnlistPortInWindow((WindowPtr)pDraw, portPriv);
+ portPriv->isOn = XV_ON;
+ portPriv->pDraw = pDraw;
+ portPriv->drw_x = drw_x; portPriv->drw_y = drw_y;
+ portPriv->drw_w = drw_w; portPriv->drw_h = drw_h;
+ portPriv->type = 0; /* no mask means it's transient and should
+ not be reput once it's removed */
+ pPort->pDraw = pDraw; /* make sure we can get stop requests */
+ }
+
+PUT_IMAGE_BAILOUT:
+
+ if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
+ (*portPriv->AdaptorRec->StopVideo)(
+ portPriv->pScrn, portPriv->DevPriv.ptr, FALSE);
+ portPriv->isOn = XV_PENDING;
+ }
+
+ REGION_UNINIT(pScreen, &WinRegion);
+ REGION_UNINIT(pScreen, &ClipRegion);
+
+ return ret;
+}
+
+
+static int
+xf86XVQueryImageAttributes(
+ ClientPtr client,
+ XvPortPtr pPort,
+ XvImagePtr format,
+ CARD16 *width,
+ CARD16 *height,
+ int *pitches,
+ int *offsets
+){
+ XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
+
+ return (*portPriv->AdaptorRec->QueryImageAttributes)(portPriv->pScrn,
+ format->id, width, height, pitches, offsets);
+}
+
+void
+xf86XVFillKeyHelper (ScreenPtr pScreen, CARD32 key, RegionPtr clipboxes)
+{
+ XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen);
+ DrawablePtr root = &WindowTable[pScreen->myNum]->drawable;
+ XID pval[2];
+ BoxPtr pbox = REGION_RECTS(clipboxes);
+ int i, nbox = REGION_NUM_RECTS(clipboxes);
+ xRectangle *rects;
+
+ if(!xf86Screens[pScreen->myNum]->vtSema) return;
+
+ if(!ScreenPriv->videoGC) {
+ int status;
+ pval[0] = key;
+ pval[1] = IncludeInferiors;
+ ScreenPriv->videoGC = CreateGC(root, GCForeground | GCSubwindowMode,
+ pval, &status);
+ if(!ScreenPriv->videoGC) return;
+ ValidateGC(root, ScreenPriv->videoGC);
+ } else if (key != ScreenPriv->videoGC->fgPixel){
+ pval[0] = key;
+ ChangeGC(ScreenPriv->videoGC, GCForeground, pval);
+ ValidateGC(root, ScreenPriv->videoGC);
+ }
+
+ rects = ALLOCATE_LOCAL(nbox * sizeof(xRectangle));
+
+ for(i = 0; i < nbox; i++, pbox++) {
+ rects[i].x = pbox->x1;
+ rects[i].y = pbox->y1;
+ rects[i].width = pbox->x2 - pbox->x1;
+ rects[i].height = pbox->y2 - pbox->y1;
+ }
+
+ (*ScreenPriv->videoGC->ops->PolyFillRect)(
+ root, ScreenPriv->videoGC, nbox, rects);
+
+ DEALLOCATE_LOCAL(rects);
+}
+
+/* xf86XVClipVideoHelper -
+
+ Takes the dst box in standard X BoxRec form (top and left
+ edges inclusive, bottom and right exclusive). The new dst
+ box is returned. The source boundaries are given (x1, y1
+ inclusive, x2, y2 exclusive) and returned are the new source
+ boundaries in 16.16 fixed point.
+*/
+
+#define DummyScreen screenInfo.screens[0]
+
+Bool
+xf86XVClipVideoHelper(
+ BoxPtr dst,
+ INT32 *xa,
+ INT32 *xb,
+ INT32 *ya,
+ INT32 *yb,
+ RegionPtr reg,
+ INT32 width,
+ INT32 height
+){
+ INT32 vscale, hscale, delta;
+ BoxPtr extents = REGION_EXTENTS(DummyScreen, reg);
+ int diff;
+
+ hscale = ((*xb - *xa) << 16) / (dst->x2 - dst->x1);
+ vscale = ((*yb - *ya) << 16) / (dst->y2 - dst->y1);
+
+ *xa <<= 16; *xb <<= 16;
+ *ya <<= 16; *yb <<= 16;
+
+ diff = extents->x1 - dst->x1;
+ if(diff > 0) {
+ dst->x1 = extents->x1;
+ *xa += diff * hscale;
+ }
+ diff = dst->x2 - extents->x2;
+ if(diff > 0) {
+ dst->x2 = extents->x2;
+ *xb -= diff * hscale;
+ }
+ diff = extents->y1 - dst->y1;
+ if(diff > 0) {
+ dst->y1 = extents->y1;
+ *ya += diff * vscale;
+ }
+ diff = dst->y2 - extents->y2;
+ if(diff > 0) {
+ dst->y2 = extents->y2;
+ *yb -= diff * vscale;
+ }
+
+ if(*xa < 0) {
+ diff = (- *xa + hscale - 1)/ hscale;
+ dst->x1 += diff;
+ *xa += diff * hscale;
+ }
+ delta = *xb - (width << 16);
+ if(delta > 0) {
+ diff = (delta + hscale - 1)/ hscale;
+ dst->x2 -= diff;
+ *xb -= diff * hscale;
+ }
+ if(*xa >= *xb) return FALSE;
+
+ if(*ya < 0) {
+ diff = (- *ya + vscale - 1)/ vscale;
+ dst->y1 += diff;
+ *ya += diff * vscale;
+ }
+ delta = *yb - (height << 16);
+ if(delta > 0) {
+ diff = (delta + vscale - 1)/ vscale;
+ dst->y2 -= diff;
+ *yb -= diff * vscale;
+ }
+ if(*ya >= *yb) return FALSE;
+
+ if((dst->x1 != extents->x1) || (dst->x2 != extents->x2) ||
+ (dst->y1 != extents->y1) || (dst->y2 != extents->y2))
+ {
+ RegionRec clipReg;
+ REGION_INIT(DummyScreen, &clipReg, dst, 1);
+ REGION_INTERSECT(DummyScreen, reg, reg, &clipReg);
+ REGION_UNINIT(DummyScreen, &clipReg);
+ }
+ return TRUE;
+}
+
+
+/**************** Offscreen surface stuff *******************/
+
+typedef struct {
+ XF86OffscreenImagePtr images;
+ int num;
+} OffscreenImageRec;
+
+static OffscreenImageRec OffscreenImages[MAXSCREENS];
+static Bool offscreenInited = FALSE;
+
+Bool
+xf86XVRegisterOffscreenImages(
+ ScreenPtr pScreen,
+ XF86OffscreenImagePtr images,
+ int num
+){
+ if(!offscreenInited) {
+ bzero(OffscreenImages, sizeof(OffscreenImages[MAXSCREENS]));
+ offscreenInited = TRUE;
+ }
+
+ OffscreenImages[pScreen->myNum].num = num;
+ OffscreenImages[pScreen->myNum].images = images;
+
+ return TRUE;
+}
+
+XF86OffscreenImagePtr
+xf86XVQueryOffscreenImages(
+ ScreenPtr pScreen,
+ int *num
+){
+ if(!offscreenInited) {
+ *num = 0;
+ return NULL;
+ }
+
+ *num = OffscreenImages[pScreen->myNum].num;
+ return OffscreenImages[pScreen->myNum].images;
+}
diff --git a/hw/xfree86/common/xf86xv.h b/hw/xfree86/common/xf86xv.h
new file mode 100644
index 000000000..9fd6b4edf
--- /dev/null
+++ b/hw/xfree86/common/xf86xv.h
@@ -0,0 +1,272 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86xv.h,v 1.23 2002/11/09 01:18:33 keithp Exp $ */
+
+#ifndef _XF86XV_H_
+#define _XF86XV_H_
+
+#include "xvdix.h"
+#include "xf86str.h"
+
+#define VIDEO_NO_CLIPPING 0x00000001
+#define VIDEO_INVERT_CLIPLIST 0x00000002
+#define VIDEO_OVERLAID_IMAGES 0x00000004
+#define VIDEO_OVERLAID_STILLS 0x00000008
+#define VIDEO_CLIP_TO_VIEWPORT 0x00000010
+
+typedef struct {
+ int id;
+ int type;
+ int byte_order;
+ unsigned char guid[16];
+ int bits_per_pixel;
+ int format;
+ int num_planes;
+
+ /* for RGB formats only */
+ int depth;
+ unsigned int red_mask;
+ unsigned int green_mask;
+ unsigned int blue_mask;
+
+ /* for YUV formats only */
+ unsigned int y_sample_bits;
+ unsigned int u_sample_bits;
+ unsigned int v_sample_bits;
+ unsigned int horz_y_period;
+ unsigned int horz_u_period;
+ unsigned int horz_v_period;
+ unsigned int vert_y_period;
+ unsigned int vert_u_period;
+ unsigned int vert_v_period;
+ char component_order[32];
+ int scanline_order;
+} XF86ImageRec, *XF86ImagePtr;
+
+
+typedef struct {
+ ScrnInfoPtr pScrn;
+ int id;
+ unsigned short width, height;
+ int *pitches; /* bytes */
+ int *offsets; /* in bytes from start of framebuffer */
+ DevUnion devPrivate;
+} XF86SurfaceRec, *XF86SurfacePtr;
+
+
+typedef int (* PutVideoFuncPtr)( ScrnInfoPtr pScrn,
+ short vid_x, short vid_y, short drw_x, short drw_y,
+ short vid_w, short vid_h, short drw_w, short drw_h,
+ RegionPtr clipBoxes, pointer data );
+typedef int (* PutStillFuncPtr)( ScrnInfoPtr pScrn,
+ short vid_x, short vid_y, short drw_x, short drw_y,
+ short vid_w, short vid_h, short drw_w, short drw_h,
+ RegionPtr clipBoxes, pointer data );
+typedef int (* GetVideoFuncPtr)( ScrnInfoPtr pScrn,
+ short vid_x, short vid_y, short drw_x, short drw_y,
+ short vid_w, short vid_h, short drw_w, short drw_h,
+ RegionPtr clipBoxes, pointer data );
+typedef int (* GetStillFuncPtr)( ScrnInfoPtr pScrn,
+ short vid_x, short vid_y, short drw_x, short drw_y,
+ short vid_w, short vid_h, short drw_w, short drw_h,
+ RegionPtr clipBoxes, pointer data );
+typedef void (* StopVideoFuncPtr)(ScrnInfoPtr pScrn, pointer data, Bool Exit);
+typedef int (* SetPortAttributeFuncPtr)(ScrnInfoPtr pScrn, Atom attribute,
+ INT32 value, pointer data);
+typedef int (* GetPortAttributeFuncPtr)(ScrnInfoPtr pScrn, Atom attribute,
+ INT32 *value, pointer data);
+typedef void (* QueryBestSizeFuncPtr)(ScrnInfoPtr pScrn, Bool motion,
+ short vid_w, short vid_h, short drw_w, short drw_h,
+ unsigned int *p_w, unsigned int *p_h, pointer data);
+typedef int (* PutImageFuncPtr)( ScrnInfoPtr pScrn,
+ short src_x, short src_y, short drw_x, short drw_y,
+ short src_w, short src_h, short drw_w, short drw_h,
+ int image, unsigned char* buf, short width, short height, Bool Sync,
+ RegionPtr clipBoxes, pointer data );
+typedef int (* ReputImageFuncPtr)( ScrnInfoPtr pScrn, short drw_x, short drw_y,
+ RegionPtr clipBoxes, pointer data );
+typedef int (*QueryImageAttributesFuncPtr)(ScrnInfoPtr pScrn,
+ int image, unsigned short *width, unsigned short *height,
+ int *pitches, int *offsets);
+
+typedef enum {
+ XV_OFF,
+ XV_PENDING,
+ XV_ON
+} XvStatus;
+
+/*** this is what the driver needs to fill out ***/
+
+typedef struct {
+ int id;
+ char *name;
+ unsigned short width, height;
+ XvRationalRec rate;
+} XF86VideoEncodingRec, *XF86VideoEncodingPtr;
+
+typedef struct {
+ char depth;
+ short class;
+} XF86VideoFormatRec, *XF86VideoFormatPtr;
+
+typedef struct {
+ int flags;
+ int min_value;
+ int max_value;
+ char *name;
+} XF86AttributeRec, *XF86AttributePtr;
+
+typedef struct {
+ unsigned int type;
+ int flags;
+ char *name;
+ int nEncodings;
+ XF86VideoEncodingPtr pEncodings;
+ int nFormats;
+ XF86VideoFormatPtr pFormats;
+ int nPorts;
+ DevUnion *pPortPrivates;
+ int nAttributes;
+ XF86AttributePtr pAttributes;
+ int nImages;
+ XF86ImagePtr pImages;
+ PutVideoFuncPtr PutVideo;
+ PutStillFuncPtr PutStill;
+ GetVideoFuncPtr GetVideo;
+ GetStillFuncPtr GetStill;
+ StopVideoFuncPtr StopVideo;
+ SetPortAttributeFuncPtr SetPortAttribute;
+ GetPortAttributeFuncPtr GetPortAttribute;
+ QueryBestSizeFuncPtr QueryBestSize;
+ PutImageFuncPtr PutImage;
+ ReputImageFuncPtr ReputImage;
+ QueryImageAttributesFuncPtr QueryImageAttributes;
+} XF86VideoAdaptorRec, *XF86VideoAdaptorPtr;
+
+typedef struct {
+ XF86ImagePtr image;
+ int flags;
+ int (*alloc_surface)(ScrnInfoPtr pScrn,
+ int id,
+ unsigned short width,
+ unsigned short height,
+ XF86SurfacePtr surface);
+ int (*free_surface)(XF86SurfacePtr surface);
+ int (*display) (XF86SurfacePtr surface,
+ short vid_x, short vid_y,
+ short drw_x, short drw_y,
+ short vid_w, short vid_h,
+ short drw_w, short drw_h,
+ RegionPtr clipBoxes);
+ int (*stop) (XF86SurfacePtr surface);
+ int (*getAttribute) (ScrnInfoPtr pScrn, Atom attr, INT32 *value);
+ int (*setAttribute) (ScrnInfoPtr pScrn, Atom attr, INT32 value);
+ int max_width;
+ int max_height;
+ int num_attributes;
+ XF86AttributePtr attributes;
+} XF86OffscreenImageRec, *XF86OffscreenImagePtr;
+
+Bool
+xf86XVScreenInit(
+ ScreenPtr pScreen,
+ XF86VideoAdaptorPtr *Adaptors,
+ int num
+);
+
+typedef int (* xf86XVInitGenericAdaptorPtr)(ScrnInfoPtr pScrn,
+ XF86VideoAdaptorPtr **Adaptors);
+
+int
+xf86XVRegisterGenericAdaptorDriver(
+ xf86XVInitGenericAdaptorPtr InitFunc
+);
+
+int
+xf86XVListGenericAdaptors(
+ ScrnInfoPtr pScrn,
+ XF86VideoAdaptorPtr **Adaptors
+);
+
+Bool
+xf86XVRegisterOffscreenImages(
+ ScreenPtr pScreen,
+ XF86OffscreenImagePtr images,
+ int num
+);
+
+XF86OffscreenImagePtr
+xf86XVQueryOffscreenImages(
+ ScreenPtr pScreen,
+ int *num
+);
+
+XF86VideoAdaptorPtr xf86XVAllocateVideoAdaptorRec(ScrnInfoPtr pScrn);
+
+void xf86XVFreeVideoAdaptorRec(XF86VideoAdaptorPtr ptr);
+
+void
+xf86XVFillKeyHelper (ScreenPtr pScreen, CARD32 key, RegionPtr clipboxes);
+
+Bool
+xf86XVClipVideoHelper(
+ BoxPtr dst,
+ INT32 *xa,
+ INT32 *xb,
+ INT32 *ya,
+ INT32 *yb,
+ RegionPtr reg,
+ INT32 width,
+ INT32 height
+);
+
+/*** These are DDX layer privates ***/
+
+extern int XF86XvScreenIndex;
+
+typedef struct {
+ DestroyWindowProcPtr DestroyWindow;
+ ClipNotifyProcPtr ClipNotify;
+ WindowExposuresProcPtr WindowExposures;
+ void (*AdjustFrame)(int, int, int, int);
+ Bool (*EnterVT)(int, int);
+ void (*LeaveVT)(int, int);
+ GCPtr videoGC;
+} XF86XVScreenRec, *XF86XVScreenPtr;
+
+typedef struct {
+ int flags;
+ PutVideoFuncPtr PutVideo;
+ PutStillFuncPtr PutStill;
+ GetVideoFuncPtr GetVideo;
+ GetStillFuncPtr GetStill;
+ StopVideoFuncPtr StopVideo;
+ SetPortAttributeFuncPtr SetPortAttribute;
+ GetPortAttributeFuncPtr GetPortAttribute;
+ QueryBestSizeFuncPtr QueryBestSize;
+ PutImageFuncPtr PutImage;
+ ReputImageFuncPtr ReputImage;
+ QueryImageAttributesFuncPtr QueryImageAttributes;
+} XvAdaptorRecPrivate, *XvAdaptorRecPrivatePtr;
+
+typedef struct {
+ ScrnInfoPtr pScrn;
+ DrawablePtr pDraw;
+ unsigned char type;
+ unsigned int subWindowMode;
+ DDXPointRec clipOrg;
+ RegionPtr clientClip;
+ RegionPtr pCompositeClip;
+ Bool FreeCompositeClip;
+ XvAdaptorRecPrivatePtr AdaptorRec;
+ XvStatus isOn;
+ Bool moved;
+ int vid_x, vid_y, vid_w, vid_h;
+ int drw_x, drw_y, drw_w, drw_h;
+ DevUnion DevPriv;
+} XvPortRecPrivate, *XvPortRecPrivatePtr;
+
+typedef struct _XF86XVWindowRec{
+ XvPortRecPrivatePtr PortRec;
+ struct _XF86XVWindowRec *next;
+} XF86XVWindowRec, *XF86XVWindowPtr;
+
+#endif /* _XF86XV_H_ */
diff --git a/hw/xfree86/common/xf86xvmc.c b/hw/xfree86/common/xf86xvmc.c
new file mode 100644
index 000000000..4559359ec
--- /dev/null
+++ b/hw/xfree86/common/xf86xvmc.c
@@ -0,0 +1,201 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86xvmc.c,v 1.3 2001/04/01 14:00:08 tsi Exp $ */
+
+#include "misc.h"
+#include "xf86.h"
+#include "xf86_OSproc.h"
+
+#include "X.h"
+#include "Xproto.h"
+#include "scrnintstr.h"
+#include "resource.h"
+#include "dixstruct.h"
+
+#ifdef XFree86LOADER
+#include "xvmodproc.h"
+#endif
+
+#include "xf86xvmc.h"
+
+#ifdef XFree86LOADER
+int (*XvMCScreenInitProc)(ScreenPtr, int, XvMCAdaptorPtr) = NULL;
+#else
+int (*XvMCScreenInitProc)(ScreenPtr, int, XvMCAdaptorPtr) = XvMCScreenInit;
+#endif
+
+
+typedef struct {
+ CloseScreenProcPtr CloseScreen;
+ int num_adaptors;
+ XF86MCAdaptorPtr *adaptors;
+ XvMCAdaptorPtr dixinfo;
+} xf86XvMCScreenRec, *xf86XvMCScreenPtr;
+
+static unsigned long XF86XvMCGeneration = 0;
+static int XF86XvMCScreenIndex = -1;
+
+#define XF86XVMC_GET_PRIVATE(pScreen) \
+ (xf86XvMCScreenPtr)((pScreen)->devPrivates[XF86XvMCScreenIndex].ptr)
+
+
+static int
+xf86XvMCCreateContext (
+ XvPortPtr pPort,
+ XvMCContextPtr pContext,
+ int *num_priv,
+ CARD32 **priv
+)
+{
+ xf86XvMCScreenPtr pScreenPriv = XF86XVMC_GET_PRIVATE(pContext->pScreen);
+ ScrnInfoPtr pScrn = xf86Screens[pContext->pScreen->myNum];
+
+ pContext->port_priv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
+
+ return (*pScreenPriv->adaptors[pContext->adapt_num]->CreateContext)(
+ pScrn, pContext, num_priv, priv);
+}
+
+static void
+xf86XvMCDestroyContext ( XvMCContextPtr pContext)
+{
+ xf86XvMCScreenPtr pScreenPriv = XF86XVMC_GET_PRIVATE(pContext->pScreen);
+ ScrnInfoPtr pScrn = xf86Screens[pContext->pScreen->myNum];
+
+ (*pScreenPriv->adaptors[pContext->adapt_num]->DestroyContext)(
+ pScrn, pContext);
+}
+
+static int
+xf86XvMCCreateSurface (
+ XvMCSurfacePtr pSurface,
+ int *num_priv,
+ CARD32 **priv
+)
+{
+ XvMCContextPtr pContext = pSurface->context;
+ xf86XvMCScreenPtr pScreenPriv = XF86XVMC_GET_PRIVATE(pContext->pScreen);
+ ScrnInfoPtr pScrn = xf86Screens[pContext->pScreen->myNum];
+
+ return (*pScreenPriv->adaptors[pContext->adapt_num]->CreateSurface)(
+ pScrn, pSurface, num_priv, priv);
+}
+
+static void
+xf86XvMCDestroySurface (XvMCSurfacePtr pSurface)
+{
+ XvMCContextPtr pContext = pSurface->context;
+ xf86XvMCScreenPtr pScreenPriv = XF86XVMC_GET_PRIVATE(pContext->pScreen);
+ ScrnInfoPtr pScrn = xf86Screens[pContext->pScreen->myNum];
+
+ (*pScreenPriv->adaptors[pContext->adapt_num]->DestroySurface)(
+ pScrn, pSurface);
+}
+
+static int
+xf86XvMCCreateSubpicture (
+ XvMCSubpicturePtr pSubpicture,
+ int *num_priv,
+ CARD32 **priv
+)
+{
+ XvMCContextPtr pContext = pSubpicture->context;
+ xf86XvMCScreenPtr pScreenPriv = XF86XVMC_GET_PRIVATE(pContext->pScreen);
+ ScrnInfoPtr pScrn = xf86Screens[pContext->pScreen->myNum];
+
+ return (*pScreenPriv->adaptors[pContext->adapt_num]->CreateSubpicture)(
+ pScrn, pSubpicture, num_priv, priv);
+}
+
+static void
+xf86XvMCDestroySubpicture (XvMCSubpicturePtr pSubpicture)
+{
+ XvMCContextPtr pContext = pSubpicture->context;
+ xf86XvMCScreenPtr pScreenPriv = XF86XVMC_GET_PRIVATE(pContext->pScreen);
+ ScrnInfoPtr pScrn = xf86Screens[pContext->pScreen->myNum];
+
+ (*pScreenPriv->adaptors[pContext->adapt_num]->DestroySubpicture)(
+ pScrn, pSubpicture);
+}
+
+
+static Bool
+xf86XvMCCloseScreen (int i, ScreenPtr pScreen)
+{
+ xf86XvMCScreenPtr pScreenPriv = XF86XVMC_GET_PRIVATE(pScreen);
+
+ pScreen->CloseScreen = pScreenPriv->CloseScreen;
+
+ xfree(pScreenPriv->dixinfo);
+ xfree(pScreenPriv);
+
+ return (*pScreen->CloseScreen)(i, pScreen);
+}
+
+Bool xf86XvMCScreenInit(
+ ScreenPtr pScreen,
+ int num_adaptors,
+ XF86MCAdaptorPtr *adaptors
+)
+{
+ XvMCAdaptorPtr pAdapt;
+ xf86XvMCScreenPtr pScreenPriv;
+ XvScreenPtr pxvs =
+ (XvScreenPtr)(pScreen->devPrivates[XF86XvScreenIndex].ptr);
+
+ int i, j;
+
+ if(!XvMCScreenInitProc) return FALSE;
+
+ if(XF86XvMCGeneration != serverGeneration) {
+ if((XF86XvMCScreenIndex = AllocateScreenPrivateIndex()) < 0)
+ return FALSE;
+ XF86XvMCGeneration = serverGeneration;
+ }
+
+ if(!(pAdapt = xalloc(sizeof(XvMCAdaptorRec) * num_adaptors)))
+ return FALSE;
+
+ if(!(pScreenPriv = xalloc(sizeof(xf86XvMCScreenRec)))) {
+ xfree(pAdapt);
+ return FALSE;
+ }
+
+ pScreen->devPrivates[XF86XvMCScreenIndex].ptr = (pointer)pScreenPriv;
+
+ pScreenPriv->CloseScreen = pScreen->CloseScreen;
+ pScreen->CloseScreen = xf86XvMCCloseScreen;
+
+ pScreenPriv->num_adaptors = num_adaptors;
+ pScreenPriv->adaptors = adaptors;
+ pScreenPriv->dixinfo = pAdapt;
+
+ for(i = 0; i < num_adaptors; i++) {
+ pAdapt[i].xv_adaptor = NULL;
+ for(j = 0; j < pxvs->nAdaptors; j++) {
+ if(!strcmp((*adaptors)->name, pxvs->pAdaptors[j].name)) {
+ pAdapt[i].xv_adaptor = &(pxvs->pAdaptors[j]);
+ break;
+ }
+ }
+ if(!pAdapt[i].xv_adaptor) {
+ /* no adaptor by that name */
+ xfree(pAdapt);
+ return FALSE;
+ }
+ pAdapt[i].num_surfaces = (*adaptors)->num_surfaces;
+ pAdapt[i].surfaces = (XvMCSurfaceInfoPtr*)((*adaptors)->surfaces);
+ pAdapt[i].num_subpictures = (*adaptors)->num_subpictures;
+ pAdapt[i].subpictures = (XvImagePtr*)((*adaptors)->subpictures);
+ pAdapt[i].CreateContext = xf86XvMCCreateContext;
+ pAdapt[i].DestroyContext = xf86XvMCDestroyContext;
+ pAdapt[i].CreateSurface = xf86XvMCCreateSurface;
+ pAdapt[i].DestroySurface = xf86XvMCDestroySurface;
+ pAdapt[i].CreateSubpicture = xf86XvMCCreateSubpicture;
+ pAdapt[i].DestroySubpicture = xf86XvMCDestroySubpicture;
+ adaptors++;
+ }
+
+ if(Success != (*XvMCScreenInitProc)(pScreen, num_adaptors, pAdapt))
+ return FALSE;
+
+ return TRUE;
+}
diff --git a/hw/xfree86/common/xf86xvmc.h b/hw/xfree86/common/xf86xvmc.h
new file mode 100644
index 000000000..074edbebe
--- /dev/null
+++ b/hw/xfree86/common/xf86xvmc.h
@@ -0,0 +1,134 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86xvmc.h,v 1.5 2001/11/14 21:54:39 mvojkovi Exp $ */
+
+#ifndef _XF86XVMC_H
+#define _XF86XVMC_H
+
+#include "xvmcext.h"
+#include "xf86xv.h"
+
+typedef struct {
+ int num_xvimages;
+ int *xvimage_ids; /* reference the subpictures in the XF86MCAdaptorRec */
+} XF86MCImageIDList;
+
+typedef struct {
+ int surface_type_id; /* Driver generated. Must be unique on the port */
+ int chroma_format;
+ int color_description; /* no longer used */
+ unsigned short max_width;
+ unsigned short max_height;
+ unsigned short subpicture_max_width;
+ unsigned short subpicture_max_height;
+ int mc_type;
+ int flags;
+ XF86MCImageIDList *compatible_subpictures; /* can be null, if none */
+} XF86MCSurfaceInfoRec, *XF86MCSurfaceInfoPtr;
+
+
+/*
+ xf86XvMCCreateContextProc
+
+ DIX will fill everything out in the context except the driver_priv.
+ The port_priv holds the private data specified for the port when
+ Xv was initialized by the driver.
+ The driver may store whatever it wants in driver_priv and edit
+ the width, height and flags. If the driver wants to return something
+ to the client it can allocate space in priv and specify the number
+ of 32 bit words in num_priv. This must be dynamically allocated
+ space because DIX will free it after it passes it to the client.
+*/
+
+
+typedef int (*xf86XvMCCreateContextProcPtr) (
+ ScrnInfoPtr pScrn,
+ XvMCContextPtr context,
+ int *num_priv,
+ CARD32 **priv
+);
+
+typedef void (*xf86XvMCDestroyContextProcPtr) (
+ ScrnInfoPtr pScrn,
+ XvMCContextPtr context
+);
+
+/*
+ xf86XvMCCreateSurfaceProc
+
+ DIX will fill everything out in the surface except the driver_priv.
+ The driver may store whatever it wants in driver_priv. The driver
+ may pass data back to the client in the same manner as the
+ xf86XvMCCreateContextProc.
+*/
+
+
+typedef int (*xf86XvMCCreateSurfaceProcPtr) (
+ ScrnInfoPtr pScrn,
+ XvMCSurfacePtr surface,
+ int *num_priv,
+ CARD32 **priv
+);
+
+typedef void (*xf86XvMCDestroySurfaceProcPtr) (
+ ScrnInfoPtr pScrn,
+ XvMCSurfacePtr surface
+);
+
+/*
+ xf86XvMCCreateSubpictureProc
+
+ DIX will fill everything out in the subpicture except the driver_priv,
+ num_palette_entries, entry_bytes and component_order. The driver may
+ store whatever it wants in driver_priv and edit the width and height.
+ If it is a paletted subpicture the driver needs to fill out the
+ num_palette_entries, entry_bytes and component_order. These are
+ not communicated to the client until the time the surface is
+ created.
+
+ The driver may pass data back to the client in the same manner as the
+ xf86XvMCCreateContextProc.
+*/
+
+
+typedef int (*xf86XvMCCreateSubpictureProcPtr) (
+ ScrnInfoPtr pScrn,
+ XvMCSubpicturePtr subpicture,
+ int *num_priv,
+ CARD32 **priv
+);
+
+typedef void (*xf86XvMCDestroySubpictureProcPtr) (
+ ScrnInfoPtr pScrn,
+ XvMCSubpicturePtr subpicture
+);
+
+
+typedef struct {
+ char *name;
+ int num_surfaces;
+ XF86MCSurfaceInfoPtr *surfaces;
+ int num_subpictures;
+ XF86ImagePtr *subpictures;
+ xf86XvMCCreateContextProcPtr CreateContext;
+ xf86XvMCDestroyContextProcPtr DestroyContext;
+ xf86XvMCCreateSurfaceProcPtr CreateSurface;
+ xf86XvMCDestroySurfaceProcPtr DestroySurface;
+ xf86XvMCCreateSubpictureProcPtr CreateSubpicture;
+ xf86XvMCDestroySubpictureProcPtr DestroySubpicture;
+} XF86MCAdaptorRec, *XF86MCAdaptorPtr;
+
+/*
+ xf86XvMCScreenInit
+
+ Unlike Xv, the adaptor data is not copied from this structure.
+ This structure's data is used so it must stick around for the
+ life of the server. Note that it's an array of pointers not
+ an array of structures.
+*/
+
+Bool xf86XvMCScreenInit(
+ ScreenPtr pScreen,
+ int num_adaptors,
+ XF86MCAdaptorPtr *adaptors
+);
+
+#endif /* _XF86XVMC_H */
diff --git a/hw/xfree86/common/xisb.c b/hw/xfree86/common/xisb.c
new file mode 100644
index 000000000..4132c7abf
--- /dev/null
+++ b/hw/xfree86/common/xisb.c
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 1997 Metro Link Incorporated
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of the Metro Link shall not be
+ * used in advertising or otherwise to promote the sale, use or other dealings
+ * in this Software without prior written authorization from Metro Link.
+ *
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xisb.c,v 1.5 2000/11/06 19:24:07 dawes Exp $ */
+
+/*
+ X Input Serial Buffer routines for use in any XInput driver that accesses
+ a serial device.
+*/
+
+
+/*****************************************************************************
+ * Standard Headers
+ ****************************************************************************/
+
+#include <misc.h>
+#include <xf86.h>
+#include <xf86Version.h>
+#include <xf86_OSproc.h>
+#include <xf86_OSlib.h>
+#include <xf86Xinput.h>
+#include "xisb.h"
+
+/*****************************************************************************
+ * Local Headers
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Variables without includable headers
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Local Variables
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Function Definitions
+ ****************************************************************************/
+
+XISBuffer *
+XisbNew (int fd, xf86ssize_t size)
+{
+ XISBuffer *b;
+
+ b = xalloc (sizeof (XISBuffer));
+ if (!b)
+ return (NULL);
+ b->buf = xalloc ((sizeof (unsigned char) * size));
+ if (!b->buf)
+ {
+ xfree (b);
+ return (NULL);
+ }
+
+ b->fd = fd;
+ b->trace = 0;
+ b->block_duration = 0;
+ b->current = 1; /* force it to be past the end to trigger initial read */
+ b->end = 0;
+ b->buffer_size = size;
+ return (b);
+}
+
+void
+XisbFree (XISBuffer *b)
+{
+ xfree (b->buf);
+ xfree (b);
+}
+
+int
+XisbRead (XISBuffer *b)
+{
+ int ret;
+
+ if (b->current >= b->end)
+ {
+ if (b->block_duration >= 0)
+ {
+ if (xf86WaitForInput (b->fd, b->block_duration) < 1)
+ return (-1);
+ }
+ else
+ {
+ /*
+ * automatically clear it so if XisbRead is called in a loop
+ * the next call will make sure there is data with select and
+ * thus prevent a blocking read
+ */
+ b->block_duration = 0;
+ }
+
+ ret = xf86ReadSerial (b->fd, b->buf, b->buffer_size);
+ switch (ret)
+ {
+ case 0:
+ return (-1); /* timeout */
+ case -1:
+ return (-2); /* error */
+ default:
+ b->end = ret;
+ b->current = 0;
+ break;
+ }
+ }
+ if (b->trace)
+ ErrorF ("read 0x%02x (%c)\n", b->buf[b->current],
+ isprint(b->buf[b->current])?b->buf[b->current]:'.');
+
+ return (b->buf[b->current++]);
+}
+
+/* the only purpose of this function is to provide output tracing */
+xf86ssize_t
+XisbWrite (XISBuffer *b, unsigned char *msg, xf86ssize_t len)
+{
+ if (b->trace)
+ {
+ int i = 0;
+ for (i = 0; i < len; i++)
+ ErrorF ("\t\twrote 0x%02x (%c)\n", msg[i], msg[i]);
+ }
+ return (xf86WriteSerial (b->fd, msg, len));
+}
+
+/* turn tracing of this buffer on (1) or off (0) */
+void
+XisbTrace (XISBuffer *b, int trace)
+{
+ b->trace = trace;
+}
+
+/*
+ * specify a block_duration of -1 when you know the buffer's fd is ready to
+ * read. After a read, it is automatically set to 0 so that the next read
+ * will use check to select for data and prevent a block.
+ * It is the caller's responsibility to set the block_duration to -1 if it
+ * knows that there is data to read (because the main select loop triggered
+ * the read) and want's to avoid the unnecessary overhead of the select call
+ *
+ * a zero or positive block duration will cause the select to block for the
+ * give duration in usecs.
+ */
+
+void
+XisbBlockDuration (XISBuffer *b, int block_duration)
+{
+ b->block_duration = block_duration;
+}
diff --git a/hw/xfree86/common/xisb.h b/hw/xfree86/common/xisb.h
new file mode 100644
index 000000000..7b5e26a23
--- /dev/null
+++ b/hw/xfree86/common/xisb.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 1997 Metro Link Incorporated
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of the Metro Link shall not be
+ * used in advertising or otherwise to promote the sale, use or other dealings
+ * in this Software without prior written authorization from Metro Link.
+ *
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xisb.h,v 1.1 1998/12/05 14:40:10 dawes Exp $ */
+
+#ifndef _xisb_H_
+#define _xisb_H_
+
+/******************************************************************************
+ * Definitions
+ * structs, typedefs, #defines, enums
+ *****************************************************************************/
+
+typedef struct _XISBuffer
+{
+ int fd;
+ int trace;
+ int block_duration;
+ xf86ssize_t current; /* bytes read */
+ xf86ssize_t end;
+ xf86ssize_t buffer_size;
+ unsigned char *buf;
+} XISBuffer;
+
+/******************************************************************************
+ * Declarations
+ * variables: use xisb_LOC in front
+ * of globals.
+ * put locals in the .c file.
+ *****************************************************************************/
+XISBuffer * XisbNew (int fd, xf86ssize_t size);
+void XisbFree (XISBuffer *b);
+int XisbRead (XISBuffer *b);
+xf86ssize_t XisbWrite (XISBuffer *b, unsigned char *msg, xf86ssize_t len);
+void XisbTrace (XISBuffer *b, int trace);
+void XisbBlockDuration (XISBuffer *b, int block_duration);
+
+/*
+ * DO NOT PUT ANYTHING AFTER THIS ENDIF
+ */
+#endif