libdrm全解析十七 —— 源码全解析(14)

接前一篇文章:libdrm全解析十六 —— 源码全解析(13)

本文参考以下博文:

DRM 驱动程序开发(VKMS)

特此致谢!

本文继续对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虚拟地址空间。此函数在后文具体讲解函数的时候进行详细解析。在此先认识一下、有个印象就好。

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

猜你喜欢

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