0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028 #include "vmwgfx_drv.h"
0029 #include "vmwgfx_devcaps.h"
0030 #include "vmwgfx_kms.h"
0031
0032 #include <drm/vmwgfx_drm.h>
0033 #include <linux/pci.h>
0034
0035 int vmw_getparam_ioctl(struct drm_device *dev, void *data,
0036 struct drm_file *file_priv)
0037 {
0038 struct vmw_private *dev_priv = vmw_priv(dev);
0039 struct drm_vmw_getparam_arg *param =
0040 (struct drm_vmw_getparam_arg *)data;
0041 struct vmw_fpriv *vmw_fp = vmw_fpriv(file_priv);
0042
0043 switch (param->param) {
0044 case DRM_VMW_PARAM_NUM_STREAMS:
0045 param->value = vmw_overlay_num_overlays(dev_priv);
0046 break;
0047 case DRM_VMW_PARAM_NUM_FREE_STREAMS:
0048 param->value = vmw_overlay_num_free_overlays(dev_priv);
0049 break;
0050 case DRM_VMW_PARAM_3D:
0051 param->value = vmw_supports_3d(dev_priv) ? 1 : 0;
0052 break;
0053 case DRM_VMW_PARAM_HW_CAPS:
0054 param->value = dev_priv->capabilities;
0055 break;
0056 case DRM_VMW_PARAM_HW_CAPS2:
0057 param->value = dev_priv->capabilities2;
0058 break;
0059 case DRM_VMW_PARAM_FIFO_CAPS:
0060 param->value = vmw_fifo_caps(dev_priv);
0061 break;
0062 case DRM_VMW_PARAM_MAX_FB_SIZE:
0063 param->value = dev_priv->max_primary_mem;
0064 break;
0065 case DRM_VMW_PARAM_FIFO_HW_VERSION:
0066 {
0067 if ((dev_priv->capabilities & SVGA_CAP_GBOBJECTS))
0068 param->value = SVGA3D_HWVERSION_WS8_B1;
0069 else
0070 param->value = vmw_fifo_mem_read(
0071 dev_priv,
0072 ((vmw_fifo_caps(dev_priv) &
0073 SVGA_FIFO_CAP_3D_HWVERSION_REVISED) ?
0074 SVGA_FIFO_3D_HWVERSION_REVISED :
0075 SVGA_FIFO_3D_HWVERSION));
0076 break;
0077 }
0078 case DRM_VMW_PARAM_MAX_SURF_MEMORY:
0079 if ((dev_priv->capabilities & SVGA_CAP_GBOBJECTS) &&
0080 !vmw_fp->gb_aware)
0081 param->value = dev_priv->max_mob_pages * PAGE_SIZE / 2;
0082 else
0083 param->value = dev_priv->memory_size;
0084 break;
0085 case DRM_VMW_PARAM_3D_CAPS_SIZE:
0086 param->value = vmw_devcaps_size(dev_priv, vmw_fp->gb_aware);
0087 break;
0088 case DRM_VMW_PARAM_MAX_MOB_MEMORY:
0089 vmw_fp->gb_aware = true;
0090 param->value = dev_priv->max_mob_pages * PAGE_SIZE;
0091 break;
0092 case DRM_VMW_PARAM_MAX_MOB_SIZE:
0093 param->value = dev_priv->max_mob_size;
0094 break;
0095 case DRM_VMW_PARAM_SCREEN_TARGET:
0096 param->value =
0097 (dev_priv->active_display_unit == vmw_du_screen_target);
0098 break;
0099 case DRM_VMW_PARAM_DX:
0100 param->value = has_sm4_context(dev_priv);
0101 break;
0102 case DRM_VMW_PARAM_SM4_1:
0103 param->value = has_sm4_1_context(dev_priv);
0104 break;
0105 case DRM_VMW_PARAM_SM5:
0106 param->value = has_sm5_context(dev_priv);
0107 break;
0108 case DRM_VMW_PARAM_GL43:
0109 param->value = has_gl43_context(dev_priv);
0110 break;
0111 case DRM_VMW_PARAM_DEVICE_ID:
0112 param->value = to_pci_dev(dev_priv->drm.dev)->device;
0113 break;
0114 default:
0115 return -EINVAL;
0116 }
0117
0118 return 0;
0119 }
0120
0121
0122 int vmw_get_cap_3d_ioctl(struct drm_device *dev, void *data,
0123 struct drm_file *file_priv)
0124 {
0125 struct drm_vmw_get_3d_cap_arg *arg =
0126 (struct drm_vmw_get_3d_cap_arg *) data;
0127 struct vmw_private *dev_priv = vmw_priv(dev);
0128 uint32_t size;
0129 void __user *buffer = (void __user *)((unsigned long)(arg->buffer));
0130 void *bounce = NULL;
0131 int ret;
0132 struct vmw_fpriv *vmw_fp = vmw_fpriv(file_priv);
0133
0134 if (unlikely(arg->pad64 != 0 || arg->max_size == 0)) {
0135 VMW_DEBUG_USER("Illegal GET_3D_CAP argument.\n");
0136 return -EINVAL;
0137 }
0138
0139 size = vmw_devcaps_size(dev_priv, vmw_fp->gb_aware);
0140 if (unlikely(size == 0)) {
0141 DRM_ERROR("Failed to figure out the devcaps size (no 3D).\n");
0142 return -ENOMEM;
0143 }
0144
0145 if (arg->max_size < size)
0146 size = arg->max_size;
0147
0148 bounce = vzalloc(size);
0149 if (unlikely(bounce == NULL)) {
0150 DRM_ERROR("Failed to allocate bounce buffer for 3D caps.\n");
0151 return -ENOMEM;
0152 }
0153
0154 ret = vmw_devcaps_copy(dev_priv, vmw_fp->gb_aware, bounce, size);
0155 if (unlikely (ret != 0))
0156 goto out_err;
0157
0158 ret = copy_to_user(buffer, bounce, size);
0159 if (ret)
0160 ret = -EFAULT;
0161 out_err:
0162 vfree(bounce);
0163
0164 if (unlikely(ret != 0))
0165 DRM_ERROR("Failed to report 3D caps info.\n");
0166
0167 return ret;
0168 }
0169
0170 int vmw_present_ioctl(struct drm_device *dev, void *data,
0171 struct drm_file *file_priv)
0172 {
0173 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
0174 struct vmw_private *dev_priv = vmw_priv(dev);
0175 struct drm_vmw_present_arg *arg =
0176 (struct drm_vmw_present_arg *)data;
0177 struct vmw_surface *surface;
0178 struct drm_vmw_rect __user *clips_ptr;
0179 struct drm_vmw_rect *clips = NULL;
0180 struct drm_framebuffer *fb;
0181 struct vmw_framebuffer *vfb;
0182 struct vmw_resource *res;
0183 uint32_t num_clips;
0184 int ret;
0185
0186 num_clips = arg->num_clips;
0187 clips_ptr = (struct drm_vmw_rect __user *)(unsigned long)arg->clips_ptr;
0188
0189 if (unlikely(num_clips == 0))
0190 return 0;
0191
0192 if (clips_ptr == NULL) {
0193 VMW_DEBUG_USER("Variable clips_ptr must be specified.\n");
0194 ret = -EINVAL;
0195 goto out_clips;
0196 }
0197
0198 clips = kcalloc(num_clips, sizeof(*clips), GFP_KERNEL);
0199 if (clips == NULL) {
0200 DRM_ERROR("Failed to allocate clip rect list.\n");
0201 ret = -ENOMEM;
0202 goto out_clips;
0203 }
0204
0205 ret = copy_from_user(clips, clips_ptr, num_clips * sizeof(*clips));
0206 if (ret) {
0207 DRM_ERROR("Failed to copy clip rects from userspace.\n");
0208 ret = -EFAULT;
0209 goto out_no_copy;
0210 }
0211
0212 drm_modeset_lock_all(dev);
0213
0214 fb = drm_framebuffer_lookup(dev, file_priv, arg->fb_id);
0215 if (!fb) {
0216 VMW_DEBUG_USER("Invalid framebuffer id.\n");
0217 ret = -ENOENT;
0218 goto out_no_fb;
0219 }
0220 vfb = vmw_framebuffer_to_vfb(fb);
0221
0222 ret = vmw_user_resource_lookup_handle(dev_priv, tfile, arg->sid,
0223 user_surface_converter,
0224 &res);
0225 if (ret)
0226 goto out_no_surface;
0227
0228 surface = vmw_res_to_srf(res);
0229 ret = vmw_kms_present(dev_priv, file_priv,
0230 vfb, surface, arg->sid,
0231 arg->dest_x, arg->dest_y,
0232 clips, num_clips);
0233
0234
0235 vmw_surface_unreference(&surface);
0236
0237 out_no_surface:
0238 drm_framebuffer_put(fb);
0239 out_no_fb:
0240 drm_modeset_unlock_all(dev);
0241 out_no_copy:
0242 kfree(clips);
0243 out_clips:
0244 return ret;
0245 }
0246
0247 int vmw_present_readback_ioctl(struct drm_device *dev, void *data,
0248 struct drm_file *file_priv)
0249 {
0250 struct vmw_private *dev_priv = vmw_priv(dev);
0251 struct drm_vmw_present_readback_arg *arg =
0252 (struct drm_vmw_present_readback_arg *)data;
0253 struct drm_vmw_fence_rep __user *user_fence_rep =
0254 (struct drm_vmw_fence_rep __user *)
0255 (unsigned long)arg->fence_rep;
0256 struct drm_vmw_rect __user *clips_ptr;
0257 struct drm_vmw_rect *clips = NULL;
0258 struct drm_framebuffer *fb;
0259 struct vmw_framebuffer *vfb;
0260 uint32_t num_clips;
0261 int ret;
0262
0263 num_clips = arg->num_clips;
0264 clips_ptr = (struct drm_vmw_rect __user *)(unsigned long)arg->clips_ptr;
0265
0266 if (unlikely(num_clips == 0))
0267 return 0;
0268
0269 if (clips_ptr == NULL) {
0270 VMW_DEBUG_USER("Argument clips_ptr must be specified.\n");
0271 ret = -EINVAL;
0272 goto out_clips;
0273 }
0274
0275 clips = kcalloc(num_clips, sizeof(*clips), GFP_KERNEL);
0276 if (clips == NULL) {
0277 DRM_ERROR("Failed to allocate clip rect list.\n");
0278 ret = -ENOMEM;
0279 goto out_clips;
0280 }
0281
0282 ret = copy_from_user(clips, clips_ptr, num_clips * sizeof(*clips));
0283 if (ret) {
0284 DRM_ERROR("Failed to copy clip rects from userspace.\n");
0285 ret = -EFAULT;
0286 goto out_no_copy;
0287 }
0288
0289 drm_modeset_lock_all(dev);
0290
0291 fb = drm_framebuffer_lookup(dev, file_priv, arg->fb_id);
0292 if (!fb) {
0293 VMW_DEBUG_USER("Invalid framebuffer id.\n");
0294 ret = -ENOENT;
0295 goto out_no_fb;
0296 }
0297
0298 vfb = vmw_framebuffer_to_vfb(fb);
0299 if (!vfb->bo) {
0300 VMW_DEBUG_USER("Framebuffer not buffer backed.\n");
0301 ret = -EINVAL;
0302 goto out_no_ttm_lock;
0303 }
0304
0305 ret = vmw_kms_readback(dev_priv, file_priv,
0306 vfb, user_fence_rep,
0307 clips, num_clips);
0308
0309 out_no_ttm_lock:
0310 drm_framebuffer_put(fb);
0311 out_no_fb:
0312 drm_modeset_unlock_all(dev);
0313 out_no_copy:
0314 kfree(clips);
0315 out_clips:
0316 return ret;
0317 }