> Date: Wed, 23 Nov 2016 11:50:49 +1100
> From: Jonathan Gray <j...@jsg.id.au>
> 
> On Tue, Nov 22, 2016 at 09:29:03PM +0100, Mark Kettenis wrote:
> > > Date: Sat, 19 Nov 2016 19:31:18 +1100
> > > From: Jonathan Gray <j...@jsg.id.au>
> > > 
> > > Support libdrm functions required for Mesa versions >= 13.
> > > 
> > > On linux this information is pulled out of a psuedo filesystem, here the
> > > new DRM_IOCTL_GET_PCIINFO ioctl is used for the same.
> > > 
> > > Only primary drm nodes are handled, render and control nodes which we
> > > don't have aren't.  This also only handles devices with PCI ids.
> > > 
> > > drmGetMinorNameForFD() based on code the Mesa loader used to have.
> > 
> > See my reply to the kernel diff.  One nit...
> > 
> > > diff --git xf86drm.c xf86drm.c
> > > index 3c2c5d4..03fe257 100644
> > > --- xf86drm.c
> > > +++ xf86drm.c
> > > @@ -62,6 +62,10 @@
> > >  #endif
> > >  #include <math.h>
> > >  
> > > +#ifdef __OpenBSD__
> > > +#include <sys/pciio.h>
> > > +#endif
> > > +
> > >  /* Not all systems have MAP_FAILED defined */
> > >  #ifndef MAP_FAILED
> > >  #define MAP_FAILED ((void *)-1)
> > > @@ -2851,7 +2855,25 @@ static char *drmGetMinorNameForFD(int fd, int type)
> > >  out_close_dir:
> > >      closedir(sysdir);
> > >  #else
> > > -#warning "Missing implementation of drmGetMinorNameForFD"
> > > +    struct stat sbuf;
> > > +    unsigned int maj, min;
> > > +    char buf[0x40];
> > 
> > Any reason not to use PATH_MAX + 1 here?
> 
> This was carried over from the old Mesa loader code, updated diff to
> use PATH_MAX and inline ioctl definition:

ok kettenis@

