libdrm全解析八 —— 源码全解析(5)

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

本文参考以下博文:

DRM 驱动程序开发(VKMS)

特此致谢!

 本文继续对include/drm/drm.h中实际功能宏定义进行讲解。

7. DRM_IOCTL_GET_STATS

第7个宏是DRM_IOCTL_GET_STATS,相应代码如下:

#define DRM_IOCTL_GET_STATS             DRM_IOR( 0x06, struct drm_stats)

结合之前文章中的_IOR(type,nr,size)的最终定义,得到如下代码:

#define DRM_IOCTL_GET_STATS		( ((2)  << 30) | (('d') << 8) | ((0x06)   << 0) | ((sizeof(struct drm_stats)) << 16) )

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

/*
 * DRM_IOCTL_GET_STATS ioctl argument type.
 */
struct drm_stats {
	unsigned long count;
	struct {
		unsigned long value;
		enum drm_stat_type type;
	} data[15];
};

drm_stat_type的定义就在上边,代码如下:

enum drm_stat_type {
	_DRM_STAT_LOCK,
	_DRM_STAT_OPENS,
	_DRM_STAT_CLOSES,
	_DRM_STAT_IOCTLS,
	_DRM_STAT_LOCKS,
	_DRM_STAT_UNLOCKS,
	_DRM_STAT_VALUE,	/**< Generic value */
	_DRM_STAT_BYTE,		/**< Generic byte counter (1024bytes/K) */个
	_DRM_STAT_COUNT,	/**< Generic non-byte counter (1000/k) */

	_DRM_STAT_IRQ,		/**< IRQ */
	_DRM_STAT_PRIMARY,	/**< Primary DMA bytes */
	_DRM_STAT_SECONDARY,	/**< Secondary DMA bytes */
	_DRM_STAT_DMA,		/**< DMA */
	_DRM_STAT_SPECIAL,	/**< Special DMA (e.g., priority or polled) */
	_DRM_STAT_MISSED	/**< Missed DMA opportunity */
	    /* Add to the *END* of the list */
};

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

drm_public int drmGetStats(int fd, drmStatsT *stats)
{
    drm_stats_t s;
    unsigned    i;

    memclear(s);
    if (drmIoctl(fd, DRM_IOCTL_GET_STATS, &s))
        return -errno;

    stats->count = 0;
    memset(stats, 0, sizeof(*stats));
    if (s.count > sizeof(stats->data)/sizeof(stats->data[0]))
        return -1;

#define SET_VALUE                              \
    stats->data[i].long_format = "%-20.20s";   \
    stats->data[i].rate_format = "%8.8s";      \
    stats->data[i].isvalue     = 1;            \
    stats->data[i].verbose     = 0

#define SET_COUNT                              \
    stats->data[i].long_format = "%-20.20s";   \
    stats->data[i].rate_format = "%5.5s";      \
    stats->data[i].isvalue     = 0;            \
    stats->data[i].mult_names  = "kgm";        \
    stats->data[i].mult        = 1000;         \
    stats->data[i].verbose     = 0

#define SET_BYTE                               \
    stats->data[i].long_format = "%-20.20s";   \
    stats->data[i].rate_format = "%5.5s";      \
    stats->data[i].isvalue     = 0;            \
    stats->data[i].mult_names  = "KGM";        \
    stats->data[i].mult        = 1024;         \
    stats->data[i].verbose     = 0


    stats->count = s.count;
    for (i = 0; i < s.count; i++) {
        stats->data[i].value = s.data[i].value;
        switch (s.data[i].type) {
        case _DRM_STAT_LOCK:
            stats->data[i].long_name = "Lock";
            stats->data[i].rate_name = "Lock";
            SET_VALUE;
            break;
        case _DRM_STAT_OPENS:
            stats->data[i].long_name = "Opens";
            stats->data[i].rate_name = "O";
            SET_COUNT;
            stats->data[i].verbose   = 1;
            break;
        case _DRM_STAT_CLOSES:
            stats->data[i].long_name = "Closes";
            stats->data[i].rate_name = "Lock";
            SET_COUNT;
            stats->data[i].verbose   = 1;
            break;
        case _DRM_STAT_IOCTLS:
            stats->data[i].long_name = "Ioctls";
            stats->data[i].rate_name = "Ioc/s";
            SET_COUNT;
            break;
        case _DRM_STAT_LOCKS:
            stats->data[i].long_name = "Locks";
            stats->data[i].rate_name = "Lck/s";
            SET_COUNT;
            break;
        case _DRM_STAT_UNLOCKS:
            stats->data[i].long_name = "Unlocks";
            stats->data[i].rate_name = "Unl/s";
            SET_COUNT;
            break;
        case _DRM_STAT_IRQ:
            stats->data[i].long_name = "IRQs";
            stats->data[i].rate_name = "IRQ/s";
            SET_COUNT;
            break;
        case _DRM_STAT_PRIMARY:
            stats->data[i].long_name = "Primary Bytes";
            stats->data[i].rate_name = "PB/s";
            SET_BYTE;
            break;
        case _DRM_STAT_SECONDARY:
            stats->data[i].long_name = "Secondary Bytes";
            stats->data[i].rate_name = "SB/s";
            SET_BYTE;
            break;
        case _DRM_STAT_DMA:
            stats->data[i].long_name = "DMA";
            stats->data[i].rate_name = "DMA/s";
            SET_COUNT;
            break;
        case _DRM_STAT_SPECIAL:
            stats->data[i].long_name = "Special DMA";
            stats->data[i].rate_name = "dma/s";
            SET_COUNT;
            break;
        case _DRM_STAT_MISSED:
            stats->data[i].long_name = "Miss";
            stats->data[i].rate_name = "Ms/s";
            SET_COUNT;
            break;
        case _DRM_STAT_VALUE:
            stats->data[i].long_name = "Value";
            stats->data[i].rate_name = "Value";
            SET_VALUE;
            break;
        case _DRM_STAT_BYTE:
            stats->data[i].long_name = "Bytes";
            stats->data[i].rate_name = "B/s";
            SET_BYTE;
            break;
        case _DRM_STAT_COUNT:
        default:
            stats->data[i].long_name = "Count";
            stats->data[i].rate_name = "Cnt/s";
            SET_COUNT;
            break;
        }
    }
    return 0;
}

