radeon_ioc32.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395
  1. /**
  2. * \file radeon_ioc32.c
  3. *
  4. * 32-bit ioctl compatibility routines for the Radeon DRM.
  5. *
  6. * \author Paul Mackerras <paulus@samba.org>
  7. *
  8. * Copyright (C) Paul Mackerras 2005
  9. * All Rights Reserved.
  10. *
  11. * Permission is hereby granted, free of charge, to any person obtaining a
  12. * copy of this software and associated documentation files (the "Software"),
  13. * to deal in the Software without restriction, including without limitation
  14. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  15. * and/or sell copies of the Software, and to permit persons to whom the
  16. * Software is furnished to do so, subject to the following conditions:
  17. *
  18. * The above copyright notice and this permission notice (including the next
  19. * paragraph) shall be included in all copies or substantial portions of the
  20. * Software.
  21. *
  22. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  23. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  24. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  25. * THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  26. * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  27. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  28. * IN THE SOFTWARE.
  29. */
  30. #include <linux/compat.h>
  31. #include <linux/ioctl32.h>
  32. #include "drmP.h"
  33. #include "drm.h"
  34. #include "radeon_drm.h"
  35. #include "radeon_drv.h"
  36. typedef struct drm_radeon_init32 {
  37. int func;
  38. u32 sarea_priv_offset;
  39. int is_pci;
  40. int cp_mode;
  41. int gart_size;
  42. int ring_size;
  43. int usec_timeout;
  44. unsigned int fb_bpp;
  45. unsigned int front_offset, front_pitch;
  46. unsigned int back_offset, back_pitch;
  47. unsigned int depth_bpp;
  48. unsigned int depth_offset, depth_pitch;
  49. u32 fb_offset;
  50. u32 mmio_offset;
  51. u32 ring_offset;
  52. u32 ring_rptr_offset;
  53. u32 buffers_offset;
  54. u32 gart_textures_offset;
  55. } drm_radeon_init32_t;
  56. static int compat_radeon_cp_init(struct file *file, unsigned int cmd,
  57. unsigned long arg)
  58. {
  59. drm_radeon_init32_t init32;
  60. drm_radeon_init_t __user *init;
  61. if (copy_from_user(&init32, (void __user *)arg, sizeof(init32)))
  62. return -EFAULT;
  63. init = compat_alloc_user_space(sizeof(*init));
  64. if (!access_ok(VERIFY_WRITE, init, sizeof(*init))
  65. || __put_user(init32.func, &init->func)
  66. || __put_user(init32.sarea_priv_offset, &init->sarea_priv_offset)
  67. || __put_user(init32.is_pci, &init->is_pci)
  68. || __put_user(init32.cp_mode, &init->cp_mode)
  69. || __put_user(init32.gart_size, &init->gart_size)
  70. || __put_user(init32.ring_size, &init->ring_size)
  71. || __put_user(init32.usec_timeout, &init->usec_timeout)
  72. || __put_user(init32.fb_bpp, &init->fb_bpp)
  73. || __put_user(init32.front_offset, &init->front_offset)
  74. || __put_user(init32.front_pitch, &init->front_pitch)
  75. || __put_user(init32.back_offset, &init->back_offset)
  76. || __put_user(init32.back_pitch, &init->back_pitch)
  77. || __put_user(init32.depth_bpp, &init->depth_bpp)
  78. || __put_user(init32.depth_offset, &init->depth_offset)
  79. || __put_user(init32.depth_pitch, &init->depth_pitch)
  80. || __put_user(init32.fb_offset, &init->fb_offset)
  81. || __put_user(init32.mmio_offset, &init->mmio_offset)
  82. || __put_user(init32.ring_offset, &init->ring_offset)
  83. || __put_user(init32.ring_rptr_offset, &init->ring_rptr_offset)
  84. || __put_user(init32.buffers_offset, &init->buffers_offset)
  85. || __put_user(init32.gart_textures_offset,
  86. &init->gart_textures_offset))
  87. return -EFAULT;
  88. return drm_ioctl(file->f_dentry->d_inode, file,
  89. DRM_IOCTL_RADEON_CP_INIT, (unsigned long) init);
  90. }
  91. typedef struct drm_radeon_clear32 {
  92. unsigned int flags;
  93. unsigned int clear_color;
  94. unsigned int clear_depth;
  95. unsigned int color_mask;
  96. unsigned int depth_mask; /* misnamed field: should be stencil */
  97. u32 depth_boxes;
  98. } drm_radeon_clear32_t;
  99. static int compat_radeon_cp_clear(struct file *file, unsigned int cmd,
  100. unsigned long arg)
  101. {
  102. drm_radeon_clear32_t clr32;
  103. drm_radeon_clear_t __user *clr;
  104. if (copy_from_user(&clr32, (void __user *)arg, sizeof(clr32)))
  105. return -EFAULT;
  106. clr = compat_alloc_user_space(sizeof(*clr));
  107. if (!access_ok(VERIFY_WRITE, clr, sizeof(*clr))
  108. || __put_user(clr32.flags, &clr->flags)
  109. || __put_user(clr32.clear_color, &clr->clear_color)
  110. || __put_user(clr32.clear_depth, &clr->clear_depth)
  111. || __put_user(clr32.color_mask, &clr->color_mask)
  112. || __put_user(clr32.depth_mask, &clr->depth_mask)
  113. || __put_user((void __user *)(unsigned long)clr32.depth_boxes,
  114. &clr->depth_boxes))
  115. return -EFAULT;
  116. return drm_ioctl(file->f_dentry->d_inode, file,
  117. DRM_IOCTL_RADEON_CLEAR, (unsigned long) clr);
  118. }
  119. typedef struct drm_radeon_stipple32 {
  120. u32 mask;
  121. } drm_radeon_stipple32_t;
  122. static int compat_radeon_cp_stipple(struct file *file, unsigned int cmd,
  123. unsigned long arg)
  124. {
  125. drm_radeon_stipple32_t __user *argp = (void __user *) arg;
  126. drm_radeon_stipple_t __user *request;
  127. u32 mask;
  128. if (get_user(mask, &argp->mask))
  129. return -EFAULT;
  130. request = compat_alloc_user_space(sizeof(*request));
  131. if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
  132. || __put_user((unsigned int __user *)(unsigned long) mask,
  133. &request->mask))
  134. return -EFAULT;
  135. return drm_ioctl(file->f_dentry->d_inode, file,
  136. DRM_IOCTL_RADEON_STIPPLE, (unsigned long) request);
  137. }
  138. typedef struct drm_radeon_tex_image32 {
  139. unsigned int x, y; /* Blit coordinates */
  140. unsigned int width, height;
  141. u32 data;
  142. } drm_radeon_tex_image32_t;
  143. typedef struct drm_radeon_texture32 {
  144. unsigned int offset;
  145. int pitch;
  146. int format;
  147. int width; /* Texture image coordinates */
  148. int height;
  149. u32 image;
  150. } drm_radeon_texture32_t;
  151. static int compat_radeon_cp_texture(struct file *file, unsigned int cmd,
  152. unsigned long arg)
  153. {
  154. drm_radeon_texture32_t req32;
  155. drm_radeon_texture_t __user *request;
  156. drm_radeon_tex_image32_t img32;
  157. drm_radeon_tex_image_t __user *image;
  158. if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
  159. return -EFAULT;
  160. if (req32.image == 0)
  161. return -EINVAL;
  162. if (copy_from_user(&img32, (void __user *)(unsigned long)req32.image,
  163. sizeof(img32)))
  164. return -EFAULT;
  165. request = compat_alloc_user_space(sizeof(*request) + sizeof(*image));
  166. if (!access_ok(VERIFY_WRITE, request,
  167. sizeof(*request) + sizeof(*image)))
  168. return -EFAULT;
  169. image = (drm_radeon_tex_image_t __user *) (request + 1);
  170. if (__put_user(req32.offset, &request->offset)
  171. || __put_user(req32.pitch, &request->pitch)
  172. || __put_user(req32.format, &request->format)
  173. || __put_user(req32.width, &request->width)
  174. || __put_user(req32.height, &request->height)
  175. || __put_user(image, &request->image)
  176. || __put_user(img32.x, &image->x)
  177. || __put_user(img32.y, &image->y)
  178. || __put_user(img32.width, &image->width)
  179. || __put_user(img32.height, &image->height)
  180. || __put_user((const void __user *)(unsigned long)img32.data,
  181. &image->data))
  182. return -EFAULT;
  183. return drm_ioctl(file->f_dentry->d_inode, file,
  184. DRM_IOCTL_RADEON_TEXTURE, (unsigned long) request);
  185. }
  186. typedef struct drm_radeon_vertex2_32 {
  187. int idx; /* Index of vertex buffer */
  188. int discard; /* Client finished with buffer? */
  189. int nr_states;
  190. u32 state;
  191. int nr_prims;
  192. u32 prim;
  193. } drm_radeon_vertex2_32_t;
  194. static int compat_radeon_cp_vertex2(struct file *file, unsigned int cmd,
  195. unsigned long arg)
  196. {
  197. drm_radeon_vertex2_32_t req32;
  198. drm_radeon_vertex2_t __user *request;
  199. if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
  200. return -EFAULT;
  201. request = compat_alloc_user_space(sizeof(*request));
  202. if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
  203. || __put_user(req32.idx, &request->idx)
  204. || __put_user(req32.discard, &request->discard)
  205. || __put_user(req32.nr_states, &request->nr_states)
  206. || __put_user((void __user *)(unsigned long)req32.state,
  207. &request->state)
  208. || __put_user(req32.nr_prims, &request->nr_prims)
  209. || __put_user((void __user *)(unsigned long)req32.prim,
  210. &request->prim))
  211. return -EFAULT;
  212. return drm_ioctl(file->f_dentry->d_inode, file,
  213. DRM_IOCTL_RADEON_VERTEX2, (unsigned long) request);
  214. }
  215. typedef struct drm_radeon_cmd_buffer32 {
  216. int bufsz;
  217. u32 buf;
  218. int nbox;
  219. u32 boxes;
  220. } drm_radeon_cmd_buffer32_t;
  221. static int compat_radeon_cp_cmdbuf(struct file *file, unsigned int cmd,
  222. unsigned long arg)
  223. {
  224. drm_radeon_cmd_buffer32_t req32;
  225. drm_radeon_cmd_buffer_t __user *request;
  226. if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
  227. return -EFAULT;
  228. request = compat_alloc_user_space(sizeof(*request));
  229. if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
  230. || __put_user(req32.bufsz, &request->bufsz)
  231. || __put_user((void __user *)(unsigned long)req32.buf,
  232. &request->buf)
  233. || __put_user(req32.nbox, &request->nbox)
  234. || __put_user((void __user *)(unsigned long)req32.boxes,
  235. &request->boxes))
  236. return -EFAULT;
  237. return drm_ioctl(file->f_dentry->d_inode, file,
  238. DRM_IOCTL_RADEON_CMDBUF, (unsigned long) request);
  239. }
  240. typedef struct drm_radeon_getparam32 {
  241. int param;
  242. u32 value;
  243. } drm_radeon_getparam32_t;
  244. static int compat_radeon_cp_getparam(struct file *file, unsigned int cmd,
  245. unsigned long arg)
  246. {
  247. drm_radeon_getparam32_t req32;
  248. drm_radeon_getparam_t __user *request;
  249. if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
  250. return -EFAULT;
  251. request = compat_alloc_user_space(sizeof(*request));
  252. if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
  253. || __put_user(req32.param, &request->param)
  254. || __put_user((void __user *)(unsigned long)req32.value,
  255. &request->value))
  256. return -EFAULT;
  257. return drm_ioctl(file->f_dentry->d_inode, file,
  258. DRM_IOCTL_RADEON_GETPARAM, (unsigned long) request);
  259. }
  260. typedef struct drm_radeon_mem_alloc32 {
  261. int region;
  262. int alignment;
  263. int size;
  264. u32 region_offset; /* offset from start of fb or GART */
  265. } drm_radeon_mem_alloc32_t;
  266. static int compat_radeon_mem_alloc(struct file *file, unsigned int cmd,
  267. unsigned long arg)
  268. {
  269. drm_radeon_mem_alloc32_t req32;
  270. drm_radeon_mem_alloc_t __user *request;
  271. if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
  272. return -EFAULT;
  273. request = compat_alloc_user_space(sizeof(*request));
  274. if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
  275. || __put_user(req32.region, &request->region)
  276. || __put_user(req32.alignment, &request->alignment)
  277. || __put_user(req32.size, &request->size)
  278. || __put_user((int __user *)(unsigned long)req32.region_offset,
  279. &request->region_offset))
  280. return -EFAULT;
  281. return drm_ioctl(file->f_dentry->d_inode, file,
  282. DRM_IOCTL_RADEON_ALLOC, (unsigned long) request);
  283. }
  284. typedef struct drm_radeon_irq_emit32 {
  285. u32 irq_seq;
  286. } drm_radeon_irq_emit32_t;
  287. static int compat_radeon_irq_emit(struct file *file, unsigned int cmd,
  288. unsigned long arg)
  289. {
  290. drm_radeon_irq_emit32_t req32;
  291. drm_radeon_irq_emit_t __user *request;
  292. if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
  293. return -EFAULT;
  294. request = compat_alloc_user_space(sizeof(*request));
  295. if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
  296. || __put_user((int __user *)(unsigned long)req32.irq_seq,
  297. &request->irq_seq))
  298. return -EFAULT;
  299. return drm_ioctl(file->f_dentry->d_inode, file,
  300. DRM_IOCTL_RADEON_IRQ_EMIT, (unsigned long) request);
  301. }
  302. drm_ioctl_compat_t *radeon_compat_ioctls[] = {
  303. [DRM_RADEON_CP_INIT] = compat_radeon_cp_init,
  304. [DRM_RADEON_CLEAR] = compat_radeon_cp_clear,
  305. [DRM_RADEON_STIPPLE] = compat_radeon_cp_stipple,
  306. [DRM_RADEON_TEXTURE] = compat_radeon_cp_texture,
  307. [DRM_RADEON_VERTEX2] = compat_radeon_cp_vertex2,
  308. [DRM_RADEON_CMDBUF] = compat_radeon_cp_cmdbuf,
  309. [DRM_RADEON_GETPARAM] = compat_radeon_cp_getparam,
  310. [DRM_RADEON_ALLOC] = compat_radeon_mem_alloc,
  311. [DRM_RADEON_IRQ_EMIT] = compat_radeon_irq_emit,
  312. };
  313. /**
  314. * Called whenever a 32-bit process running under a 64-bit kernel
  315. * performs an ioctl on /dev/dri/card<n>.
  316. *
  317. * \param filp file pointer.
  318. * \param cmd command.
  319. * \param arg user argument.
  320. * \return zero on success or negative number on failure.
  321. */
  322. long radeon_compat_ioctl(struct file *filp, unsigned int cmd,
  323. unsigned long arg)
  324. {
  325. unsigned int nr = DRM_IOCTL_NR(cmd);
  326. drm_ioctl_compat_t *fn = NULL;
  327. int ret;
  328. if (nr < DRM_COMMAND_BASE)
  329. return drm_compat_ioctl(filp, cmd, arg);
  330. if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(radeon_compat_ioctls))
  331. fn = radeon_compat_ioctls[nr - DRM_COMMAND_BASE];
  332. lock_kernel(); /* XXX for now */
  333. if (fn != NULL)
  334. ret = (*fn)(filp, cmd, arg);
  335. else
  336. ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
  337. unlock_kernel();
  338. return ret;
  339. }