> diff --git xf86drm.c xf86drm.c
> index 3c2c5d4..38f6440 100644
> --- xf86drm.c
> +++ xf86drm.c
> @@ -103,7 +103,23 @@
>  #endif
>  
>  #ifdef __OpenBSD__
> +
>  #define X_PRIVSEP
> +
> +struct drm_pciinfo {
> +     uint16_t        domain;
> +     uint8_t         bus;
> +     uint8_t         dev;
> +     uint8_t         func;
> +     uint16_t        vendor_id;
> +     uint16_t        device_id;
> +     uint16_t        subvendor_id;
> +     uint16_t        subdevice_id;
> +     uint8_t         revision_id;
> +};
> +
> +#define DRM_IOCTL_GET_PCIINFO        DRM_IOR(0x15, struct drm_pciinfo)
> +
>  #endif
>  
>  #define DRM_MSG_VERBOSITY 3
> @@ -2851,7 +2867,25 @@ static char *drmGetMinorNameForFD(int fd, int type)
>  out_close_dir:
>      closedir(sysdir);
>  #else
> -#warning "Missing implementation of drmGetMinorNameForFD"
> +    struct stat sbuf;
> +    unsigned int maj, min;
> +    char buf[PATH_MAX + 1];
> +    int n;
> +
> +    if (fstat(fd, &sbuf))
> +        return NULL;
> +
> +    maj = major(sbuf.st_rdev);
> +    min = minor(sbuf.st_rdev);
> +
> +    if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode))
> +        return NULL;
> +
> +    n = snprintf(buf, sizeof(buf), DRM_DEV_NAME, DRM_DIR_NAME, min);
> +    if (n == -1 || n >= sizeof(buf))
> +        return NULL;
> +
> +    return strdup(buf);
>  #endif
>      return NULL;
>  }
> @@ -2887,6 +2921,8 @@ static int drmParseSubsystemType(int maj, int min)
>          return DRM_BUS_PCI;
>  
>      return -EINVAL;
> +#elif defined(__OpenBSD__)
> +     return DRM_BUS_PCI;
>  #else
>  #warning "Missing implementation of drmParseSubsystemType"
>      return -EINVAL;
> @@ -2929,6 +2965,26 @@ static int drmParsePciBusInfo(int maj, int min, 
> drmPciBusInfoPtr info)
>      info->func = func;
>  
>      return 0;
> +#elif defined(__OpenBSD__)
> +    struct drm_pciinfo pinfo;
> +    int fd;
> +
> +    fd = drmOpenMinor(min, 0, DRM_NODE_PRIMARY);
> +    if (fd < 0)
> +        return -errno;
> +
> +    if (drmIoctl(fd, DRM_IOCTL_GET_PCIINFO, &pinfo)) {
> +        close(fd);
> +        return -errno;
> +    }
> +    close(fd);
> +
> +    info->domain = pinfo.domain;
> +    info->bus = pinfo.bus;
> +    info->dev = pinfo.dev;
> +    info->func = pinfo.func;
> +
> +    return 0;
>  #else
>  #warning "Missing implementation of drmParsePciBusInfo"
>      return -EINVAL;
> @@ -3004,6 +3060,37 @@ static int drmParsePciDeviceInfo(const char *d_name,
>      device->subdevice_id = config[46] | (config[47] << 8);
>  
>      return 0;
> +#elif defined(__OpenBSD__)
> +    struct drm_pciinfo pinfo;
> +    char buf[PATH_MAX + 1];
> +    int fd, n;
> +
> +    n = snprintf(buf, sizeof(buf), "%s/%s", DRM_DIR_NAME, d_name);
> +    if (n == -1 || n >= sizeof(buf))
> +        return -errno;
> +
> +#ifndef X_PRIVSEP
> +    fd = open(buf, O_RDWR, 0);
> +#else
> +    fd = priv_open_device(buf);
> +#endif
> +
> +    if (fd < 0)
> +        return -errno;
> +
> +    if (drmIoctl(fd, DRM_IOCTL_GET_PCIINFO, &pinfo)) {
> +        close(fd);
> +        return -errno;
> +    }
> +    close(fd);
> +
> +    device->vendor_id = pinfo.vendor_id;
> +    device->device_id = pinfo.device_id;
> +    device->revision_id = pinfo.revision_id;
> +    device->subvendor_id = pinfo.subvendor_id;
> +    device->subdevice_id = pinfo.subdevice_id;
> +
> +    return 0;
>  #else
>  #warning "Missing implementation of drmParsePciDeviceInfo"
>      return -EINVAL;
> @@ -3117,6 +3204,46 @@ static void drmFoldDuplicatedDevices(drmDevicePtr 
> local_devices[], int count)
>   */
>  int drmGetDevice(int fd, drmDevicePtr *device)
>  {
> +#ifdef __OpenBSD__
> +    drmDevicePtr d;
> +    struct stat sbuf;
> +    char node[PATH_MAX + 1];
> +    char d_name[PATH_MAX + 1];
> +    int maj, min, n;
> +    int ret;
> +    int max_count = 1;
> +
> +    if (fd == -1 || device == NULL)
> +        return -EINVAL;
> +
> +    if (fstat(fd, &sbuf))
> +        return -errno;
> +
> +    maj = major(sbuf.st_rdev);
> +    min = minor(sbuf.st_rdev);
> +
> +    if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode))
> +        return -EINVAL;
> +
> +    n = snprintf(d_name, PATH_MAX, "drm%d", min);
> +    if (n == -1 || n >= PATH_MAX)
> +      return -errno;
> +
> +    n = snprintf(node, PATH_MAX, DRM_DEV_NAME, DRM_DIR_NAME, min);
> +    if (n == -1 || n >= PATH_MAX)
> +      return -errno;
> +    if (stat(node, &sbuf))
> +        return -EINVAL;
> +
> +    ret = drmProcessPciDevice(&d, d_name, node, DRM_NODE_PRIMARY,
> +                           maj, min, true);
> +    if (ret)
> +        return ret;
> +
> +    *device = d;
> +
> +    return 0;
> +#else
>      drmDevicePtr *local_devices;
>      drmDevicePtr d;
>      DIR *sysdir;
> @@ -3224,6 +3351,7 @@ free_devices:
>  free_locals:
>      free(local_devices);
>      return ret;
> +#endif
>  }
>  
>  /**
> 

Reply via email to