函数的作用是从中获取各种状态(stat)的相关信息,包括IRQs、DMA、Locks、Unlocks等等。此函数在后文具体讲解函数的时候进行详细解析。在此先认识一下、有个印象就好。

8. DRM_IOCTL_SET_VERSION

第8个宏是DRM_IOCTL_SET_VERSION,相应代码如下:

#define DRM_IOCTL_SET_VERSION		DRM_IOWR(0x07, struct drm_set_version)

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

#define DRM_IOCTL_SET_VERSION		( ((3)  << 30) | (('d') << 8) | ((0x07)   << 0) | ((sizeof(struct drm_set_version)) << 16) )

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

/*
 * DRM_IOCTL_SET_VERSION ioctl argument type.
 */
struct drm_set_version {
	int drm_di_major;
	int drm_di_minor;
	int drm_dd_major;
	int drm_dd_minor;
};

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

/**
 * Issue a set-version ioctl.
 *
 * \param fd file descriptor.
 * \param drmCommandIndex command index
 * \param data source pointer of the data to be read and written.
 * \param size size of the data to be read and written.
 *
 * \return zero on success, or a negative value on failure.
 *
 * \internal
 * It issues a read-write ioctl given by
 * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
 */
drm_public int drmSetInterfaceVersion(int fd, drmSetVersion *version)
{
    int retcode = 0;
    drm_set_version_t sv;

    memclear(sv);
    sv.drm_di_major = version->drm_di_major;
    sv.drm_di_minor = version->drm_di_minor;
    sv.drm_dd_major = version->drm_dd_major;
    sv.drm_dd_minor = version->drm_dd_minor;

    if (drmIoctl(fd, DRM_IOCTL_SET_VERSION, &sv)) {
        retcode = -errno;
    }

    version->drm_di_major = sv.drm_di_major;
    version->drm_di_minor = sv.drm_di_minor;
    version->drm_dd_major = sv.drm_dd_major;
    version->drm_dd_minor = sv.drm_dd_minor;

    return retcode;
}

函数的作用是设置当前DRM接口的版本号。此函数在后文具体讲解函数的时候进行详细解析。在此先认识一下、有个印象就好。

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

猜你喜欢

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