libdrm: Add get_sysctl_pci_bus_info for FreeBSD

The FreeBSD drm driver expose a sysctl hw.dri.%d.busid which contain
the busid.
Use this sysctl to parse the busid information based on the major/minor
that allow us to implement FreeBSD support for drmParsePciBusInfo.

Signed-off-by: Emmanuel Vadot <manu@FreeBSD.org>
Reviewed-by: Eric Engestrom <eric@engestrom.ch>
Reviewed-by: Emil Velikov <emil.velikov@collabora.com>
main
Emmanuel Vadot 2020-01-21 18:49:11 +01:00 committed by Emmanuel Vadot
parent bb584b8fd2
commit 379113724f
1 changed files with 65 additions and 0 deletions

View File

@ -57,6 +57,9 @@
#ifdef MAJOR_IN_SYSMACROS #ifdef MAJOR_IN_SYSMACROS
#include <sys/sysmacros.h> #include <sys/sysmacros.h>
#endif #endif
#if HAVE_SYS_SYSCTL_H
#include <sys/sysctl.h>
#endif
#include <math.h> #include <math.h>
#if defined(__FreeBSD__) #if defined(__FreeBSD__)
@ -3133,6 +3136,66 @@ get_pci_path(int maj, int min, char *pci_path)
*term = 0; *term = 0;
} }
#ifdef __FreeBSD__
static int get_sysctl_pci_bus_info(int maj, int min, drmPciBusInfoPtr info)
{
char dname[SPECNAMELEN];
char sysctl_name[16];
char sysctl_val[256];
size_t sysctl_len;
int id, type, nelem;
unsigned int rdev, majmin, domain, bus, dev, func;
rdev = makedev(maj, min);
if (!devname_r(rdev, S_IFCHR, dname, sizeof(dname)))
return -EINVAL;
if (sscanf(dname, "drm/%d\n", &id) != 1)
return -EINVAL;
type = drmGetMinorType(maj, min);
if (type == -1)
return -EINVAL;
/* BUG: This above section is iffy, since it mandates that a driver will
* create both card and render node.
* If it does not, the next DRM device will create card#X and
* renderD#(128+X)-1.
* This is a possibility in FreeBSD but for now there is no good way for
* obtaining the info.
*/
switch (type) {
case DRM_NODE_PRIMARY:
break;
case DRM_NODE_CONTROL:
id -= 64;
break;
case DRM_NODE_RENDER:
id -= 128;
break;
}
if (id < 0)
return -EINVAL;
if (snprintf(sysctl_name, sizeof(sysctl_name), "hw.dri.%d.busid", id) <= 0)
return -EINVAL;
sysctl_len = sizeof(sysctl_val);
if (sysctlbyname(sysctl_name, sysctl_val, &sysctl_len, NULL, 0))
return -EINVAL;
#define bus_fmt "pci:%04x:%02x:%02x.%u"
nelem = sscanf(sysctl_val, bus_fmt, &domain, &bus, &dev, &func);
if (nelem != 4)
return -EINVAL;
info->domain = domain;
info->bus = bus;
info->dev = dev;
info->func = func;
return 0;
}
#endif
static int drmParsePciBusInfo(int maj, int min, drmPciBusInfoPtr info) static int drmParsePciBusInfo(int maj, int min, drmPciBusInfoPtr info)
{ {
#ifdef __linux__ #ifdef __linux__
@ -3182,6 +3245,8 @@ static int drmParsePciBusInfo(int maj, int min, drmPciBusInfoPtr info)
info->func = pinfo.func; info->func = pinfo.func;
return 0; return 0;
#elif __FreeBSD__
return get_sysctl_pci_bus_info(maj, min, info);
#else #else
#warning "Missing implementation of drmParsePciBusInfo" #warning "Missing implementation of drmParsePciBusInfo"
return -EINVAL; return -EINVAL;