libdrm全解析十五 —— 源码全解析(12)

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

本文参考以下博文:

DRM 驱动程序开发(VKMS)

特此致谢!

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

19. DRM_IOCTL_CONTROL

第19个宏是DRM_IOCTL_CONTROL,相应代码如下:

#define DRM_IOCTL_CONTROL		DRM_IOW( 0x14, struct drm_control)

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

#define DRM_IOCTL_CONTROL		( ((1)  << 30) | (('d') << 8) | ((0x14)   << 0) | ((sizeof(struct drm_control)) << 16) )

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

/*
 * DRM_IOCTL_CONTROL ioctl argument type.
 *
 * \sa drmCtlInstHandler() and drmCtlUninstHandler().
 */
struct drm_control {
	enum {
		DRM_ADD_COMMAND,
		DRM_RM_COMMAND,
		DRM_INST_HANDLER,
		DRM_UNINST_HANDLER
	} func;
	int irq;
};

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

/**
 * Uninstall IRQ handler.
 *
 * \param fd file descriptor.
 *
 * \return zero on success, or a negative value on failure.
 *
 * \internal
 * This function is a wrapper around the DRM_IOCTL_CONTROL ioctl, passing the
 * argument in a drm_control structure.
 */
drm_public int drmCtlUninstHandler(int fd)
{
    drm_control_t ctl;

    memclear(ctl);
    ctl.func  = DRM_UNINST_HANDLER;
    ctl.irq   = 0;
    if (drmIoctl(fd, DRM_IOCTL_CONTROL, &ctl))
        return -errno;
    return 0;
}

函数的作用是卸载中断(IRQ)处理。此函数在后文具体讲解函数的时候进行详细解析。在此先认识一下、有个印象就好。

20. DRM_IOCTL_ADD_MAP

第20个宏是DRM_IOCTL_ADD_MAP,相应代码如下:

#define DRM_IOCTL_ADD_MAP		DRM_IOWR(0x15, struct drm_map)

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

#define DRM_IOCTL_ADD_MAP		( ((3)  << 30) | (('d') << 8) | ((0x15)   << 0) | ((sizeof(struct drm_map)) << 16) )

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

/*
 * DRM_IOCTL_GET_MAP, DRM_IOCTL_ADD_MAP and DRM_IOCTL_RM_MAP ioctls
 * argument type.
 *
 * \sa drmAddMap().
 */
struct drm_map {
	unsigned long offset;	 /**< Requested physical address (0 for SAREA)*/
	unsigned long size;	 /**< Requested physical size (bytes) */
	enum drm_map_type type;	 /**< Type of memory to map */
	enum drm_map_flags flags;	 /**< Flags */
	void *handle;		 /**< User-space: "Handle" to pass to mmap() */
				 /**< Kernel-space: kernel-virtual address */
	int mtrr;		 /**< MTRR slot used */
	/*   Private data */
};

drm_map_type和drm_map_flags的定义都是在上边,分别如下:

/*
 * Type of memory to map.
 */
enum drm_map_type {
	_DRM_FRAME_BUFFER = 0,	  /**< WC (no caching), no core dump */
	_DRM_REGISTERS = 1,	  /**< no caching, no core dump */
	_DRM_SHM = 2,		  /**< shared, cached */
	_DRM_AGP = 3,		  /**< AGP/GART */
	_DRM_SCATTER_GATHER = 4,  /**< Scatter/gather memory for PCI DMA */
	_DRM_CONSISTENT = 5	  /**< Consistent memory for PCI DMA */
};

/*
 * Memory mapping flags.
 */
enum drm_map_flags {
	_DRM_RESTRICTED = 0x01,	     /**< Cannot be mapped to user-virtual */
	_DRM_READ_ONLY = 0x02,
	_DRM_LOCKED = 0x04,	     /**< shared, cached, locked */
	_DRM_KERNEL = 0x08,	     /**< kernel requires access */
	_DRM_WRITE_COMBINING = 0x10, /**< use write-combining if available */
	_DRM_CONTAINS_LOCK = 0x20,   /**< SHM page that contains lock */
	_DRM_REMOVABLE = 0x40,	     /**< Removable mapping */
	_DRM_DRIVER = 0x80	     /**< Managed by driver */
};

drm_map结构中各成员的意义代码注释描述得很清楚了,在此无需赘述。

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

/**
 * Specifies a range of memory that is available for mapping by a
 * non-root process.
 *
 * \param fd file descriptor.
 * \param offset usually the physical address. The actual meaning depends of
 * the \p type parameter. See below.
 * \param size of the memory in bytes.
 * \param type type of the memory to be mapped.
 * \param flags combination of several flags to modify the function actions.
 * \param handle will be set to a value that may be used as the offset
 * parameter for mmap().
 *
 * \return zero on success or a negative value on error.
 *
 * \par Mapping the frame buffer
 * For the frame buffer
 * - \p offset will be the physical address of the start of the frame buffer,
 * - \p size will be the size of the frame buffer in bytes, and
 * - \p type will be DRM_FRAME_BUFFER.
 *
 * \par
 * The area mapped will be uncached. If MTRR support is available in the
 * kernel, the frame buffer area will be set to write combining.
 *
 * \par Mapping the MMIO register area
 * For the MMIO register area,
 * - \p offset will be the physical address of the start of the register area,
 * - \p size will be the size of the register area bytes, and
 * - \p type will be DRM_REGISTERS.
 * \par
 * The area mapped will be uncached.
 *
 * \par Mapping the SAREA
 * For the SAREA,
 * - \p offset will be ignored and should be set to zero,
 * - \p size will be the desired size of the SAREA in bytes,
 * - \p type will be DRM_SHM.
 *
 * \par
 * A shared memory area of the requested size will be created and locked in
 * kernel memory. This area may be mapped into client-space by using the handle
 * returned.
 *
 * \note May only be called by root.
 *
 * \internal
 * This function is a wrapper around the DRM_IOCTL_ADD_MAP ioctl, passing
 * the arguments in a drm_map structure.
 */
drm_public int drmAddMap(int fd, drm_handle_t offset, drmSize size, drmMapType type,
                         drmMapFlags flags, drm_handle_t *handle)
{
    drm_map_t map;

    memclear(map);
    map.offset  = offset;
    map.size    = size;
    map.type    = (enum drm_map_type)type;
    map.flags   = (enum drm_map_flags)flags;
    if (drmIoctl(fd, DRM_IOCTL_ADD_MAP, &map))
        return -errno;
    if (handle)
        *handle = (drm_handle_t)(uintptr_t)map.handle;
    return 0;
}

函数的作用是添加内存映射(map)。此函数在后文具体讲解函数的时候进行详细解析。在此先认识一下、有个印象就好。

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

猜你喜欢

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