diff options
author | Aaron Plattner <aplattner@nvidia.com> | 2008-02-13 10:26:52 -0800 |
---|---|---|
committer | Aaron Plattner <aplattner@nvidia.com> | 2008-02-13 10:26:52 -0800 |
commit | 80e326c7dff56784314d3ae0087e914b23598a5a (patch) | |
tree | d21421183f147ca085e3956f458fb6692e3c3422 | |
parent | c1cb49fc2abcb44580f7544e2ac8f987da5205cc (diff) |
-rw-r--r-- | Makefile | 3 | ||||
-rw-r--r-- | XF86Config-parser/Flags.c | 24 | ||||
-rw-r--r-- | XF86Config-parser/Generate.c | 138 | ||||
-rw-r--r-- | XF86Config-parser/Read.c | 29 | ||||
-rw-r--r-- | XF86Config-parser/Scan.c | 31 | ||||
-rw-r--r-- | XF86Config-parser/xf86Parser.h | 7 | ||||
-rw-r--r-- | gen-manpage-opts.c | 58 | ||||
-rw-r--r-- | lscf.c | 138 | ||||
-rw-r--r-- | make_usable.c | 52 | ||||
-rw-r--r-- | multiple_screens.c | 153 | ||||
-rw-r--r-- | nvidia-xconfig.1.m4 | 2 | ||||
-rw-r--r-- | nvidia-xconfig.c | 110 | ||||
-rw-r--r-- | nvidia-xconfig.h | 95 | ||||
-rw-r--r-- | option_table.h | 35 | ||||
-rw-r--r-- | options.c | 6 | ||||
-rw-r--r-- | query_gpu_info.c | 232 | ||||
-rw-r--r-- | tree.c | 22 | ||||
-rw-r--r-- | util.c | 2 |
18 files changed, 1000 insertions, 137 deletions
@@ -120,7 +120,8 @@ SRC = util.c \ tree.c \ nvgetopt.c \ options.c \ - lscf.c + lscf.c \ + query_gpu_info.c ALL_SRC = $(SRC) $(STAMP_C) diff --git a/XF86Config-parser/Flags.c b/XF86Config-parser/Flags.c index 62eeb12..c296b8a 100644 --- a/XF86Config-parser/Flags.c +++ b/XF86Config-parser/Flags.c @@ -368,6 +368,30 @@ xconfigFindOptionValue (XConfigOptionPtr list, const char *name) return (NULL); } +/* + * this function searches the given option list for the named option. If + * found and the the value of the option is set to "1", "ON", "YES" or + * "TRUE", 1 is returned. Otherwise, 0 is returned. + */ + +int +xconfigFindOptionBoolean (XConfigOptionPtr list, const char *name) +{ + XConfigOptionPtr p = xconfigFindOption (list, name); + + if (p && p->val) + { + if ( strcasecmp(p->val, "1") == 0 || + strcasecmp(p->val, "ON") == 0 || + strcasecmp(p->val, "YES") == 0 || + strcasecmp(p->val, "TRUE") == 0 ) + { + return 1; + } + } + return 0; +} + XConfigOptionPtr xconfigOptionListCreate( const char **options, int count, int used ) { diff --git a/XF86Config-parser/Generate.c b/XF86Config-parser/Generate.c index 7561aa9..1c374cf 100644 --- a/XF86Config-parser/Generate.c +++ b/XF86Config-parser/Generate.c @@ -58,7 +58,6 @@ add_monitor(XConfigPtr config, int count); static XConfigDevicePtr add_device(XConfigPtr config, int bus, int slot, char *boardname, int count); -static XConfigDisplayPtr add_display(int depth); static void add_layout(GenerateOptions *gop, XConfigPtr config); static void add_inputref(XConfigPtr config, XConfigLayoutPtr layout, @@ -130,7 +129,8 @@ XConfigScreenPtr xconfigGenerateAddScreen(XConfigPtr config, screen->defaultdepth = 24; - screen->displays = add_display(screen->defaultdepth); + screen->displays = xconfigAddDisplay(screen->displays, + screen->defaultdepth); /* append to the end of the screen list */ @@ -199,6 +199,66 @@ static int is_file(const char *filename) } /* is_file() */ +/* + * find_libdir() - attempt to find the X server library path; this is + * either + * + * `pkg-config --variable=libdir xorg-server` + * + * or + * + * [X PROJECT ROOT]/lib + */ + +static char *find_libdir(GenerateOptions *gop) +{ + struct stat stat_buf; + FILE *stream = NULL; + char *s, *libdir = NULL; + + /* + * run the pkg-config command and read the output; if the output + * is a directory, then return that as the libdir + */ + + stream = popen("pkg-config --variable=libdir xorg-server", "r"); + + if (stream) { + char buf[256]; + + buf[0] = '\0'; + + while (1) { + if (fgets(buf, 255, stream) == NULL) break; + + if (buf[0] != '\0') { + + /* truncate any newline */ + + s = strchr(buf, '\n'); + if (s) *s = '\0'; + + if ((stat(buf, &stat_buf) == 0) && + (S_ISDIR(stat_buf.st_mode))) { + + libdir = xconfigStrdup(buf); + break; + } + } + } + + pclose(stream); + + if (libdir) return libdir; + } + + /* otherwise, just fallback to [X PROJECT ROOT]/lib */ + + return xconfigStrcat(gop->x_project_root, "/lib", NULL); + +} /* find_libdir() */ + + /* * add_files() - @@ -206,9 +266,13 @@ static int is_file(const char *filename) static void add_files(GenerateOptions *gop, XConfigPtr config) { + char *libdir = find_libdir(gop); + config->files = xconfigAlloc(sizeof(XConfigFilesRec)); - config->files->rgbpath = xconfigStrcat(gop->x_project_root, - "/lib/X11/rgb", NULL); + config->files->rgbpath = xconfigStrcat(libdir, "/X11/rgb", NULL); + + free(libdir); + } /* add_files() */ @@ -222,7 +286,7 @@ static void add_files(GenerateOptions *gop, XConfigPtr config) static void add_font_path(GenerateOptions *gop, XConfigPtr config) { int i, ret; - char *path, *p, *orig, *fonts_dir; + char *path, *p, *orig, *fonts_dir, *libdir; /* * The below font path has been constructed from various examples @@ -230,19 +294,22 @@ static void add_font_path(GenerateOptions *gop, XConfigPtr config) */ static const char *__font_paths[] = { - "ROOT/lib/X11/fonts/local/", - "ROOT/lib/X11/fonts/misc/:unscaled", - "ROOT/lib/X11/fonts/100dpi/:unscaled", - "ROOT/lib/X11/fonts/75dpi/:unscaled", - "ROOT/lib/X11/fonts/misc/", - "ROOT/lib/X11/fonts/Type1/", - "ROOT/lib/X11/fonts/CID/", - "ROOT/lib/X11/fonts/Speedo/", - "ROOT/lib/X11/fonts/100dpi/", - "ROOT/lib/X11/fonts/75dpi/", - "ROOT/lib/X11/fonts/cyrillic/", - "ROOT/lib/X11/fonts/TTF/", - "ROOT/lib/X11/fonts/truetype/", + "LIBDIR/X11/fonts/local/", + "LIBDIR/X11/fonts/misc/:unscaled", + "LIBDIR/X11/fonts/100dpi/:unscaled", + "LIBDIR/X11/fonts/75dpi/:unscaled", + "LIBDIR/X11/fonts/misc/", + "LIBDIR/X11/fonts/Type1/", + "LIBDIR/X11/fonts/CID/", + "LIBDIR/X11/fonts/Speedo/", + "LIBDIR/X11/fonts/100dpi/", + "LIBDIR/X11/fonts/75dpi/", + "LIBDIR/X11/fonts/cyrillic/", + "LIBDIR/X11/fonts/TTF/", + "LIBDIR/X11/fonts/truetype/", + "LIBDIR/X11/fonts/TrueType/", + "LIBDIR/X11/fonts/Type1/sun/", + "LIBDIR/X11/fonts/F3bitmaps/", "/usr/local/share/fonts/ttfonts", "/usr/share/fonts/default/Type1", "/usr/lib/openoffice/share/fonts/truetype", @@ -264,13 +331,18 @@ static void add_font_path(GenerateOptions *gop, XConfigPtr config) if (WEXITSTATUS(ret) == 0) { config->files->fontpath = "unix/:7100"; } else { + + /* get the X server libdir */ + + libdir = find_libdir(gop); + for (i = 0; __font_paths[i]; i++) { path = xconfigStrdup(__font_paths[i]); - /* replace ROOT with the project root */ + /* replace LIBDIR with libdir */ - if (strncmp(path, "ROOT", 4) == 0) { - p = xconfigStrcat(gop->x_project_root, path + 4, NULL); + if (strncmp(path, "LIBDIR", 6) == 0) { + p = xconfigStrcat(libdir, path + 6, NULL); free(path); path = p; } @@ -309,6 +381,10 @@ static void add_font_path(GenerateOptions *gop, XConfigPtr config) config->files->fontpath = path; } } + + /* free the libdir string */ + + free(libdir); } } /* add_font_path() */ @@ -443,7 +519,7 @@ add_device(XConfigPtr config, int bus, int slot, char *boardname, int count) -static XConfigDisplayPtr add_display(int depth) +XConfigDisplayPtr xconfigAddDisplay(XConfigDisplayPtr head, const int depth) { XConfigDisplayPtr display; XConfigModePtr mode = NULL; @@ -461,6 +537,8 @@ static XConfigDisplayPtr add_display(int depth) display->frameY0 = -1; display->black.red = -1; display->white.red = -1; + + display->next = head; return display; } @@ -744,6 +822,7 @@ static char *find_config_entry(const char *filename, const char *keyword) int fd = -1; char *data = NULL; char *value = NULL; + char *buf = NULL; char *tmp, *start, *c, *end; struct stat stat_buf; size_t len; @@ -755,9 +834,21 @@ static char *find_config_entry(const char *filename, const char *keyword) if ((data = mmap(0, stat_buf.st_size, PROT_READ, MAP_SHARED, fd, 0)) == (void *) -1) goto done; + /* + * create a sysmem copy of the buffer, so that we can explicitly + * NULL terminate it + */ + + buf = malloc(stat_buf.st_size + 1); + + if (!buf) goto done; + + memcpy(buf, data, stat_buf.st_size); + buf[stat_buf.st_size] = '\0'; + /* search for the keyword */ - start = data; + start = buf; while (TRUE) { tmp = strstr(start, keyword); @@ -808,6 +899,7 @@ static char *find_config_entry(const char *filename, const char *keyword) done: + if (buf) free(buf); if (data) munmap(data, stat_buf.st_size); if (fd != -1) close(fd); diff --git a/XF86Config-parser/Read.c b/XF86Config-parser/Read.c index 2983447..4e76d2e 100644 --- a/XF86Config-parser/Read.c +++ b/XF86Config-parser/Read.c @@ -305,6 +305,35 @@ xconfigAddListItem (GenericListPtr head, GenericListPtr new) return (new); } + +/* + * removes an item from the linked list. Any record whose first field + * is a GenericListRec can be cast to this type and used with this function. + * A pointer to the head of the list is returned to handle the removal of + * the first item. + */ +GenericListPtr +xconfigRemoveListItem (GenericListPtr head, GenericListPtr item) +{ + GenericListPtr cur = head; + GenericListPtr prev = NULL; + + while (cur) + { + if (cur == item) + { + if (prev) prev->next = item->next; + if (head == item) head = item->next; + break; + } + prev = cur; + cur = cur->next; + } + + return head; +} + + /* * Test if one chained list contains the other. * In this case both list have the same endpoint (provided they don't loop) diff --git a/XF86Config-parser/Scan.c b/XF86Config-parser/Scan.c index e57a3d1..4e694ba 100644 --- a/XF86Config-parser/Scan.c +++ b/XF86Config-parser/Scan.c @@ -736,7 +736,7 @@ const char *xconfigOpenConfigFile(const char *cmdline, const char *projroot) if (getuid() == 0) { searchpath = __root_configpath; } else { - searchpath = __user_configpath; + searchpath = __user_configpath; } if (!projroot) projroot = PROJECTROOT; @@ -944,3 +944,32 @@ xconfigNameCompare (const char *s1, const char *s2) } return (c1 - c2); } + +/* + * Compare two modelines. The modeline identifiers and comments are + * ignored in the comparison. + */ +int +xconfigModelineCompare(XConfigModeLinePtr m1, XConfigModeLinePtr m2) +{ + if (!m1 && !m2) + return (0); + + if (!m1 || !m2) + return (1); + + if (m1->clock != m2->clock && + m1->hdisplay != m2->hdisplay && + m1->hsyncstart != m2->hsyncstart && + m1->hsyncend != m2->hsyncend && + m1->htotal != m2->htotal && + m1->vdisplay != m2->vdisplay && + m1->vsyncstart != m2->vsyncstart && + m1->vsyncend != m2->vsyncend && + m1->vtotal != m2->vtotal && + m1->vscan != m2->vscan && + m1->flags != m2->flags && + m1->hskew != m2->hskew) + return (1); + return (0); +} diff --git a/XF86Config-parser/xf86Parser.h b/XF86Config-parser/xf86Parser.h index 3347690..e47e108 100644 --- a/XF86Config-parser/xf86Parser.h +++ b/XF86Config-parser/xf86Parser.h @@ -647,6 +647,7 @@ int xconfigCheckCoreInputDevices(XConfigPtr config, XConfigLayoutPtr layout); */ GenericListPtr xconfigAddListItem(GenericListPtr head, GenericListPtr c_new); +GenericListPtr xconfigRemoveListItem(GenericListPtr list, GenericListPtr item); int xconfigItemNotSublist(GenericListPtr list_1, GenericListPtr list_2); char *xconfigAddComment(char *cur, char *add); XConfigLoadPtr xconfigAddNewLoadDirective(XConfigLoadPtr head, @@ -673,7 +674,7 @@ XConfigOptionPtr xconfigFindOption(XConfigOptionPtr list, const char *name); char *xconfigFindOptionValue(XConfigOptionPtr list, const char *name); int xconfigFindOptionBoolean (XConfigOptionPtr, - const char *, int); + const char *name); XConfigOptionPtr xconfigOptionListCreate(const char **options, int count, int used); XConfigOptionPtr xconfigOptionListMerge(XConfigOptionPtr head, @@ -686,6 +687,7 @@ XConfigOptionPtr xconfigOptionListMerge(XConfigOptionPtr head, char *xconfigStrdup(const char *s); char *xconfigStrcat(const char *str, ...); int xconfigNameCompare(const char *s1, const char *s2); +int xconfigModelineCompare(XConfigModeLinePtr m1, XConfigModeLinePtr m2); char *xconfigULongToString(unsigned long i); void xconfigDebugListOptions(XConfigOptionPtr); XConfigOptionPtr xconfigParseOption(XConfigOptionPtr head); @@ -693,6 +695,9 @@ void xconfigPrintOptionList(FILE *fp, XConfigOptionPtr list, int tabs); int xconfigParsePciBusString(const char *busID, int *bus, int *device, int *func); +XConfigDisplayPtr +xconfigAddDisplay(XConfigDisplayPtr head, const int depth); + XConfigModePtr xconfigAddMode(XConfigModePtr head, const char *name); diff --git a/gen-manpage-opts.c b/gen-manpage-opts.c index c656003..03bde3e 100644 --- a/gen-manpage-opts.c +++ b/gen-manpage-opts.c @@ -3,6 +3,7 @@ */ #include <stdio.h> #include <ctype.h> +#include <string.h> #include "XF86Config-parser/xf86Parser.h" #include "nvidia-xconfig.h" @@ -11,6 +12,11 @@ static void print_option(const NVGetoptOption *o) { + char scratch[64], *s; + int j, len; + + int omitWhiteSpace; + printf(".TP\n.BI "); /* Print the name of the option */ /* XXX We should backslashify the '-' characters in o->name. */ @@ -26,15 +32,61 @@ static void print_option(const NVGetoptOption *o) } if (o->flags & NVGETOPT_HAS_ARGUMENT) { - printf("=\" \"%s", o->name); + len = strlen(o->name); + for (j = 0; j < len; j++) scratch[j] = toupper(o->name[j]); + scratch[len] = '\0'; + printf("=\" \"%s", scratch); } printf("\"\n"); /* Print the option description */ /* XXX Each sentence should be on its own line! */ - /* XXX We need to backslashify the '-' characters here. */ - printf("%s\n", o->description); + + /* + * Print the option description: write each character one at a + * time (ugh) so that we can special-case a few characters: + * + * "[" --> "\n.I " + * "]" --> "\n" + * "-" --> "\-" + * + * Brackets are used to mark the text inbetween as italics. + * '-' is special cased so that we can backslashify it. + * + * XXX Each sentence should be on its own line! + */ + + omitWhiteSpace = 0; + + for (s = o->description; s && *s; s++) { + + switch (*s) { + case '[': + printf("\n.I "); + omitWhiteSpace = 0; + break; + case ']': + printf("\n"); + omitWhiteSpace = 1; + break; + case '-': + printf("\\-"); + omitWhiteSpace = 0; + break; + case ' ': + if (!omitWhiteSpace) { + printf("%c", *s); + } + break; + default: + printf("%c", *s); + omitWhiteSpace = 0; + break; + } + } + + printf("\n"); } int main(int argc, char* argv[]) @@ -32,7 +32,11 @@ static int lscf_setprop_int(scf_handle_t *scf_handle, scf_service_t *current_svc, const char *group, const char *name, int value); - +static int lscf_getprop_int(scf_handle_t *scf_handle, + scf_scope_t *scf_scope, + scf_service_t *current_svc, + const char *group, + const char *name, int *value); /* UPDATE THE DEFAULT DEPTH PROPERTY IN SMF WITH THE LIBSCF FUNCTIONS */ int update_scf_depth(int depth) @@ -77,6 +81,49 @@ done: return status; } +/* READ THE DEFAULT DEPTH PROPERTY FROM SMF WITH THE LIBSCF FUNCTIONS */ +int read_scf_depth(int *depth) +{ + static scf_handle_t *scf_handle = NULL; + static scf_scope_t *scf_scope = NULL; + scf_service_t *curren_svc = NULL; + int status = 1; + + // Initialization of the handles + lscf_init_handle(&scf_handle, &scf_scope); + if (scf_handle == NULL) { + status =0; + goto done; + } + + // Set the current selection + if(!lscf_select(scf_handle, scf_scope, "application/x11/x11-server", + ¤_svc)) { + status =0; + goto done; + } + + // Get the depth property of the current selection + if(!lscf_getprop_int(scf_handle, scf_scope, curren_svc, + "options", "default_depth", depth)) { + status =0; + goto done; + } + +done: + if(curren_svc) scf_service_destroy(curren_svc); + if(scf_scope) scf_scope_destroy(scf_scope); + if(scf_handle) { + scf_handle_unbind(scf_handle); + scf_handle_destroy(scf_handle); + } + if (!status) { + fmterr("Unable to get X server default depth from " + "Solaris Service Management Facility"); + } + return status; +} + /* INITIALIZATION OF THE HANDLES */ static int lscf_init_handle(scf_handle_t **scf_handle, @@ -270,10 +317,99 @@ done: return status; } +/* EQUIVALENT TO THE SVCCFG SETPROP COMMAND FOR AN INTEGER TYPED VALUE */ +static int lscf_getprop_int(scf_handle_t *scf_handle, + scf_scope_t *scf_scope, + scf_service_t *current_svc, + const char *group, + const char *name, int *value) +{ + scf_transaction_entry_t *entry=NULL; + scf_propertygroup_t *pg = NULL; + scf_property_t *prop = NULL; + scf_value_t *v = NULL; + int status = 1; + int64_t t; + + // Allocate a new transaction entry handle + entry = scf_entry_create(scf_handle); + if (entry == NULL) { + status=0; + goto done; + } + + // Allocate a property group. + pg = scf_pg_create(scf_handle); + if (pg == NULL) { + status=0; + goto done; + } + + // Allocate a property. A property is a named set + // of values. + prop = scf_property_create(scf_handle); + if (prop == NULL) { + status=0; + goto done; + } + + // Set the the property group 'pg' to the + // groups specified by 'group' in the service + // specified by 'current_svc' + if (scf_service_get_pg(current_svc, group, pg) != SCF_SUCCESS) { + status=0; + goto done; + } + + // Update the property group. + if (scf_pg_update(pg) == -1) { + status=0; + goto done; + } + + // Set the property 'prop' to the property + // specified ny 'name' in the property group 'pg' + if (scf_pg_get_property(pg, name, prop) != SCF_SUCCESS) { + status=0; + goto done; + } + // Allocate a value. + v = scf_value_create(scf_handle); + if (v == NULL) { + status=0; + goto done; + } + + // Get the value + if (scf_property_get_value(prop, v) != SCF_SUCCESS) { + status=0; + goto done; + } + + // Get the integer value + if (scf_value_get_integer(v, &t) != SCF_SUCCESS) { + status=0; + goto done; + } + + *value = (int)t; + +done: + if (entry) scf_entry_destroy(entry); + if (pg) scf_pg_destroy(pg); + if (prop) scf_property_destroy(prop); + if (v) scf_value_destroy(v); + return status; +} #else // NOT SOLARIS int update_scf_depth(int depth) { return 1; } + +int read_scf_depth(int *depth) +{ + return 0; +} #endif diff --git a/make_usable.c b/make_usable.c index 0f6c189..c372186 100644 --- a/make_usable.c +++ b/make_usable.c @@ -27,6 +27,7 @@ #include <unistd.h> #include <string.h> +#include <stdlib.h> #include <sys/types.h> #include "nvidia-xconfig.h" @@ -144,6 +145,45 @@ XConfigLayoutPtr get_layout(Options *op, XConfigPtr config) /* + * update_extensions() - apply any requested updates to the Extensions + * section; currently, this only applies to the Composite option. + */ + +int update_extensions(Options *op, XConfigPtr config) +{ + char *value; + + if (GET_BOOL_OPTION(op->boolean_options, COMPOSITE_OPTION)) { + + /* if we don't already have the Extensions section, create it now */ + + if (!config->extensions) { + config->extensions = calloc(1, sizeof(XConfigExtensionsRec)); + } + + /* remove any existing composite extension option */ + + remove_option_from_list(&(config->extensions->options), "Composite"); + + /* determine the value to set for the Composite option */ + + value = GET_BOOL_OPTION(op->boolean_option_values, COMPOSITE_OPTION) ? + "Enable" : "Disable"; + + /* add the option */ + + config->extensions->options = + xconfigAddNewOption(config->extensions->options, + nvstrdup("Composite"), nvstrdup(value)); + } + + return TRUE; + +} /* update_extensions() */ + + + +/* * update_device() - update the device; there is a lot of information * in the device that is not relevant to the NVIDIA X driver. In * fact, some options, like "Chipset" can actually prevent XFree86 @@ -215,7 +255,17 @@ static void update_depth(Options *op, XConfigScreenPtr screen) if ((op->depth == 8) || (op->depth == 15) || (op->depth == 16) || (op->depth == 24)) { screen->defaultdepth = op->depth; - } + } else { + /* read the default depth to SVC and set it as the default depth */ + int scf_depth; + + if (read_scf_depth(&scf_depth) && scf_depth != screen->defaultdepth) { + fmtwarn("The default depth of %d read from " + "the Solaris Management Facility is set as the default " + "depth for screen \"%s\"", scf_depth, screen->identifier); + screen->defaultdepth = scf_depth; + } + } /* * if there is no display at the default depth, force the first diff --git a/multiple_screens.c b/multiple_screens.c index 5b4597c..dd8d60d 100644 --- a/multiple_screens.c +++ b/multiple_screens.c @@ -33,17 +33,6 @@ #include <dlfcn.h> -typedef struct _device_rec { - NvCfgDevice dev; - NvCfgDisplayDeviceInformation info[2]; - int edid_valid; - int crtcs; - char *name; - unsigned int display_device_mask; -} DeviceRec, *DevicePtr; - -static DevicePtr find_devices(Options *op, int *num); - static int enable_separate_x_screens(Options *op, XConfigPtr config, XConfigLayoutPtr layout); static int disable_separate_x_screens(Options *op, XConfigPtr config, @@ -119,9 +108,10 @@ int apply_multi_screen_options(Options *op, XConfigPtr config, * available information about the GPUs in the system. */ -static DevicePtr find_devices(Options *op, int *num) +DevicesPtr find_devices(Options *op) { - DevicePtr devices = NULL; + DevicesPtr pDevices = NULL; + DisplayDevicePtr pDisplayDevice; int i, j, n, count = 0; unsigned int mask, bit; NvCfgDeviceHandle handle; @@ -140,8 +130,6 @@ static DevicePtr find_devices(Options *op, int *num) NvCfgDisplayDeviceInformation *info); NvCfgBool (*__closeDevice)(NvCfgDeviceHandle handle); - *num = 0; - /* dlopen() the nvidia-cfg library */ #define __LIB_NAME "libnvidia-cfg.so.1" @@ -184,63 +172,119 @@ static DevicePtr find_devices(Options *op, int *num) if (count == 0) return NULL; - devices = nvalloc(sizeof(DeviceRec) * count); + pDevices = nvalloc(sizeof(DevicesRec)); + + pDevices->devices = nvalloc(sizeof(DeviceRec) * count); + + pDevices->nDevices = count; for (i = 0; i < count; i++) { - devices[i].dev = devs[i]; + pDevices->devices[i].dev = devs[i]; if (__openDevice(devs[i].bus, devs[i].slot, &handle) != NVCFG_TRUE) goto fail; - if (__getNumCRTCs(handle, &devices[i].crtcs) != NVCFG_TRUE) + if (__getNumCRTCs(handle, &pDevices->devices[i].crtcs) != NVCFG_TRUE) goto fail; - if (__getProductName(handle, &devices[i].name) != NVCFG_TRUE) + if (__getProductName(handle, &pDevices->devices[i].name) != NVCFG_TRUE) goto fail; if (__getDisplayDevices(handle, &mask) != NVCFG_TRUE) goto fail; - devices[i].display_device_mask = mask; + pDevices->devices[i].displayDeviceMask = mask; + /* count the number of display devices */ + for (n = j = 0; j < 32; j++) { - bit = 1 << j; - if (!(bit & mask)) continue; + if (mask & (1 << j)) n++; + } + + pDevices->devices[i].nDisplayDevices = n; + + if (n) { + + /* allocate the info array of the right size */ - if (__getEDID(handle, bit, &devices[i].info[n]) != NVCFG_TRUE) { - devices[i].edid_valid = FALSE; - } else { - devices[i].edid_valid = TRUE; - } + pDevices->devices[i].displayDevices = + nvalloc(sizeof(DisplayDeviceRec) * n); - n++; + /* fill in the info array */ + + for (n = j = 0; j < 32; j++) { + bit = 1 << j; + if (!(bit & mask)) continue; + + pDisplayDevice = &pDevices->devices[i].displayDevices[n]; + pDisplayDevice->mask = bit; + + if (__getEDID(handle, bit, + &pDisplayDevice->info) != NVCFG_TRUE) { + pDisplayDevice->info_valid = FALSE; + } else { + pDisplayDevice->info_valid = TRUE; + } + n++; + } + } else { + pDevices->devices[i].displayDevices = NULL; } if (__closeDevice(handle) != NVCFG_TRUE) goto fail; } - *num = count; - - return devices; - + goto done; + fail: - *num = 0; - if (devices) nvfree((void *) devices); - if (devs) free(devs); - fmtwarn("Unable to use the nvidia-cfg library to query NVIDIA " "hardware."); + + free_devices(pDevices); + pDevices = NULL; + + /* fall through */ + + done: - return NULL; + if (devs) free(devs); + + return pDevices; } /* find_devices() */ /* + * free_devices() + */ + +void free_devices(DevicesPtr pDevices) +{ + int i; + + if (!pDevices) return; + + for (i = 0; i < pDevices->nDevices; i++) { + if (pDevices->devices[i].displayDevices) { + nvfree(pDevices->devices[i].displayDevices); + } + } + + if (pDevices->devices) { + nvfree(pDevices->devices); + } + + nvfree(pDevices); + +} /* free_devices() */ + + + +/* * set_xinerama() - This makes sure there is a ServerFlags * section and sets the "Xinerama" option */ @@ -348,11 +392,10 @@ static int enable_separate_x_screens(Options *op, XConfigPtr config, */ if (!have_busids) { - DevicePtr devs; - int ndevs; + DevicesPtr pDevices; - devs = find_devices(op, &ndevs); - if (!devs) { + pDevices = find_devices(op); + if (!pDevices) { fmterr("Unable to determine number or location of " "GPUs in system; cannot " "honor '--separate-x-screens' option."); @@ -360,7 +403,7 @@ static int enable_separate_x_screens(Options *op, XConfigPtr config, } for (i = 0; i < nscreens; i++) { - if (i > ndevs) { + if (i > pDevices->nDevices) { /* * we have more screens than GPUs, this screen is no * longer a candidate @@ -371,9 +414,13 @@ static int enable_separate_x_screens(Options *op, XConfigPtr config, screenlist[i]->device->busid = nvalloc(32); snprintf(screenlist[i]->device->busid, 32, - "PCI:%d:%d:0", devs[i].dev.bus, devs[i].dev.slot); - screenlist[i]->device->board = nvstrdup(devs[i].name); + "PCI:%d:%d:0", + pDevices->devices[i].dev.bus, + pDevices->devices[i].dev.slot); + screenlist[i]->device->board = nvstrdup(pDevices->devices[i].name); } + + free_devices(pDevices); } /* @@ -747,11 +794,11 @@ static void create_adjacencies(Options *op, XConfigPtr config, static int enable_all_gpus(Options *op, XConfigPtr config, XConfigLayoutPtr layout) { - DevicePtr devs; - int n, i; + DevicesPtr pDevices; + int i; - devs = find_devices(op, &n); - if (!devs) { + pDevices = find_devices(op); + if (!pDevices) { fmterr("Unable to determine number of GPUs in system; cannot " "honor '--enable-all-gpus' option."); return FALSE; @@ -773,11 +820,15 @@ static int enable_all_gpus(Options *op, XConfigPtr config, /* add N new screens; this will also add device and monitor sections */ - for (i = 0; i < n; i++) { - xconfigGenerateAddScreen(config, devs[i].dev.bus, devs[i].dev.slot, - devs[i].name, i); + for (i = 0; i < pDevices->nDevices; i++) { + xconfigGenerateAddScreen(config, + pDevices->devices[i].dev.bus, + pDevices->devices[i].dev.slot, + pDevices->devices[i].name, i); } + free_devices(pDevices); + /* create adjacencies for the layout */ create_adjacencies(op, config, layout); diff --git a/nvidia-xconfig.1.m4 b/nvidia-xconfig.1.m4 index e0f5278..3e19099 100644 --- a/nvidia-xconfig.1.m4 +++ b/nvidia-xconfig.1.m4 @@ -32,7 +32,7 @@ configuration file to create: if the X server in use is X.org or .I /etc/X11/XF86Config -if the X server in use is XFree86." +if the X server in use is XFree86. .TP 2) The configuration in memory is modified to support the NVIDIA driver. diff --git a/nvidia-xconfig.c b/nvidia-xconfig.c index b5fd719..8e78d6a 100644 --- a/nvidia-xconfig.c +++ b/nvidia-xconfig.c @@ -33,6 +33,9 @@ #include <errno.h> #include <libgen.h> +#include <sys/types.h> +#include <sys/stat.h> + #include "nvidia-xconfig.h" #include "nvgetopt.h" @@ -81,6 +84,35 @@ static void print_summary(void) /* + * cook_description() - the description string may contain text within + * brackets, which is used by the manpage generator to denote text to + * be italicized. We want to omit the bracket characters here. + */ + +static char *cook_description(const char *description) +{ + int len; + char *s, *dst; + const char *src; + + len = strlen(description); + s = nvalloc(len + 1); + + for (src = description, dst = s; *src; src++) { + if (*src != '[' && (*src != ']')) { + *dst = *src; + dst++; + } + } + + *dst = '\0'; + + return s; + +} /* cook_description() */ + + +/* * print_help() - loop through the __options[] table, and print the * description of each option. */ @@ -118,7 +150,7 @@ static void print_help(int advanced) len = strlen(o->name); for (j = 0; j < len; j++) scratch[j] = toupper(o->name[j]); scratch[len] = '\0'; - tmp = nvstrcat(msg, "=[", scratch, "]", NULL); + tmp = nvstrcat(msg, "=", scratch, NULL); free(msg); msg = tmp; } @@ -130,7 +162,11 @@ static void print_help(int advanced) } fmtoutp(TAB, msg); - if (o->description) fmtoutp(BIGTAB, o->description); + if (o->description) { + tmp = cook_description(o->description); + fmtoutp(BIGTAB, tmp); + free(tmp); + } fmtout(""); free(msg); } @@ -139,6 +175,39 @@ static void print_help(int advanced) /* + * get_default_project_root() - scan some common directories for the X + * project root + * + * Users of this information should be careful to account for the + * modular layout. + */ + +char *get_default_project_root(void) +{ + char *paths[] = { "/usr/X11R6", "/usr/X11", NULL }; + struct stat stat_buf; + int i; + + for (i = 0; paths[i]; i++) { + + if (stat(paths[i], &stat_buf) == -1) { + continue; + } + + if (S_ISDIR(stat_buf.st_mode)) { + return paths[i]; + } + } + + /* default to "/usr/X11R6", I guess */ + + return paths[0]; + +} /* get_default_project_root() */ + + + +/* * parse_commandline() - malloc an Options structure, initialize it, * and fill in any pertinent data from the commandline arguments */ @@ -153,7 +222,7 @@ Options *parse_commandline(int argc, char *argv[]) op = (Options *) nvalloc(sizeof(Options)); - op->gop.x_project_root = "/usr/X11R6"; + op->gop.x_project_root = get_default_project_root(); op->nvagp = -1; op->digital_vibrance = -1; op->transparent_index = -1; @@ -348,6 +417,8 @@ Options *parse_commandline(int argc, char *argv[]) case DISABLE_SCF_OPTION: op->disable_scf = TRUE; break; + case QUERY_GPU_INFO_OPTION: op->query_gpu_info = TRUE; break; + default: goto fail; } @@ -527,6 +598,16 @@ int write_xconfig(Options *op, XConfigPtr config) fmtmsg("New X configuration file written to '%s'", filename); fmtmsg(""); + + /* Set the default depth in the Solaris Management Facility + * to the default depth of the first screen + */ + if (op->disable_scf == FALSE) { + if(!update_scf_depth(config->screens[0].defaultdepth)) { + goto done; + } + } + ret = TRUE; done: @@ -679,6 +760,8 @@ int update_xconfig(Options *op, XConfigPtr config) } } + update_extensions(op, config); + update_modules(config); update_banner(config); @@ -688,6 +771,14 @@ int update_xconfig(Options *op, XConfigPtr config) } /* update_xconfig() */ + +/* + * get_xserver_in_use() - try to determine which X server is in use + * (XFree86, Xorg) + * + * XXX need to update for modular layout + */ + # define NV_LINE_LEN 1024 static void get_xserver_in_use(Options *op) { @@ -775,6 +866,11 @@ int main(int argc, char *argv[]) xconfigGeneratePrintPossibleMice(); return 0; } + + if (op->query_gpu_info) { + ret = query_gpu_info(op); + return (ret ? 0 : 1); + } /* * we want to open and parse the system's existing X config file, @@ -835,14 +931,6 @@ int main(int argc, char *argv[]) return 1; } - /* Set the default depth in the Solaris Management Facility - * to the default depth of the first screen - */ - if (op->disable_scf == TRUE) { - return 0; - } else if(!update_scf_depth(config->screens[0].defaultdepth)) { - return 1; - } return 0; } /* main() */ diff --git a/nvidia-xconfig.h b/nvidia-xconfig.h index 4786992..2d839e6 100644 --- a/nvidia-xconfig.h +++ b/nvidia-xconfig.h @@ -52,35 +52,37 @@ typedef struct { /* Boolean options */ -#define NOLOGO_OPTION 1 -#define UBB_OPTION 2 -#define RENDER_ACCEL_OPTION 3 -#define NO_RENDER_EXTENSION_OPTION 4 -#define OVERLAY_OPTION 5 -#define CIOVERLAY_OPTION 6 -#define OVERLAY_DEFAULT_VISUAL_OPTION 7 -#define NO_BANDWIDTH_TEST_OPTION 8 -#define NO_POWER_CONNECTOR_CHECK_OPTION 9 -#define ALLOW_DFP_STEREO_OPTION 10 -#define ALLOW_GLX_WITH_COMPOSITE_OPTION 11 -#define RANDR_ROTATION_OPTION 12 -#define TWINVIEW_OPTION 13 -#define SEPARATE_X_SCREENS_OPTION 14 -#define XINERAMA_OPTION 15 -#define NO_TWINVIEW_XINERAMA_INFO_OPTION 16 -#define NOFLIP_OPTION 17 -#define DAC_8BIT_OPTION 18 -#define USE_EDID_FREQS_OPTION 19 -#define IGNORE_EDID_OPTION 20 -#define USE_INT10_MODULE_OPTION 21 -#define FORCE_STEREO_FLIPPING_OPTION 22 -#define MULTISAMPLE_COMPATIBILITY_OPTION 23 -#define XVMC_USES_TEXTURES_OPTION 24 -#define EXACT_MODE_TIMINGS_DVI_OPTION 25 -#define ALLOW_DDCCI_OPTION 26 -#define LOAD_KERNEL_MODULE_OPTION 27 - -#define XCONFIG_BOOL_OPTION_COUNT LOAD_KERNEL_MODULE_OPTION +#define NOLOGO_OPTION 0 +#define UBB_OPTION 1 +#define RENDER_ACCEL_OPTION 2 +#define NO_RENDER_EXTENSION_OPTION 3 +#define OVERLAY_OPTION 4 +#define CIOVERLAY_OPTION 5 +#define OVERLAY_DEFAULT_VISUAL_OPTION 6 +#define NO_BANDWIDTH_TEST_OPTION 7 +#define NO_POWER_CONNECTOR_CHECK_OPTION 8 +#define ALLOW_DFP_STEREO_OPTION 9 +#define ALLOW_GLX_WITH_COMPOSITE_OPTION 10 +#define RANDR_ROTATION_OPTION 11 +#define TWINVIEW_OPTION 12 +#define SEPARATE_X_SCREENS_OPTION 13 +#define XINERAMA_OPTION 14 +#define NO_TWINVIEW_XINERAMA_INFO_OPTION 15 +#define NOFLIP_OPTION 16 +#define DAC_8BIT_OPTION 17 +#define USE_EDID_FREQS_OPTION 18 +#define IGNORE_EDID_OPTION 19 +#define USE_INT10_MODULE_OPTION 20 +#define FORCE_STEREO_FLIPPING_OPTION 21 +#define MULTISAMPLE_COMPATIBILITY_OPTION 22 +#define XVMC_USES_TEXTURES_OPTION 23 +#define EXACT_MODE_TIMINGS_DVI_OPTION 24 +#define ALLOW_DDCCI_OPTION 25 +#define LOAD_KERNEL_MODULE_OPTION 26 +#define ADD_ARGB_GLX_VISUALS_OPTION 27 +#define COMPOSITE_OPTION 28 + +#define XCONFIG_BOOL_OPTION_COUNT (COMPOSITE_OPTION + 1) /* # of 32-bit variables needed to hold all the boolean options (bits) */ #define XCONFIG_BOOL_OPTION_SLOTS \ @@ -111,6 +113,7 @@ typedef struct __options { int enable_all_gpus; int only_one_screen; int disable_scf; + int query_gpu_info; /* * the option parser will set bits in boolean_options to indicate @@ -144,6 +147,28 @@ typedef struct __options { } Options; +/* data structures for storing queried GPU information */ + +typedef struct _display_device_rec { + NvCfgDisplayDeviceInformation info; + int info_valid; + unsigned int mask; +} DisplayDeviceRec, *DisplayDevicePtr; + +typedef struct _device_rec { + NvCfgDevice dev; + int crtcs; + char *name; + unsigned int displayDeviceMask; + int nDisplayDevices; + DisplayDevicePtr displayDevices; +} DeviceRec, *DevicePtr; + +typedef struct { + int nDevices; + DevicePtr devices; +} DevicesRec, *DevicesPtr; + /* util.c */ @@ -151,7 +176,7 @@ void *nvalloc(size_t size); char *nvstrcat(const char *str, ...); void *nvrealloc(void *ptr, size_t size); char *nvstrdup(const char *s); -void nvfree(char *s); +void nvfree(void *s); int copy_file(const char *srcfile, const char *dstfile, mode_t mode); int directory_exists(const char *dir); @@ -180,9 +205,13 @@ void fmtwarn(const char *fmt, ...); int update_modules(XConfigPtr config); int update_screen(Options *op, XConfigPtr config, XConfigScreenPtr screen); XConfigLayoutPtr get_layout(Options *op, XConfigPtr config); +int update_extensions(Options *op, XConfigPtr config); /* multiple_screens.c */ +DevicesPtr find_devices(Options *op); +void free_devices(DevicesPtr devs); + int apply_multi_screen_options(Options *op, XConfigPtr config, XConfigLayoutPtr layout); @@ -197,5 +226,11 @@ void update_options(Options *op, XConfigScreenPtr screen); /* lscf.c */ int update_scf_depth(int depth); +int read_scf_depth(int *depth); + +/* query_gpu_info.c */ + +int query_gpu_info(Options *op); + #endif /* __NVIDIA_XCONFIG_H__ */ diff --git a/option_table.h b/option_table.h index 5d42994..148120a 100644 --- a/option_table.h +++ b/option_table.h @@ -29,6 +29,7 @@ #define TRANSPARENT_INDEX_OPTION 17 #define STEREO_OPTION 18 #define ROTATE_OPTION 19 +#define QUERY_GPU_INFO_OPTION 20 #define XCONFIG_OPTION_START 128 @@ -74,6 +75,11 @@ static const NVGetoptOption __options[] = { /* These options are only printed by "nvidia-xconfig --advanced-help" */ + { "add-argb-glx-visuals", + XCONFIG_OPTION_START + ADD_ARGB_GLX_VISUALS_OPTION, NVGETOPT_IS_BOOLEAN, + "Enables or disables support for OpenGL rendering into 32-bit ARGB " + "windows and pixmaps." }, + { "allow-ddcci", XCONFIG_OPTION_START + ALLOW_DDCCI_OPTION, NVGETOPT_IS_BOOLEAN, "Enables or disables DDC/CI support in the " "NV-CONTROL X extension." }, @@ -91,6 +97,10 @@ static const NVGetoptOption __options[] = { XCONFIG_OPTION_START + NO_BANDWIDTH_TEST_OPTION, NVGETOPT_IS_BOOLEAN, "Disable or enable the \"NoBandWidthTest\" X configuration option." }, + { "composite", + XCONFIG_OPTION_START + COMPOSITE_OPTION, NVGETOPT_IS_BOOLEAN, + "Enable or disable the \"Composite\" X extension." }, + { "dac-8bit", XCONFIG_OPTION_START + DAC_8BIT_OPTION, NVGETOPT_IS_BOOLEAN, "Most Quadro parts by default use a 10 bit color look up table (LUT) " "by default; setting this option to TRUE forces these graphics chips " @@ -101,11 +111,13 @@ static const NVGetoptOption __options[] = { "Synonym for \"ignore-edid\"" }, { "depth", 'd', NVGETOPT_HAS_ARGUMENT, - "Set the default depth to [DEPTH]; valid values are 8, 15, 16 and 24." }, + "Set the default depth to [DEPTH]; valid values for [DEPTH] are " + "8, 15, 16 and 24." }, { "digital-vibrance", DIGITAL_VIBRANCE_OPTION, NVGETOPT_IS_INTEGER | NVGETOPT_HAS_ARGUMENT, - "Enables digital vibrance control. Valid values are 0-255." }, + "Enables digital vibrance control. Valid values for " + "[DIGITAL-VIBRANCE] are 0-255." }, { "enable-all-gpus", 'a', 0, "Configure an X screen on every GPU in the system." }, @@ -234,7 +246,7 @@ static const NVGetoptOption __options[] = { { "transparent-index", TRANSPARENT_INDEX_OPTION, NVGETOPT_IS_INTEGER | NVGETOPT_HAS_ARGUMENT, "Pixel to use as transparent when using color index overlays. " - "Valid values are 0-255."}, + "Valid values for [TRANSPARENT-INDEX] are 0-255."}, { "overlay-default-visual", XCONFIG_OPTION_START + OVERLAY_DEFAULT_VISUAL_OPTION, @@ -253,6 +265,9 @@ static const NVGetoptOption __options[] = { NVGETOPT_IS_BOOLEAN, "Disable or enable the \"NoPowerConnectorCheck\" " "X configuration option." }, + { "query-gpu-info", QUERY_GPU_INFO_OPTION, 0, + "Print information about all recognized NVIDIA GPUs in the system." }, + { "randr-rotation", XCONFIG_OPTION_START + RANDR_ROTATION_OPTION, NVGETOPT_IS_BOOLEAN, "Enable or disable the \"RandRRotation\" X configuration option." }, @@ -260,7 +275,7 @@ static const NVGetoptOption __options[] = { { "rotate", ROTATE_OPTION, NVGETOPT_HAS_ARGUMENT, "Enable or disable the \"Rotate\" X configuration option. Valid values " - "are 'normal', 'left', 'inverted', and 'right'." }, + "for [ROTATE] are 'normal', 'left', 'inverted', and 'right'." }, { "render-accel", XCONFIG_OPTION_START + RENDER_ACCEL_OPTION, NVGETOPT_IS_BOOLEAN, @@ -282,14 +297,14 @@ static const NVGetoptOption __options[] = { "details." }, { "sli", SLI_OPTION, NVGETOPT_HAS_ARGUMENT, - "Enable or disable SLI. Valid options are 'Off', 'Auto', 'AFR', 'SFR', " - "and 'SLIAA'." }, + "Enable or disable SLI. Valid values for [SLI] are 'Off', 'Auto', " + "'AFR', 'SFR', and 'SLIAA'." }, { "stereo", STEREO_OPTION, NVGETOPT_IS_INTEGER | NVGETOPT_HAS_ARGUMENT, - "Enable/Disable the stereo mode. Valid options are: 1 (DCC glasses), " - "2 (Blueline glasses), 3 (Onboard stereo), 4 (TwinView clone mode " - "stereo), 5 (SeeReal digital flat panel), 6 (Sharp3D digital flat " - "panel)." }, + "Enable/Disable the stereo mode. Valid values for [STEREO] are: 1 " + "(DCC glasses), 2 (Blueline glasses), 3 (Onboard stereo), 4 (TwinView " + "clone mode stereo), 5 (SeeReal digital flat panel), 6 (Sharp3D " + "digital flat panel)." }, { "twinview", XCONFIG_OPTION_START + TWINVIEW_OPTION, NVGETOPT_IS_BOOLEAN, "Enable or disable TwinView." }, @@ -66,6 +66,7 @@ static const NvidiaXConfigOption __options[] = { { EXACT_MODE_TIMINGS_DVI_OPTION, FALSE, "ExactModeTimingsDVI" }, { ALLOW_DDCCI_OPTION, FALSE, "AllowDDCCI" }, { LOAD_KERNEL_MODULE_OPTION, FALSE, "LoadKernelModule" }, + { ADD_ARGB_GLX_VISUALS_OPTION, FALSE, "AddARGBGLXVisuals" }, { 0, FALSE, NULL }, }; @@ -194,12 +195,13 @@ void update_options(Options *op, XConfigScreenPtr screen) if (GET_BOOL_OPTION(op->boolean_options, i)) { /* - * SEPARATE_X_SCREENS_OPTION and XINERAMA_OPTION are - * handled separately + * SEPARATE_X_SCREENS_OPTION, XINERAMA_OPTION, and + * COMPOSITE_OPTION are handled separately */ if (i == SEPARATE_X_SCREENS_OPTION) continue; if (i == XINERAMA_OPTION) continue; + if (i == COMPOSITE_OPTION) continue; o = get_option(i); diff --git a/query_gpu_info.c b/query_gpu_info.c new file mode 100644 index 0000000..b187bd0 --- /dev/null +++ b/query_gpu_info.c @@ -0,0 +1,232 @@ +/* + * nvidia-xconfig: A tool for manipulating X config files, + * specifically for use by the NVIDIA Linux graphics driver. + * + * Copyright (C) 2006 NVIDIA Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307, USA + * + * + * query_gpu_info.c + */ + +#include "nvidia-xconfig.h" + +static char *display_device_mask_to_display_device_name(unsigned int mask); + + +#define TAB " " +#define BIGTAB " " + + + +/* + * query_gpu_info() - query information about the GPU, and print it + * out + */ + +int query_gpu_info(Options *op) +{ + DevicesPtr pDevices; + DisplayDevicePtr pDisplayDevice; + int i, j; + char *name; + + /* query the GPU information */ + + pDevices = find_devices(op); + + if (!pDevices) { + fmterr("Unable to query GPU information"); + return FALSE; + } + + /* print the GPU information */ + + fmtout("Number of GPUs: %d", pDevices->nDevices); + + for (i = 0; i < pDevices->nDevices; i++) { + + fmtout(""); + fmtout("GPU #%d:", i); + fmtoutp(TAB, "Name : %s", pDevices->devices[i].name); + + fmtoutp(TAB, "PCI BusID : PCI:%d:%d:0", + pDevices->devices[i].dev.bus, + pDevices->devices[i].dev.slot); + + fmtout(""); + fmtoutp(TAB, "Number of Display Devices: %d", + pDevices->devices[i].nDisplayDevices); + fmtout(""); + + for (j = 0; j < pDevices->devices[i].nDisplayDevices; j++) { + + pDisplayDevice = &pDevices->devices[i].displayDevices[j]; + + name = display_device_mask_to_display_device_name + (pDisplayDevice->mask); + + if (!name) name = nvstrdup("Unknown"); + + fmtoutp(TAB, "Display Device %d (%s):", j, name); + + nvfree(name); + + /* + * convenience macro to first check that the value is + * non-zero + */ + + #define PRT(_fmt, _val) \ + if (_val) { \ + fmtoutp(BIGTAB, (_fmt), (_val)); \ + } + + if (pDisplayDevice->info_valid) { + + PRT("EDID Name : %s", + pDisplayDevice->info.monitor_name); + + PRT("Minimum HorizSync : %.3f kHz", + pDisplayDevice->info.min_horiz_sync/1000.0); + + PRT("Maximum HorizSync : %.3f kHz", + pDisplayDevice->info.max_horiz_sync/1000.0); + + PRT("Minimum VertRefresh : %d Hz", + pDisplayDevice->info.min_vert_refresh); + + PRT("Maximum VertRefresh : %d Hz", + pDisplayDevice->info.max_vert_refresh); + + PRT("Maximum PixelClock : %.3f MHz", + pDisplayDevice->info.max_pixel_clock/1000.0); + + PRT("Maximum Width : %d pixels", + pDisplayDevice->info.max_xres); + + PRT("Maximum Height : %d pixels", + pDisplayDevice->info.max_yres); + + PRT("Preferred Width : %d pixels", + pDisplayDevice->info.preferred_xres); + + PRT("Preferred Height : %d pixels", + pDisplayDevice->info.preferred_yres); + + PRT("Preferred VertRefresh : %d Hz", + pDisplayDevice->info.preferred_refresh); + + PRT("Physical Width : %d mm", + pDisplayDevice->info.physical_width); + + PRT("Physical Height : %d mm", + pDisplayDevice->info.physical_height); + + } else { + fmtoutp(BIGTAB, "No EDID information available."); + } + + fmtout(""); + } + } + + free_devices(pDevices); + + return TRUE; + +} /* query_gpu_info() */ + + + + +/* + * diaplay_mask/display_name conversions: the NV-CONTROL X extension + * identifies a display device by a bit in a display device mask. The + * below function translates from a display mask to a string + * describing the display devices. + */ + +#define BITSHIFT_CRT 0 +#define BITSHIFT_TV 8 +#define BITSHIFT_DFP 16 + +#define BITMASK_ALL_CRT (0xff << BITSHIFT_CRT) +#define BITMASK_ALL_TV (0xff << BITSHIFT_TV) +#define BITMASK_ALL_DFP (0xff << BITSHIFT_DFP) + +/* + * display_device_mask_to_display_name() - construct a string + * describing the given display device mask. + */ + +#define DISPLAY_DEVICE_STRING_LEN 256 + +static char *display_device_mask_to_display_device_name(unsigned int mask) +{ + char *s; + int first = TRUE; + unsigned int devcnt, devmask; + char *display_device_name_string; + + display_device_name_string = nvalloc(DISPLAY_DEVICE_STRING_LEN); + + s = display_device_name_string; + + devmask = 1 << BITSHIFT_CRT; + devcnt = 0; + while (devmask & BITMASK_ALL_CRT) { + if (devmask & mask) { + if (first) first = FALSE; + else s += sprintf(s, ", "); + s += sprintf(s, "CRT-%X", devcnt); + } + devmask <<= 1; + devcnt++; + } + + devmask = 1 << BITSHIFT_DFP; + devcnt = 0; + while (devmask & BITMASK_ALL_DFP) { + if (devmask & mask) { + if (first) first = FALSE; + else s += sprintf(s, ", "); + s += sprintf(s, "DFP-%X", devcnt); + } + devmask <<= 1; + devcnt++; + } + + devmask = 1 << BITSHIFT_TV; + devcnt = 0; + while (devmask & BITMASK_ALL_TV) { + if (devmask & mask) { + if (first) first = FALSE; + else s += sprintf(s, ", "); + s += sprintf(s, "TV-%X", devcnt); + } + devmask <<= 1; + devcnt++; + } + + *s = '\0'; + + return (display_device_name_string); + +} /* display_device_mask_to_display_name() */ @@ -271,6 +271,26 @@ static void print_server_flags(XConfigPtr config) /* + * print_server_extensions() + */ + +static void print_server_extensions(XConfigPtr config) +{ + if (!config->extensions || !config->extensions->options) return; + + printf("\n"); + printf(" Extensions\n"); + printf(" |\n"); + + print_options(config->extensions->options, 1); + + printf("\n"); + +} /* print_server_extensions() */ + + + +/* * print_tree() */ @@ -305,6 +325,8 @@ int print_tree(Options *op, XConfigPtr config) print_server_flags(config); + print_server_extensions(config); + return TRUE; } /* print_tree() */ @@ -210,7 +210,7 @@ char *nvstrdup(const char *s) /* * nvfree() - */ -void nvfree(char *s) +void nvfree(void *s) { if (s) free(s); |