接前一篇文章:libdrm全解析七 —— 源码全解析(4)
本文参考以下博文:
特此致谢!
本文继续对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接口的版本号。此函数在后文具体讲解函数的时候进行详细解析。在此先认识一下、有个印象就好。
其余宏定义将在后续文章中继续解析。