libdrm全解析五 —— 源码全解析(2)

接前一篇文章:libdrm全解析四 —— 源码全解析(1)

本文参考以下博文:

DRM 驱动程序开发(VKMS)

Linux内核中_IO,_IOR,_IOW,_IOWR宏的用法与解析

特此致谢!

上一篇文章深入讲解了include/drm/drm.h中的几个基础宏定义。再次贴出代码如下:

#define DRM_IOCTL_BASE			'd'
#define DRM_IO(nr)			_IO(DRM_IOCTL_BASE,nr)
#define DRM_IOR(nr,type)		_IOR(DRM_IOCTL_BASE,nr,type)
#define DRM_IOW(nr,type)		_IOW(DRM_IOCTL_BASE,nr,type)
#define DRM_IOWR(nr,type)		_IOWR(DRM_IOCTL_BASE,nr,type)

本文开始逐个讲解具有实际意义的宏。

1. DRM_IOCTL_VERSION

第1个宏是DRM_IOCTL_VERSION,相应代码如下:

#define DRM_IOCTL_VERSION		DRM_IOWR(0x00, struct drm_version)

结合上一篇文章中的_IOWR(type,nr,size)的最终定义,得到如下代码:

#define DRM_IOCTL_VERSION		( ((3)  << 30) | (('d') << 8) | ((0x00)   << 0) | ((sizeof(struct drm_version)) << 16) )

struct drm_version在同文件(include/drm/drm.h)中定义,代码如下:

/*
 * DRM_IOCTL_VERSION ioctl argument type.
 *
 * \sa drmGetVersion().
 */
struct drm_version {
	int version_major;	  /**< Major version */
	int version_minor;	  /**< Minor version */
	int version_patchlevel;	  /**< Patch level */
	__kernel_size_t name_len;	  /**< Length of name buffer */
	char *name;	  /**< Name of driver */
	__kernel_size_t date_len;	  /**< Length of date buffer */
	char *date;	  /**< User-space buffer to hold date */
	__kernel_size_t desc_len;	  /**< Length of desc buffer */
	char *desc;	  /**< User-space buffer to hold desc */
};

drm_version结构中的各成员的意义代码注释描述得很清楚了,在此无需赘述。

DRM_IOCTL_VERSION对应的Userspace API为:drmGetVersion()。该函数在xf86drm.c中,代码如下:

/**
 * Query the driver version information.
 *
 * \param fd file descriptor.
 *
 * \return pointer to a drmVersion structure which should be freed with
 * drmFreeVersion().
 *
 * \note Similar information is available via /proc/dri.
 *
 * \internal
 * It gets the version information via successive DRM_IOCTL_VERSION ioctls,
 * first with zeros to get the string lengths, and then the actually strings.
 * It also null-terminates them since they might not be already.
 */
drm_public drmVersionPtr drmGetVersion(int fd)
{
    drmVersionPtr retval;
    drm_version_t *version = drmMalloc(sizeof(*version));

    if (drmIoctl(fd, DRM_IOCTL_VERSION, version)) {
        drmFreeKernelVersion(version);
        return NULL;
    }

    if (version->name_len)
        version->name    = drmMalloc(version->name_len + 1);
    if (version->date_len)
        version->date    = drmMalloc(version->date_len + 1);
    if (version->desc_len)
        version->desc    = drmMalloc(version->desc_len + 1);

    if (drmIoctl(fd, DRM_IOCTL_VERSION, version)) {
        drmMsg("DRM_IOCTL_VERSION: %s\n", strerror(errno));
        drmFreeKernelVersion(version);
        return NULL;
    }

    /* The results might not be null-terminated strings, so terminate them. */
    if (version->name_len) version->name[version->name_len] = '\0';
    if (version->date_len) version->date[version->date_len] = '\0';
    if (version->desc_len) version->desc[version->desc_len] = '\0';

    retval = drmMalloc(sizeof(*retval));
    drmCopyVersion(retval, version);
    drmFreeKernelVersion(version);
    return retval;
}

函数的作用是获取Driver版本信息,即上面的name、desc、date、major、minor字段。此函数在后文具体讲解函数的时候进行详细解析。在此先认识一下、有个印象就好。

2. DRM_IOCTL_GET_UNIQUE

第2个宏是DRM_IOCTL_GET_UNIQUE,相应代码如下:

#define DRM_IOCTL_GET_UNIQUE		DRM_IOWR(0x01, struct drm_unique)

结合上一篇文章中的_IOWR(type,nr,size)的最终定义,得到如下代码:

#define DRM_IOCTL_GET_UNIQUE		( ((3)  << 30) | (('d') << 8) | ((0x01)   << 0) | ((sizeof(struct drm_unique)) << 16) )

struct drm_unique在同文件(include/drm/drm.h)中定义,代码如下:

/*
 * DRM_IOCTL_GET_UNIQUE ioctl argument type.
 *
 * \sa drmGetBusid() and drmSetBusId().
 */
struct drm_unique {
	__kernel_size_t unique_len;	  /**< Length of unique */
	char *unique;	  /**< Unique name for driver instantiation */
};

drm_unique结构中的各成员的意义代码注释描述得很清楚了,在此无需赘述。

DRM_IOCTL_GET_UNIQUE对应的Userspace API为:drmGetBusid()。该函数也是在xf86drm.c中,代码如下:

/**
 * Get the bus ID of the device.
 *
 * \param fd file descriptor.
 *
 * \return bus ID string.
 *
 * \internal
 * This function gets the bus ID via successive DRM_IOCTL_GET_UNIQUE ioctls to
 * get the string length and data, passing the arguments in a drm_unique
 * structure.
 */
drm_public char *drmGetBusid(int fd)
{
    drm_unique_t u;

    memclear(u);

    if (drmIoctl(fd, DRM_IOCTL_GET_UNIQUE, &u))
        return NULL;
    u.unique = drmMalloc(u.unique_len + 1);
    if (drmIoctl(fd, DRM_IOCTL_GET_UNIQUE, &u)) {
        drmFree(u.unique);
        return NULL;
    }
    u.unique[u.unique_len] = '\0';

    return u.unique;
}

函数的作用是获取Bus ID。此函数在后文具体讲解函数的时候进行详细解析。在此先认识一下、有个印象就好。

其余宏定义将在后续文章中继续解析。

猜你喜欢

转载自blog.csdn.net/phmatthaus/article/details/132458926