19042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz/************************************************************************** 29042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz * 39042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz * Copyright © 2009 VMware, Inc., Palo Alto, CA., USA 49042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz * All Rights Reserved. 59042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz * 69042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz * Permission is hereby granted, free of charge, to any person obtaining a 79042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz * copy of this software and associated documentation files (the 89042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz * "Software"), to deal in the Software without restriction, including 99042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz * without limitation the rights to use, copy, modify, merge, publish, 109042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz * distribute, sub license, and/or sell copies of the Software, and to 119042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz * permit persons to whom the Software is furnished to do so, subject to 129042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz * the following conditions: 139042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz * 149042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz * The above copyright notice and this permission notice (including the 159042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz * next paragraph) shall be included in all copies or substantial portions 169042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz * of the Software. 179042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz * 189042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 199042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 209042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 219042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 229042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 239042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 249042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz * USE OR OTHER DEALINGS IN THE SOFTWARE. 259042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz * 269042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz **************************************************************************/ 279042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz/* 289042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz * Thanks to krh and jcristau for the tips on 299042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz * going from fd to pci id via fstat and udev. 309042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz */ 319042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz 329042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz 338e93afc9765f1de613c65a76e9a86e17db96e653Emil Velikov#ifdef HAVE_CONFIG_H 34d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz#include "config.h" 358e93afc9765f1de613c65a76e9a86e17db96e653Emil Velikov#endif 369042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz#include <errno.h> 379042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz#include <stdio.h> 38d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz#include <stdlib.h> 399042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz#include <xf86drm.h> 40d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz#include <string.h> 41d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz#include <unistd.h> 42d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz 439042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz#include <sys/stat.h> 449042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz 459042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz#include "internal.h" 469042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz 47d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz#define PATH_SIZE 512 48d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz 49d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantzstatic int 50d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantzlinux_name_from_sysfs(int fd, char **out) 51d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz{ 52d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz char path[PATH_SIZE+1] = ""; /* initialize to please valgrind */ 53d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz char link[PATH_SIZE+1] = ""; 54d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz struct stat buffer; 55d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz unsigned maj, min; 56d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz char* slash_name; 57d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz int ret; 58d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz 59d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz /* 60d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz * Inside the sysfs directory for the device there is a symlink 61d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz * to the directory representing the driver module, that path 62d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz * happens to hold the name of the driver. 63d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz * 64d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz * So lets get the symlink for the drm device. Then read the link 65d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz * and filter out the last directory which happens to be the name 66d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz * of the driver, which we can use to load the correct interface. 67d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz * 68d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz * Thanks to Ray Strode of Plymouth for the code. 69d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz */ 70d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz 71d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz ret = fstat(fd, &buffer); 72d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz if (ret) 73baf0a7daafc7636106e1b19267ed22e22b1a2283Maxime Villard return -EINVAL; 74d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz 75d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz if (!S_ISCHR(buffer.st_mode)) 76d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz return -EINVAL; 77d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz 78d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz maj = major(buffer.st_rdev); 79d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz min = minor(buffer.st_rdev); 80d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz 81d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz snprintf(path, PATH_SIZE, "/sys/dev/char/%d:%d/device/driver", maj, min); 82d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz 83d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz if (readlink(path, link, PATH_SIZE) < 0) 84d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz return -EINVAL; 85d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz 86d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz /* link looks something like this: ../../../bus/pci/drivers/intel */ 87d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz slash_name = strrchr(link, '/'); 88d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz if (!slash_name) 89d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz return -EINVAL; 90d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz 91d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz /* copy name and at the same time remove the slash */ 92d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz *out = strdup(slash_name + 1); 93d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz return 0; 94d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz} 95d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz 96d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantzstatic int 97d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantzlinux_from_sysfs(int fd, struct kms_driver **out) 98d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz{ 99d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz char *name; 100d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz int ret; 101d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz 102d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz ret = linux_name_from_sysfs(fd, &name); 103d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz if (ret) 104d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz return ret; 105d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz 106f3fd11beaa70b0624ab1d6c7d8e25c65eea942acEmil Velikov#ifdef HAVE_INTEL 107d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz if (!strcmp(name, "intel")) 108d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz ret = intel_create(fd, out); 109f3fd11beaa70b0624ab1d6c7d8e25c65eea942acEmil Velikov else 110f3fd11beaa70b0624ab1d6c7d8e25c65eea942acEmil Velikov#endif 111d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz#ifdef HAVE_VMWGFX 112f3fd11beaa70b0624ab1d6c7d8e25c65eea942acEmil Velikov if (!strcmp(name, "vmwgfx")) 113d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz ret = vmwgfx_create(fd, out); 114f3fd11beaa70b0624ab1d6c7d8e25c65eea942acEmil Velikov else 115d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz#endif 116d5a2e776826f7a849f1cf654fde8611f687eb12cMarcin KoÅ›cielnicki#ifdef HAVE_NOUVEAU 117f3fd11beaa70b0624ab1d6c7d8e25c65eea942acEmil Velikov if (!strcmp(name, "nouveau")) 118d5a2e776826f7a849f1cf654fde8611f687eb12cMarcin KoÅ›cielnicki ret = nouveau_create(fd, out); 119f3fd11beaa70b0624ab1d6c7d8e25c65eea942acEmil Velikov else 120d5a2e776826f7a849f1cf654fde8611f687eb12cMarcin KoÅ›cielnicki#endif 121ed7d177f66885dfbc4e8410154559c4767fefa9fnobled#ifdef HAVE_RADEON 122f3fd11beaa70b0624ab1d6c7d8e25c65eea942acEmil Velikov if (!strcmp(name, "radeon")) 123ed7d177f66885dfbc4e8410154559c4767fefa9fnobled ret = radeon_create(fd, out); 124f3fd11beaa70b0624ab1d6c7d8e25c65eea942acEmil Velikov else 125ed7d177f66885dfbc4e8410154559c4767fefa9fnobled#endif 1263732ef59eb1198d6a4cb5b8bbca6b155c53529f6Hyungwon Hwang#ifdef HAVE_EXYNOS 127f3fd11beaa70b0624ab1d6c7d8e25c65eea942acEmil Velikov if (!strcmp(name, "exynos")) 1283732ef59eb1198d6a4cb5b8bbca6b155c53529f6Hyungwon Hwang ret = exynos_create(fd, out); 129d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz else 130f3fd11beaa70b0624ab1d6c7d8e25c65eea942acEmil Velikov#endif 131d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz ret = -ENOSYS; 132d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz 133d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz free(name); 134d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz return ret; 135d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz} 136d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz 137d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz#if 0 1389042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz#define LIBUDEV_I_KNOW_THE_API_IS_SUBJECT_TO_CHANGE 1399042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz#include <libudev.h> 1409042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz 141d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantzstruct create_record 142d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz{ 143d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz unsigned vendor; 144d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz unsigned chip; 145d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz int (*func)(int fd, struct kms_driver **out); 146d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz}; 147d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz 148d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantzstatic struct create_record table[] = { 149d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz { 0x8086, 0x2a42, intel_create }, /* i965 */ 150d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz#ifdef HAVE_VMWGFX 151d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz { 0x15ad, 0x0405, vmwgfx_create }, /* VMware vGPU */ 152d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz#endif 153d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz { 0, 0, NULL }, 154d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz}; 155d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz 156d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantzstatic int 157d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantzlinux_get_pciid_from_fd(int fd, unsigned *vendor_id, unsigned *chip_id) 1589042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz{ 1599042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz struct udev *udev; 1609042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz struct udev_device *device; 1619042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz struct udev_device *parent; 1629042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz const char *pci_id; 1639042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz struct stat buffer; 1649042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz int ret; 1659042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz 1669042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz ret = fstat(fd, &buffer); 1679042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz if (ret) 1689042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz return -EINVAL; 1699042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz 1709042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz if (!S_ISCHR(buffer.st_mode)) 1719042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz return -EINVAL; 1729042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz 1739042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz udev = udev_new(); 1749042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz if (!udev) 1759042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz return -ENOMEM; 1769042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz 1779042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz device = udev_device_new_from_devnum(udev, 'c', buffer.st_rdev); 1789042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz if (!device) 1799042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz goto err_free_udev; 1809042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz 1819042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz parent = udev_device_get_parent(device); 1829042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz if (!parent) 1839042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz goto err_free_device; 1849042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz 1859042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz pci_id = udev_device_get_property_value(parent, "PCI_ID"); 1869042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz if (!pci_id) 1879042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz goto err_free_device; 1889042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz 1899042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz if (sscanf(pci_id, "%x:%x", vendor_id, chip_id) != 2) 1909042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz goto err_free_device; 1919042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz 1929042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz udev_device_unref(device); 1939042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz udev_unref(udev); 1949042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz 1959042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz return 0; 1969042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz 1979042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantzerr_free_device: 1989042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz udev_device_unref(device); 1999042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantzerr_free_udev: 2009042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz udev_unref(udev); 2019042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz return -EINVAL; 2029042d72109d8ae448b8e0f23b93067cc37deff23Jakob Bornecrantz} 203d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz 204d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantzstatic int 205d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantzlinux_from_udev(int fd, struct kms_driver **out) 206d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz{ 207d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz unsigned vendor_id, chip_id; 208d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz int ret, i; 209d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz 210d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz ret = linux_get_pciid_from_fd(fd, &vendor_id, &chip_id); 211d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz if (ret) 212d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz return ret; 213d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz 214d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz for (i = 0; table[i].func; i++) 215d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz if (table[i].vendor == vendor_id && table[i].chip == chip_id) 216d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz return table[i].func(fd, out); 217d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz 218d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz return -ENOSYS; 219d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz} 220d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz#else 221d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantzstatic int 222d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantzlinux_from_udev(int fd, struct kms_driver **out) 223d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz{ 224d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz return -ENOSYS; 225d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz} 226d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz#endif 227d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz 228d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantzint 229d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantzlinux_create(int fd, struct kms_driver **out) 230d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz{ 231bb994653667986757b4c906b8f144737667f7374Dave Airlie if (!dumb_create(fd, out)) 232bb994653667986757b4c906b8f144737667f7374Dave Airlie return 0; 233bb994653667986757b4c906b8f144737667f7374Dave Airlie 234d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz if (!linux_from_udev(fd, out)) 235d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz return 0; 236d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz 237d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz return linux_from_sysfs(fd, out); 238d920fa9d0b54873d53f03a006d0fe3df11136b74Jakob Bornecrantz} 239