接前一篇文章:libdrm全解析十六 —— 源码全解析(13)
本文参考以下博文:
特此致谢!
本文继续对include/drm/drm.h中实际功能宏定义进行讲解。
23. DRM_IOCTL_INFO_BUFS
第23个宏是DRM_IOCTL_INFO_BUFS,相应代码如下:
#define DRM_IOCTL_INFO_BUFS DRM_IOWR(0x18, struct drm_buf_info)
结合之前文章中的_IOWR(type,nr,size)的最终定义,得到如下代码:
#define DRM_IOCTL_INFO_BUFS ( ((3) << 30) | (('d') << 8) | ((0x18) << 0) | ((sizeof(struct drm_buf_info)) << 16) )
struct drm_buf_info在同文件(include/drm/drm.h)中定义,代码如下:
/*
* DRM_IOCTL_INFO_BUFS ioctl argument type.
*/
struct drm_buf_info {
int count; /**< Entries in list */
struct drm_buf_desc *list;
};
struct_buf_desc的定义就在上边,如下:
/*
* DRM_IOCTL_ADD_BUFS and DRM_IOCTL_MARK_BUFS ioctl argument type.
*
* \sa drmAddBufs().
*/
struct drm_buf_desc {
int count; /**< Number of buffers of this size */
int size; /**< Size in bytes */
int low_mark; /**< Low water mark */
int high_mark; /**< High water mark */
enum {
_DRM_PAGE_ALIGN = 0x01, /**< Align on page boundaries for DMA */
_DRM_AGP_BUFFER = 0x02, /**< Buffer is in AGP space */
_DRM_SG_BUFFER = 0x04, /**< Scatter/gather memory buffer */
_DRM_FB_BUFFER = 0x08, /**< Buffer is in frame buffer */
_DRM_PCI_BUFFER_RO = 0x10 /**< Map PCI DMA buffer read-only */
} flags;
unsigned long agp_start; /**<
* Start address of where the AGP buffers are
* in the AGP aperture
*/
};
drm_buf_info和drm_buf_desc结构中各成员的意义代码注释描述得很清楚了,在此无需赘述。
DRM_IOCTL_INFO_BUFS对应的Userspace API为:drmMarkBufs()和drmGetBufInfo()。这两个函数也是在xf86drm.c中,代码分别如下:
drm_public int drmMarkBufs(int fd, double low, double high)
{
drm_buf_info_t info;
int i;
memclear(info);
if (drmIoctl(fd, DRM_IOCTL_INFO_BUFS, &info))
return -EINVAL;
if (!info.count)
return -EINVAL;
if (!(info.list = drmMalloc(info.count * sizeof(*info.list))))
return -ENOMEM;
if (drmIoctl(fd, DRM_IOCTL_INFO_BUFS, &info)) {
int retval = -errno;
drmFree(info.list);
return retval;
}
for (i = 0; i < info.count; i++) {
info.list[i].low_mark = low * info.list[i].count;
info.list[i].high_mark = high * info.list[i].count;
if (drmIoctl(fd, DRM_IOCTL_MARK_BUFS, &info.list[i])) {
int retval = -errno;
drmFree(info.list);
return retval;
}
}
drmFree(info.list);
return 0;
}
drm_public drmBufInfoPtr drmGetBufInfo(int fd)
{
drm_buf_info_t info;
drmBufInfoPtr retval;
int i;
memclear(info);
if (drmIoctl(fd, DRM_IOCTL_INFO_BUFS, &info))
return NULL;
if (info.count) {
if (!(info.list = drmMalloc(info.count * sizeof(*info.list))))
return NULL;
if (drmIoctl(fd, DRM_IOCTL_INFO_BUFS, &info)) {
drmFree(info.list);
return NULL;
}
retval = drmMalloc(sizeof(*retval));
retval->count = info.count;
if (!(retval->list = drmMalloc(info.count * sizeof(*retval->list)))) {
drmFree(retval);
drmFree(info.list);
return NULL;
}
for (i = 0; i < info.count; i++) {
retval->list[i].count = info.list[i].count;
retval->list[i].size = info.list[i].size;
retval->list[i].low_mark = info.list[i].low_mark;
retval->list[i].high_mark = info.list[i].high_mark;
}
drmFree(info.list);
return retval;
}
return NULL;
}
这两个函数在后文具体讲解函数的时候进行详细解析。在此先认识一下、有个印象就好。
24. DRM_IOCTL_MAP_BUFS
第24个宏是DRM_IOCTL_MAP_BUFS,相应代码如下:
#define DRM_IOCTL_MAP_BUFS DRM_IOWR(0x19, struct drm_buf_map)
结合之前文章中的_IOWR(type,nr,size)的最终定义,得到如下代码:
#define DRM_IOCTL_MAP_BUFS ( ((3) << 30) | (('d') << 8) | ((0x19) << 0) | ((sizeof(struct drm_buf_map)) << 16) )
struct drm_buf_map在同文件(include/drm/drm.h)中定义,代码如下:
/*
* DRM_IOCTL_MAP_BUFS ioctl argument type.
*/
struct drm_buf_map {
int count; /**< Length of the buffer list */
#ifdef __cplusplus
void *virt;
#else
void *virtual; /**< Mmap'd area in user-virtual */
#endif
struct drm_buf_pub *list; /**< Buffer information */
};
struct drm_buf_pub的定义就在上边,代码如下:
/*
* Buffer information
*
* \sa drm_buf_map.
*/
struct drm_buf_pub {
int idx; /**< Index into the master buffer list */
int total; /**< Buffer size */
int used; /**< Amount of buffer in use (for DMA) */
void *address; /**< Address of buffer */
};
drm_buf_map和drm_buf_pub结构中各成员的意义代码注释描述得很清楚了,在此无需赘述。
DRM_IOCTL_MAP_BUFS对应的Userspace API为:drmMapBufs()。该函数也是在xf86drm.c中,代码如下:
/**
* Map all DMA buffers into client-virtual space.
*
* \param fd file descriptor.
*
* \return a pointer to a ::drmBufMap structure.
*
* \note The client may not use these buffers until obtaining buffer indices
* with drmDMA().
*
* \internal
* This function calls the DRM_IOCTL_MAP_BUFS ioctl and copies the returned
* information about the buffers in a drm_buf_map structure into the
* client-visible data structures.
*/
drm_public drmBufMapPtr drmMapBufs(int fd)
{
drm_buf_map_t bufs;
drmBufMapPtr retval;
int i;
memclear(bufs);
if (drmIoctl(fd, DRM_IOCTL_MAP_BUFS, &bufs))
return NULL;
if (!bufs.count)
return NULL;
if (!(bufs.list = drmMalloc(bufs.count * sizeof(*bufs.list))))
return NULL;
if (drmIoctl(fd, DRM_IOCTL_MAP_BUFS, &bufs)) {
drmFree(bufs.list);
return NULL;
}
retval = drmMalloc(sizeof(*retval));
retval->count = bufs.count;
retval->list = drmMalloc(bufs.count * sizeof(*retval->list));
for (i = 0; i < bufs.count; i++) {
retval->list[i].idx = bufs.list[i].idx;
retval->list[i].total = bufs.list[i].total;
retval->list[i].used = 0;
retval->list[i].address = bufs.list[i].address;
}
drmFree(bufs.list);
return retval;
}
函数的作用是映射所有DMA缓冲(buffers)到client虚拟地址空间。此函数在后文具体讲解函数的时候进行详细解析。在此先认识一下、有个印象就好。
其余宏定义将在后续文章中继续解析。