接前一篇文章: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 = 0stats->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接口的版本号。此函数在后文具体讲解函数的时候进行详细解析。在此先认识一下、有个印象就好。
其余宏定义将在后续文章中继续解析。