mga_state.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:28k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* mga_state.c -- State support for mga g200/g400 -*- linux-c -*-
  2.  * Created: Thu Jan 27 02:53:43 2000 by jhartmann@precisioninsight.com
  3.  *
  4.  * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
  5.  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
  6.  * All Rights Reserved.
  7.  *
  8.  * Permission is hereby granted, free of charge, to any person obtaining a
  9.  * copy of this software and associated documentation files (the "Software"),
  10.  * to deal in the Software without restriction, including without limitation
  11.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  12.  * and/or sell copies of the Software, and to permit persons to whom the
  13.  * Software is furnished to do so, subject to the following conditions:
  14.  *
  15.  * The above copyright notice and this permission notice (including the next
  16.  * paragraph) shall be included in all copies or substantial portions of the
  17.  * Software.
  18.  *
  19.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  22.  * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  23.  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  24.  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  25.  * DEALINGS IN THE SOFTWARE.
  26.  *
  27.  * Authors: Jeff Hartmann <jhartmann@valinux.com>
  28.  *      Keith Whitwell <keithw@valinux.com>
  29.  *
  30.  */
  31. #define __NO_VERSION__
  32. #include "drmP.h"
  33. #include "mga_drv.h"
  34. #include "drm.h"
  35. /* If you change the functions to set state, PLEASE
  36.  * change these values
  37.  */
  38. #define MGAEMITCLIP_SIZE 10
  39. #define MGAEMITCTX_SIZE 20
  40. #define MGAG200EMITTEX_SIZE  20
  41. #define MGAG400EMITTEX0_SIZE 30
  42. #define MGAG400EMITTEX1_SIZE 25
  43. #define MGAG400EMITPIPE_SIZE 50
  44. #define MGAG200EMITPIPE_SIZE 15
  45. #define MAX_STATE_SIZE ((MGAEMITCLIP_SIZE * MGA_NR_SAREA_CLIPRECTS) + 
  46. MGAEMITCTX_SIZE + MGAG400EMITTEX0_SIZE + 
  47. MGAG400EMITTEX1_SIZE + MGAG400EMITPIPE_SIZE)
  48. static void mgaEmitClipRect(drm_mga_private_t * dev_priv,
  49.     drm_clip_rect_t * box)
  50. {
  51. drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
  52. unsigned int *regs = sarea_priv->ContextState;
  53. PRIMLOCALS;
  54. /* This takes 10 dwords */
  55. PRIMGETPTR(dev_priv);
  56. /* Force reset of dwgctl on G400 (eliminates clip disable bit) */
  57. if (dev_priv->chipset == MGA_CARD_TYPE_G400) {
  58. #if 0
  59. PRIMOUTREG(MGAREG_DMAPAD, 0);
  60. PRIMOUTREG(MGAREG_DWGSYNC, 0);
  61. PRIMOUTREG(MGAREG_DWGSYNC, 0);
  62. PRIMOUTREG(MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL]);
  63. #else
  64. PRIMOUTREG(MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL]);
  65. PRIMOUTREG(MGAREG_LEN + MGAREG_MGA_EXEC, 0x80000000);
  66. PRIMOUTREG(MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL]);
  67. PRIMOUTREG(MGAREG_LEN + MGAREG_MGA_EXEC, 0x80000000);
  68. #endif
  69. }
  70. PRIMOUTREG(MGAREG_DMAPAD, 0);
  71. PRIMOUTREG(MGAREG_CXBNDRY, ((box->x2) << 16) | (box->x1));
  72. PRIMOUTREG(MGAREG_YTOP, box->y1 * dev_priv->stride / dev_priv->cpp);
  73. PRIMOUTREG(MGAREG_YBOT, box->y2 * dev_priv->stride / dev_priv->cpp);
  74. PRIMADVANCE(dev_priv);
  75. }
  76. static void mgaEmitContext(drm_mga_private_t * dev_priv)
  77. {
  78. drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
  79. unsigned int *regs = sarea_priv->ContextState;
  80. PRIMLOCALS;
  81. /* This takes a max of 20 dwords */
  82. PRIMGETPTR(dev_priv);
  83. PRIMOUTREG(MGAREG_DSTORG, regs[MGA_CTXREG_DSTORG]);
  84. PRIMOUTREG(MGAREG_MACCESS, regs[MGA_CTXREG_MACCESS]);
  85. PRIMOUTREG(MGAREG_PLNWT, regs[MGA_CTXREG_PLNWT]);
  86. PRIMOUTREG(MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL]);
  87. PRIMOUTREG(MGAREG_ALPHACTRL, regs[MGA_CTXREG_ALPHACTRL]);
  88. PRIMOUTREG(MGAREG_FOGCOL, regs[MGA_CTXREG_FOGCOLOR]);
  89. PRIMOUTREG(MGAREG_WFLAG, regs[MGA_CTXREG_WFLAG]);
  90. PRIMOUTREG(MGAREG_ZORG, dev_priv->depthOffset); /* invarient */
  91. if (dev_priv->chipset == MGA_CARD_TYPE_G400) {
  92. PRIMOUTREG(MGAREG_WFLAG1, regs[MGA_CTXREG_WFLAG]);
  93. PRIMOUTREG(MGAREG_TDUALSTAGE0, regs[MGA_CTXREG_TDUAL0]);
  94. PRIMOUTREG(MGAREG_TDUALSTAGE1, regs[MGA_CTXREG_TDUAL1]);
  95. PRIMOUTREG(MGAREG_FCOL, regs[MGA_CTXREG_FCOL]);
  96. PRIMOUTREG(MGAREG_STENCIL, regs[MGA_CTXREG_STENCIL]);
  97. PRIMOUTREG(MGAREG_STENCILCTL, regs[MGA_CTXREG_STENCILCTL]);
  98. PRIMOUTREG(MGAREG_DMAPAD, 0);
  99. PRIMOUTREG(MGAREG_DMAPAD, 0);
  100. } else {
  101. PRIMOUTREG(MGAREG_FCOL, regs[MGA_CTXREG_FCOL]);
  102. PRIMOUTREG(MGAREG_DMAPAD, 0);
  103. PRIMOUTREG(MGAREG_DMAPAD, 0);
  104. PRIMOUTREG(MGAREG_DMAPAD, 0);
  105. }
  106. PRIMADVANCE(dev_priv);
  107. }
  108. static void mgaG200EmitTex(drm_mga_private_t * dev_priv)
  109. {
  110. drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
  111. unsigned int *regs = sarea_priv->TexState[0];
  112. PRIMLOCALS;
  113. PRIMGETPTR(dev_priv);
  114. /* This takes 20 dwords */
  115. PRIMOUTREG(MGAREG_TEXCTL2, regs[MGA_TEXREG_CTL2]);
  116. PRIMOUTREG(MGAREG_TEXCTL, regs[MGA_TEXREG_CTL]);
  117. PRIMOUTREG(MGAREG_TEXFILTER, regs[MGA_TEXREG_FILTER]);
  118. PRIMOUTREG(MGAREG_TEXBORDERCOL, regs[MGA_TEXREG_BORDERCOL]);
  119. PRIMOUTREG(MGAREG_TEXORG, regs[MGA_TEXREG_ORG]);
  120. PRIMOUTREG(MGAREG_TEXORG1, regs[MGA_TEXREG_ORG1]);
  121. PRIMOUTREG(MGAREG_TEXORG2, regs[MGA_TEXREG_ORG2]);
  122. PRIMOUTREG(MGAREG_TEXORG3, regs[MGA_TEXREG_ORG3]);
  123. PRIMOUTREG(MGAREG_TEXORG4, regs[MGA_TEXREG_ORG4]);
  124. PRIMOUTREG(MGAREG_TEXWIDTH, regs[MGA_TEXREG_WIDTH]);
  125. PRIMOUTREG(MGAREG_TEXHEIGHT, regs[MGA_TEXREG_HEIGHT]);
  126. PRIMOUTREG(MGAREG_WR24, regs[MGA_TEXREG_WIDTH]);
  127. PRIMOUTREG(MGAREG_WR34, regs[MGA_TEXREG_HEIGHT]);
  128. PRIMOUTREG(MGAREG_TEXTRANS, 0xffff);
  129. PRIMOUTREG(MGAREG_TEXTRANSHIGH, 0xffff);
  130. PRIMOUTREG(MGAREG_DMAPAD, 0);
  131. PRIMADVANCE(dev_priv);
  132. }
  133. #define TMC_dualtex_enable  0x80
  134. static void mgaG400EmitTex0(drm_mga_private_t * dev_priv)
  135. {
  136. drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
  137. unsigned int *regs = sarea_priv->TexState[0];
  138. PRIMLOCALS;
  139. PRIMGETPTR(dev_priv);
  140. /* This takes 30 dwords */
  141. PRIMOUTREG(MGAREG_TEXCTL2, regs[MGA_TEXREG_CTL2] | 0x00008000);
  142. PRIMOUTREG(MGAREG_TEXCTL, regs[MGA_TEXREG_CTL]);
  143. PRIMOUTREG(MGAREG_TEXFILTER, regs[MGA_TEXREG_FILTER]);
  144. PRIMOUTREG(MGAREG_TEXBORDERCOL, regs[MGA_TEXREG_BORDERCOL]);
  145. PRIMOUTREG(MGAREG_TEXORG, regs[MGA_TEXREG_ORG]);
  146. PRIMOUTREG(MGAREG_TEXORG1, regs[MGA_TEXREG_ORG1]);
  147. PRIMOUTREG(MGAREG_TEXORG2, regs[MGA_TEXREG_ORG2]);
  148. PRIMOUTREG(MGAREG_TEXORG3, regs[MGA_TEXREG_ORG3]);
  149. PRIMOUTREG(MGAREG_TEXORG4, regs[MGA_TEXREG_ORG4]);
  150. PRIMOUTREG(MGAREG_TEXWIDTH, regs[MGA_TEXREG_WIDTH]);
  151. PRIMOUTREG(MGAREG_TEXHEIGHT, regs[MGA_TEXREG_HEIGHT]);
  152. PRIMOUTREG(MGAREG_WR49, 0);
  153. PRIMOUTREG(MGAREG_WR57, 0);
  154. PRIMOUTREG(MGAREG_WR53, 0);
  155. PRIMOUTREG(MGAREG_WR61, 0);
  156. PRIMOUTREG(MGAREG_WR52, 0x40);
  157. PRIMOUTREG(MGAREG_WR60, 0x40);
  158. PRIMOUTREG(MGAREG_WR54, regs[MGA_TEXREG_WIDTH] | 0x40);
  159. PRIMOUTREG(MGAREG_WR62, regs[MGA_TEXREG_HEIGHT] | 0x40);
  160. PRIMOUTREG(MGAREG_DMAPAD, 0);
  161. PRIMOUTREG(MGAREG_DMAPAD, 0);
  162. PRIMOUTREG(MGAREG_DMAPAD, 0);
  163. PRIMOUTREG(MGAREG_TEXTRANS, 0xffff);
  164. PRIMOUTREG(MGAREG_TEXTRANSHIGH, 0xffff);
  165. PRIMADVANCE(dev_priv);
  166. }
  167. #define TMC_map1_enable  0x80000000
  168. static void mgaG400EmitTex1(drm_mga_private_t * dev_priv)
  169. {
  170. drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
  171. unsigned int *regs = sarea_priv->TexState[1];
  172. PRIMLOCALS;
  173. PRIMGETPTR(dev_priv);
  174. /* This takes 25 dwords */
  175. PRIMOUTREG(MGAREG_TEXCTL2,
  176.    regs[MGA_TEXREG_CTL2] | TMC_map1_enable | 0x00008000);
  177. PRIMOUTREG(MGAREG_TEXCTL, regs[MGA_TEXREG_CTL]);
  178. PRIMOUTREG(MGAREG_TEXFILTER, regs[MGA_TEXREG_FILTER]);
  179. PRIMOUTREG(MGAREG_TEXBORDERCOL, regs[MGA_TEXREG_BORDERCOL]);
  180. PRIMOUTREG(MGAREG_TEXORG, regs[MGA_TEXREG_ORG]);
  181. PRIMOUTREG(MGAREG_TEXORG1, regs[MGA_TEXREG_ORG1]);
  182. PRIMOUTREG(MGAREG_TEXORG2, regs[MGA_TEXREG_ORG2]);
  183. PRIMOUTREG(MGAREG_TEXORG3, regs[MGA_TEXREG_ORG3]);
  184. PRIMOUTREG(MGAREG_TEXORG4, regs[MGA_TEXREG_ORG4]);
  185. PRIMOUTREG(MGAREG_TEXWIDTH, regs[MGA_TEXREG_WIDTH]);
  186. PRIMOUTREG(MGAREG_TEXHEIGHT, regs[MGA_TEXREG_HEIGHT]);
  187. PRIMOUTREG(MGAREG_WR49, 0);
  188. PRIMOUTREG(MGAREG_WR57, 0);
  189. PRIMOUTREG(MGAREG_WR53, 0);
  190. PRIMOUTREG(MGAREG_WR61, 0);
  191. PRIMOUTREG(MGAREG_WR52, regs[MGA_TEXREG_WIDTH] | 0x40);
  192. PRIMOUTREG(MGAREG_WR60, regs[MGA_TEXREG_HEIGHT] | 0x40);
  193. PRIMOUTREG(MGAREG_TEXTRANS, 0xffff);
  194. PRIMOUTREG(MGAREG_TEXTRANSHIGH, 0xffff);
  195. PRIMOUTREG(MGAREG_TEXCTL2, regs[MGA_TEXREG_CTL2] | 0x00008000);
  196. PRIMADVANCE(dev_priv);
  197. }
  198. #define MAGIC_FPARAM_HEX_VALUE 0x46480000
  199. /* This is the hex value of 12800.0f which is a magic value we must
  200.  * set in wr56.
  201.  */
  202. static void mgaG400EmitPipe(drm_mga_private_t * dev_priv)
  203. {
  204. drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
  205. unsigned int pipe = sarea_priv->WarpPipe;
  206. PRIMLOCALS;
  207. PRIMGETPTR(dev_priv);
  208. /* This takes 50 dwords */
  209. /* Establish vertex size.  
  210.  */
  211. PRIMOUTREG(MGAREG_WIADDR2, WIA_wmode_suspend);
  212. PRIMOUTREG(MGAREG_DMAPAD, 0);
  213. PRIMOUTREG(MGAREG_DMAPAD, 0);
  214. PRIMOUTREG(MGAREG_DMAPAD, 0);
  215. if (pipe & MGA_T2) {
  216. PRIMOUTREG(MGAREG_WVRTXSZ, 0x00001e09);
  217. PRIMOUTREG(MGAREG_DMAPAD, 0);
  218. PRIMOUTREG(MGAREG_DMAPAD, 0);
  219. PRIMOUTREG(MGAREG_DMAPAD, 0);
  220. PRIMOUTREG(MGAREG_WACCEPTSEQ, 0);
  221. PRIMOUTREG(MGAREG_WACCEPTSEQ, 0);
  222. PRIMOUTREG(MGAREG_WACCEPTSEQ, 0);
  223. PRIMOUTREG(MGAREG_WACCEPTSEQ, 0x1e000000);
  224. } else {
  225. if (dev_priv->WarpPipe & MGA_T2) {
  226. /* Flush the WARP pipe */
  227. PRIMOUTREG(MGAREG_YDST, 0);
  228. PRIMOUTREG(MGAREG_FXLEFT, 0);
  229. PRIMOUTREG(MGAREG_FXRIGHT, 1);
  230. PRIMOUTREG(MGAREG_DWGCTL, MGA_FLUSH_CMD);
  231. PRIMOUTREG(MGAREG_LEN + MGAREG_MGA_EXEC, 1);
  232. PRIMOUTREG(MGAREG_DWGSYNC, 0x7000);
  233. PRIMOUTREG(MGAREG_TEXCTL2, 0x00008000);
  234. PRIMOUTREG(MGAREG_LEN + MGAREG_MGA_EXEC, 0);
  235. PRIMOUTREG(MGAREG_TEXCTL2, 0x80 | 0x00008000);
  236. PRIMOUTREG(MGAREG_LEN + MGAREG_MGA_EXEC, 0);
  237. PRIMOUTREG(MGAREG_TEXCTL2, 0x00008000);
  238. PRIMOUTREG(MGAREG_DMAPAD, 0);
  239. }
  240. PRIMOUTREG(MGAREG_WVRTXSZ, 0x00001807);
  241. PRIMOUTREG(MGAREG_DMAPAD, 0);
  242. PRIMOUTREG(MGAREG_DMAPAD, 0);
  243. PRIMOUTREG(MGAREG_DMAPAD, 0);
  244. PRIMOUTREG(MGAREG_WACCEPTSEQ, 0);
  245. PRIMOUTREG(MGAREG_WACCEPTSEQ, 0);
  246. PRIMOUTREG(MGAREG_WACCEPTSEQ, 0);
  247. PRIMOUTREG(MGAREG_WACCEPTSEQ, 0x18000000);
  248. }
  249. PRIMOUTREG(MGAREG_WFLAG, 0);
  250. PRIMOUTREG(MGAREG_WFLAG1, 0);
  251. PRIMOUTREG(MGAREG_WR56, MAGIC_FPARAM_HEX_VALUE);
  252. PRIMOUTREG(MGAREG_DMAPAD, 0);
  253. PRIMOUTREG(MGAREG_WR49, 0); /* Tex stage 0 */
  254. PRIMOUTREG(MGAREG_WR57, 0); /* Tex stage 0 */
  255. PRIMOUTREG(MGAREG_WR53, 0); /* Tex stage 1 */
  256. PRIMOUTREG(MGAREG_WR61, 0); /* Tex stage 1 */
  257. PRIMOUTREG(MGAREG_WR54, 0x40); /* Tex stage 0 : w */
  258. PRIMOUTREG(MGAREG_WR62, 0x40); /* Tex stage 0 : h */
  259. PRIMOUTREG(MGAREG_WR52, 0x40); /* Tex stage 1 : w */
  260. PRIMOUTREG(MGAREG_WR60, 0x40); /* Tex stage 1 : h */
  261. /* Dma pading required due to hw bug */
  262. PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff);
  263. PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff);
  264. PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff);
  265. PRIMOUTREG(MGAREG_WIADDR2,
  266.    (u32) (dev_priv->WarpIndex[pipe].
  267.   phys_addr | WIA_wmode_start | WIA_wagp_agp));
  268. PRIMADVANCE(dev_priv);
  269. }
  270. static void mgaG200EmitPipe(drm_mga_private_t * dev_priv)
  271. {
  272. drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
  273. unsigned int pipe = sarea_priv->WarpPipe;
  274. PRIMLOCALS;
  275. PRIMGETPTR(dev_priv);
  276. /* This takes 15 dwords */
  277. PRIMOUTREG(MGAREG_WIADDR, WIA_wmode_suspend);
  278. PRIMOUTREG(MGAREG_WVRTXSZ, 7);
  279. PRIMOUTREG(MGAREG_WFLAG, 0);
  280. PRIMOUTREG(MGAREG_WR24, 0); /* tex w/h */
  281. PRIMOUTREG(MGAREG_WR25, 0x100);
  282. PRIMOUTREG(MGAREG_WR34, 0); /* tex w/h */
  283. PRIMOUTREG(MGAREG_WR42, 0xFFFF);
  284. PRIMOUTREG(MGAREG_WR60, 0xFFFF);
  285. /* Dma pading required due to hw bug */
  286. PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff);
  287. PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff);
  288. PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff);
  289. PRIMOUTREG(MGAREG_WIADDR,
  290.    (u32) (dev_priv->WarpIndex[pipe].
  291.   phys_addr | WIA_wmode_start | WIA_wagp_agp));
  292. PRIMADVANCE( dev_priv );
  293. }
  294. static void mgaEmitState(drm_mga_private_t * dev_priv)
  295. {
  296. drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
  297. unsigned int dirty = sarea_priv->dirty;
  298. if (dev_priv->chipset == MGA_CARD_TYPE_G400) {
  299. int multitex = sarea_priv->WarpPipe & MGA_T2;
  300. if (sarea_priv->WarpPipe != dev_priv->WarpPipe) {
  301. mgaG400EmitPipe(dev_priv);
  302. dev_priv->WarpPipe = sarea_priv->WarpPipe;
  303. }
  304. if (dirty & MGA_UPLOAD_CTX) {
  305. mgaEmitContext(dev_priv);
  306. sarea_priv->dirty &= ~MGA_UPLOAD_CTX;
  307. }
  308. if (dirty & MGA_UPLOAD_TEX0) {
  309. mgaG400EmitTex0(dev_priv);
  310. sarea_priv->dirty &= ~MGA_UPLOAD_TEX0;
  311. }
  312. if ((dirty & MGA_UPLOAD_TEX1) && multitex) {
  313. mgaG400EmitTex1(dev_priv);
  314. sarea_priv->dirty &= ~MGA_UPLOAD_TEX1;
  315. }
  316. } else {
  317. if (sarea_priv->WarpPipe != dev_priv->WarpPipe) {
  318. mgaG200EmitPipe(dev_priv);
  319. dev_priv->WarpPipe = sarea_priv->WarpPipe;
  320. }
  321. if (dirty & MGA_UPLOAD_CTX) {
  322. mgaEmitContext(dev_priv);
  323. sarea_priv->dirty &= ~MGA_UPLOAD_CTX;
  324. }
  325. if (dirty & MGA_UPLOAD_TEX0) {
  326. mgaG200EmitTex(dev_priv);
  327. sarea_priv->dirty &= ~MGA_UPLOAD_TEX0;
  328. }
  329. }
  330. }
  331. /* Disallow all write destinations except the front and backbuffer.
  332.  */
  333. static int mgaVerifyContext(drm_mga_private_t * dev_priv)
  334. {
  335. drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
  336. unsigned int *regs = sarea_priv->ContextState;
  337. if (regs[MGA_CTXREG_DSTORG] != dev_priv->frontOffset &&
  338.     regs[MGA_CTXREG_DSTORG] != dev_priv->backOffset) {
  339. DRM_DEBUG("BAD DSTORG: %x (front %x, back %x)nn",
  340.   regs[MGA_CTXREG_DSTORG], dev_priv->frontOffset,
  341.   dev_priv->backOffset);
  342. regs[MGA_CTXREG_DSTORG] = 0;
  343. return -1;
  344. }
  345. return 0;
  346. }
  347. /* Disallow texture reads from PCI space.
  348.  */
  349. static int mgaVerifyTex(drm_mga_private_t * dev_priv, int unit)
  350. {
  351. drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
  352. if ((sarea_priv->TexState[unit][MGA_TEXREG_ORG] & 0x3) == 0x1) {
  353. DRM_DEBUG("BAD TEXREG_ORG: %x, unit %dn",
  354.   sarea_priv->TexState[unit][MGA_TEXREG_ORG],
  355.   unit);
  356. sarea_priv->TexState[unit][MGA_TEXREG_ORG] = 0;
  357. return -1;
  358. }
  359. return 0;
  360. }
  361. static int mgaVerifyState(drm_mga_private_t * dev_priv)
  362. {
  363. drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
  364. unsigned int dirty = sarea_priv->dirty;
  365. int rv = 0;
  366. if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS)
  367. sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
  368. if (dirty & MGA_UPLOAD_CTX)
  369. rv |= mgaVerifyContext(dev_priv);
  370. if (dirty & MGA_UPLOAD_TEX0)
  371. rv |= mgaVerifyTex(dev_priv, 0);
  372. if (dev_priv->chipset == MGA_CARD_TYPE_G400) {
  373. if (dirty & MGA_UPLOAD_TEX1)
  374. rv |= mgaVerifyTex(dev_priv, 1);
  375. if (dirty & MGA_UPLOAD_PIPE)
  376. rv |= (sarea_priv->WarpPipe > MGA_MAX_G400_PIPES);
  377. } else {
  378. if (dirty & MGA_UPLOAD_PIPE)
  379. rv |= (sarea_priv->WarpPipe > MGA_MAX_G200_PIPES);
  380. }
  381. return rv == 0;
  382. }
  383. static int mgaVerifyIload(drm_mga_private_t * dev_priv,
  384.   unsigned long bus_address,
  385.   unsigned int dstOrg, int length)
  386. {
  387. if (dstOrg < dev_priv->textureOffset ||
  388.     dstOrg + length >
  389.     (dev_priv->textureOffset + dev_priv->textureSize)) {
  390. return -EINVAL;
  391. }
  392. if (length % 64) {
  393. return -EINVAL;
  394. }
  395. return 0;
  396. }
  397. /* This copies a 64 byte aligned agp region to the frambuffer
  398.  * with a standard blit, the ioctl needs to do checking */
  399. static void mga_dma_dispatch_tex_blit(drm_device_t * dev,
  400.       unsigned long bus_address,
  401.       int length, unsigned int destOrg)
  402. {
  403. drm_mga_private_t *dev_priv = dev->dev_private;
  404. int use_agp = PDEA_pagpxfer_enable | 0x00000001;
  405. u16 y2;
  406. PRIMLOCALS;
  407. y2 = length / 64;
  408. PRIM_OVERFLOW(dev, dev_priv, 30);
  409. PRIMOUTREG(MGAREG_DSTORG, destOrg);
  410. PRIMOUTREG(MGAREG_MACCESS, 0x00000000);
  411. PRIMOUTREG(MGAREG_SRCORG, (u32) bus_address | use_agp);
  412. PRIMOUTREG(MGAREG_AR5, 64);
  413. PRIMOUTREG(MGAREG_PITCH, 64);
  414. PRIMOUTREG(MGAREG_DMAPAD, 0);
  415. PRIMOUTREG(MGAREG_DMAPAD, 0);
  416. PRIMOUTREG(MGAREG_DWGCTL, MGA_COPY_CMD);
  417. PRIMOUTREG(MGAREG_AR0, 63);
  418. PRIMOUTREG(MGAREG_AR3, 0);
  419. PRIMOUTREG(MGAREG_FXBNDRY, (63 << 16));
  420. PRIMOUTREG(MGAREG_YDSTLEN + MGAREG_MGA_EXEC, y2);
  421. PRIMOUTREG(MGAREG_DMAPAD, 0);
  422. PRIMOUTREG(MGAREG_SRCORG, 0);
  423. PRIMOUTREG(MGAREG_PITCH, dev_priv->stride / dev_priv->cpp);
  424. PRIMOUTREG(MGAREG_DWGSYNC, 0x7000);
  425. PRIMADVANCE(dev_priv);
  426. }
  427. static void mga_dma_dispatch_vertex(drm_device_t * dev, drm_buf_t * buf)
  428. {
  429. drm_mga_private_t *dev_priv = dev->dev_private;
  430. drm_mga_buf_priv_t *buf_priv = buf->dev_private;
  431. drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
  432. unsigned long address = (unsigned long) buf->bus_address;
  433. int length = buf->used;
  434. int use_agp = PDEA_pagpxfer_enable;
  435. int i = 0;
  436. PRIMLOCALS;
  437. if (buf->used) {
  438. /* WARNING: if you change any of the state functions verify
  439.  * these numbers (Overestimating this doesn't hurt).
  440.  */
  441. buf_priv->dispatched = 1;
  442. PRIM_OVERFLOW(dev, dev_priv,
  443.       (MAX_STATE_SIZE + (5 * MGA_NR_SAREA_CLIPRECTS)));
  444. mgaEmitState(dev_priv);
  445. #if 0
  446. length = dev_priv->vertexsize * 3 * 4;
  447. #endif
  448. do {
  449. if (i < sarea_priv->nbox) {
  450. mgaEmitClipRect(dev_priv,
  451. &sarea_priv->boxes[i]);
  452. }
  453. PRIMGETPTR(dev_priv);
  454. PRIMOUTREG(MGAREG_DMAPAD, 0);
  455. PRIMOUTREG(MGAREG_DMAPAD, 0);
  456. PRIMOUTREG(MGAREG_SECADDRESS,
  457.    ((u32) address) | TT_VERTEX);
  458. PRIMOUTREG(MGAREG_SECEND,
  459.    (((u32) (address + length)) | use_agp));
  460. PRIMADVANCE(dev_priv);
  461. } while (++i < sarea_priv->nbox);
  462. }
  463. if (buf_priv->discard) {
  464. if (buf_priv->dispatched == 1)
  465. AGEBUF(dev_priv, buf_priv);
  466. buf_priv->dispatched = 0;
  467. mga_freelist_put(dev, buf);
  468. }
  469. }
  470. static void mga_dma_dispatch_indices(drm_device_t * dev,
  471.      drm_buf_t * buf,
  472.      unsigned int start, unsigned int end)
  473. {
  474. drm_mga_private_t *dev_priv = dev->dev_private;
  475. drm_mga_buf_priv_t *buf_priv = buf->dev_private;
  476. drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
  477. unsigned int address = (unsigned int) buf->bus_address;
  478. int use_agp = PDEA_pagpxfer_enable;
  479. int i = 0;
  480. PRIMLOCALS;
  481. if (start != end) {
  482. /* WARNING: if you change any of the state functions verify
  483.  * these numbers (Overestimating this doesn't hurt).
  484.  */
  485. buf_priv->dispatched = 1;
  486. PRIM_OVERFLOW(dev, dev_priv,
  487.       (MAX_STATE_SIZE + (5 * MGA_NR_SAREA_CLIPRECTS)));
  488. mgaEmitState(dev_priv);
  489. do {
  490. if (i < sarea_priv->nbox) {
  491. mgaEmitClipRect(dev_priv,
  492. &sarea_priv->boxes[i]);
  493. }
  494. PRIMGETPTR(dev_priv);
  495. PRIMOUTREG(MGAREG_DMAPAD, 0);
  496. PRIMOUTREG(MGAREG_DMAPAD, 0);
  497. PRIMOUTREG(MGAREG_SETUPADDRESS,
  498.    ((address + start) |
  499.     SETADD_mode_vertlist));
  500. PRIMOUTREG(MGAREG_SETUPEND,
  501.    ((address + end) | use_agp));
  502. /*      ((address + start + 12) | use_agp)); */
  503. PRIMADVANCE(dev_priv);
  504. } while (++i < sarea_priv->nbox);
  505. }
  506. if (buf_priv->discard) {
  507. if (buf_priv->dispatched == 1)
  508. AGEBUF(dev_priv, buf_priv);
  509. buf_priv->dispatched = 0;
  510. mga_freelist_put(dev, buf);
  511. }
  512. }
  513. static void mga_dma_dispatch_clear(drm_device_t * dev, int flags,
  514.    unsigned int clear_color,
  515.    unsigned int clear_zval,
  516.    unsigned int clear_colormask,
  517.    unsigned int clear_depthmask)
  518. {
  519. drm_mga_private_t *dev_priv = dev->dev_private;
  520. drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
  521. unsigned int *regs = sarea_priv->ContextState;
  522. int nbox = sarea_priv->nbox;
  523. drm_clip_rect_t *pbox = sarea_priv->boxes;
  524. unsigned int cmd;
  525. int i;
  526. PRIMLOCALS;
  527. if (dev_priv->sgram)
  528. cmd = MGA_CLEAR_CMD | DC_atype_blk;
  529. else
  530. cmd = MGA_CLEAR_CMD | DC_atype_rstr;
  531. PRIM_OVERFLOW(dev, dev_priv, 35 * MGA_NR_SAREA_CLIPRECTS);
  532. for (i = 0; i < nbox; i++) {
  533. unsigned int height = pbox[i].y2 - pbox[i].y1;
  534. if (flags & MGA_FRONT) {
  535. PRIMOUTREG(MGAREG_DMAPAD, 0);
  536. PRIMOUTREG(MGAREG_PLNWT, clear_colormask);
  537. PRIMOUTREG(MGAREG_YDSTLEN,
  538.    (pbox[i].y1 << 16) | height);
  539. PRIMOUTREG(MGAREG_FXBNDRY,
  540.    (pbox[i].x2 << 16) | pbox[i].x1);
  541. PRIMOUTREG(MGAREG_DMAPAD, 0);
  542. PRIMOUTREG(MGAREG_FCOL, clear_color);
  543. PRIMOUTREG(MGAREG_DSTORG, dev_priv->frontOffset);
  544. PRIMOUTREG(MGAREG_DWGCTL + MGAREG_MGA_EXEC, cmd);
  545. }
  546. if (flags & MGA_BACK) {
  547. PRIMOUTREG(MGAREG_DMAPAD, 0);
  548. PRIMOUTREG(MGAREG_PLNWT, clear_colormask);
  549. PRIMOUTREG(MGAREG_YDSTLEN,
  550.    (pbox[i].y1 << 16) | height);
  551. PRIMOUTREG(MGAREG_FXBNDRY,
  552.    (pbox[i].x2 << 16) | pbox[i].x1);
  553. PRIMOUTREG(MGAREG_DMAPAD, 0);
  554. PRIMOUTREG(MGAREG_FCOL, clear_color);
  555. PRIMOUTREG(MGAREG_DSTORG, dev_priv->backOffset);
  556. PRIMOUTREG(MGAREG_DWGCTL + MGAREG_MGA_EXEC, cmd);
  557. }
  558. if (flags & MGA_DEPTH) {
  559. PRIMOUTREG(MGAREG_DMAPAD, 0);
  560. PRIMOUTREG(MGAREG_PLNWT, clear_depthmask);
  561. PRIMOUTREG(MGAREG_YDSTLEN,
  562.    (pbox[i].y1 << 16) | height);
  563. PRIMOUTREG(MGAREG_FXBNDRY,
  564.    (pbox[i].x2 << 16) | pbox[i].x1);
  565. PRIMOUTREG(MGAREG_DMAPAD, 0);
  566. PRIMOUTREG(MGAREG_FCOL, clear_zval);
  567. PRIMOUTREG(MGAREG_DSTORG, dev_priv->depthOffset);
  568. PRIMOUTREG(MGAREG_DWGCTL + MGAREG_MGA_EXEC, cmd);
  569. }
  570. }
  571. /* Force reset of DWGCTL */
  572. PRIMOUTREG(MGAREG_DMAPAD, 0);
  573. PRIMOUTREG(MGAREG_DMAPAD, 0);
  574. PRIMOUTREG(MGAREG_DMAPAD, 0);
  575. PRIMOUTREG(MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL]);
  576. PRIMADVANCE(dev_priv);
  577. }
  578. static void mga_dma_dispatch_swap(drm_device_t * dev)
  579. {
  580. drm_mga_private_t *dev_priv = dev->dev_private;
  581. drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
  582. unsigned int *regs = sarea_priv->ContextState;
  583. int nbox = sarea_priv->nbox;
  584. drm_clip_rect_t *pbox = sarea_priv->boxes;
  585. int i;
  586. int pixel_stride = dev_priv->stride / dev_priv->cpp;
  587. PRIMLOCALS;
  588. PRIM_OVERFLOW(dev, dev_priv, (MGA_NR_SAREA_CLIPRECTS * 5) + 20);
  589. PRIMOUTREG(MGAREG_DMAPAD, 0);
  590. PRIMOUTREG(MGAREG_DMAPAD, 0);
  591. PRIMOUTREG(MGAREG_DWGSYNC, 0x7100);
  592. PRIMOUTREG(MGAREG_DWGSYNC, 0x7000);
  593. PRIMOUTREG(MGAREG_DSTORG, dev_priv->frontOffset);
  594. PRIMOUTREG(MGAREG_MACCESS, dev_priv->mAccess);
  595. PRIMOUTREG(MGAREG_SRCORG, dev_priv->backOffset);
  596. PRIMOUTREG(MGAREG_AR5, pixel_stride);
  597. PRIMOUTREG(MGAREG_DMAPAD, 0);
  598. PRIMOUTREG(MGAREG_DMAPAD, 0);
  599. PRIMOUTREG(MGAREG_DMAPAD, 0);
  600. PRIMOUTREG(MGAREG_DWGCTL, MGA_COPY_CMD);
  601. for (i = 0; i < nbox; i++) {
  602. unsigned int h = pbox[i].y2 - pbox[i].y1;
  603. unsigned int start = pbox[i].y1 * pixel_stride;
  604. PRIMOUTREG(MGAREG_AR0, start + pbox[i].x2 - 1);
  605. PRIMOUTREG(MGAREG_AR3, start + pbox[i].x1);
  606. PRIMOUTREG(MGAREG_FXBNDRY,
  607.    pbox[i].x1 | ((pbox[i].x2 - 1) << 16));
  608. PRIMOUTREG(MGAREG_YDSTLEN + MGAREG_MGA_EXEC,
  609.    (pbox[i].y1 << 16) | h);
  610. }
  611. /* Force reset of DWGCTL */
  612. PRIMOUTREG(MGAREG_DMAPAD, 0);
  613. PRIMOUTREG(MGAREG_DMAPAD, 0);
  614. PRIMOUTREG(MGAREG_SRCORG, 0);
  615. PRIMOUTREG(MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL]);
  616. PRIMADVANCE(dev_priv);
  617. }
  618. int mga_clear_bufs(struct inode *inode, struct file *filp,
  619.    unsigned int cmd, unsigned long arg)
  620. {
  621. drm_file_t *priv = filp->private_data;
  622. drm_device_t *dev = priv->dev;
  623. drm_mga_private_t *dev_priv =
  624.     (drm_mga_private_t *) dev->dev_private;
  625. drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
  626. drm_mga_clear_t clear;
  627. if (copy_from_user(&clear, (drm_mga_clear_t *) arg, sizeof(clear)))
  628. return -EFAULT;
  629. if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
  630. DRM_ERROR("mga_clear_bufs called without lock heldn");
  631. return -EINVAL;
  632. }
  633. if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS)
  634. sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
  635. /* Make sure we restore the 3D state next time.
  636.  */
  637. dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CTX;
  638. mga_dma_dispatch_clear(dev, clear.flags,
  639.        clear.clear_color,
  640.        clear.clear_depth,
  641.        clear.clear_color_mask,
  642.        clear.clear_depth_mask);
  643. PRIMUPDATE(dev_priv);
  644. mga_flush_write_combine();
  645. mga_dma_schedule(dev, 1);
  646. return 0;
  647. }
  648. int mga_swap_bufs(struct inode *inode, struct file *filp,
  649.   unsigned int cmd, unsigned long arg)
  650. {
  651. drm_file_t *priv = filp->private_data;
  652. drm_device_t *dev = priv->dev;
  653. drm_mga_private_t *dev_priv =
  654.     (drm_mga_private_t *) dev->dev_private;
  655. drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
  656. if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
  657. DRM_ERROR("mga_swap_bufs called without lock heldn");
  658. return -EINVAL;
  659. }
  660. if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS)
  661. sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
  662. /* Make sure we restore the 3D state next time.
  663.  */
  664. dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CTX;
  665. mga_dma_dispatch_swap(dev);
  666. PRIMUPDATE(dev_priv);
  667. set_bit(MGA_BUF_SWAP_PENDING,
  668. &dev_priv->current_prim->buffer_status);
  669. mga_flush_write_combine();
  670. mga_dma_schedule(dev, 1);
  671. return 0;
  672. }
  673. int mga_iload(struct inode *inode, struct file *filp,
  674.       unsigned int cmd, unsigned long arg)
  675. {
  676. drm_file_t *priv = filp->private_data;
  677. drm_device_t *dev = priv->dev;
  678. drm_device_dma_t *dma = dev->dma;
  679. drm_mga_private_t *dev_priv =
  680.     (drm_mga_private_t *) dev->dev_private;
  681. drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
  682. drm_buf_t *buf;
  683. drm_mga_buf_priv_t *buf_priv;
  684. drm_mga_iload_t iload;
  685. unsigned long bus_address;
  686. if (copy_from_user(&iload, (drm_mga_iload_t *) arg, sizeof(iload)))
  687. return -EFAULT;
  688. if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
  689. DRM_ERROR("mga_iload called without lock heldn");
  690. return -EINVAL;
  691. }
  692. if(iload.idx < 0 || iload.idx > dma->buf_count) return -EINVAL;
  693. buf = dma->buflist[iload.idx];
  694. buf_priv = buf->dev_private;
  695. bus_address = buf->bus_address;
  696. if (mgaVerifyIload(dev_priv,
  697.    bus_address, iload.destOrg, iload.length)) {
  698. mga_freelist_put(dev, buf);
  699. return -EINVAL;
  700. }
  701. sarea_priv->dirty |= MGA_UPLOAD_CTX;
  702. mga_dma_dispatch_tex_blit(dev, bus_address, iload.length,
  703.   iload.destOrg);
  704. AGEBUF(dev_priv, buf_priv);
  705. buf_priv->discard = 1;
  706. mga_freelist_put(dev, buf);
  707. mga_flush_write_combine();
  708. mga_dma_schedule(dev, 1);
  709. return 0;
  710. }
  711. int mga_vertex(struct inode *inode, struct file *filp,
  712.        unsigned int cmd, unsigned long arg)
  713. {
  714. drm_file_t *priv = filp->private_data;
  715. drm_device_t *dev = priv->dev;
  716. drm_mga_private_t *dev_priv =
  717.     (drm_mga_private_t *) dev->dev_private;
  718. drm_device_dma_t *dma = dev->dma;
  719. drm_buf_t *buf;
  720. drm_mga_buf_priv_t *buf_priv;
  721. drm_mga_vertex_t vertex;
  722. if (copy_from_user(&vertex, (drm_mga_vertex_t *) arg, sizeof(vertex)))
  723. return -EFAULT;
  724. if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
  725. DRM_ERROR("mga_vertex called without lock heldn");
  726. return -EINVAL;
  727. }
  728. if(vertex.idx < 0 || vertex.idx > dma->buf_count) return -EINVAL;
  729. buf = dma->buflist[vertex.idx];
  730. buf_priv = buf->dev_private;
  731. buf->used = vertex.used;
  732. buf_priv->discard = vertex.discard;
  733. if (!mgaVerifyState(dev_priv)) {
  734. if (vertex.discard) {
  735. if (buf_priv->dispatched == 1)
  736. AGEBUF(dev_priv, buf_priv);
  737. buf_priv->dispatched = 0;
  738. mga_freelist_put(dev, buf);
  739. }
  740. return -EINVAL;
  741. }
  742. mga_dma_dispatch_vertex(dev, buf);
  743. PRIMUPDATE(dev_priv);
  744. mga_flush_write_combine();
  745. mga_dma_schedule(dev, 1);
  746. return 0;
  747. }
  748. int mga_indices(struct inode *inode, struct file *filp,
  749. unsigned int cmd, unsigned long arg)
  750. {
  751. drm_file_t *priv = filp->private_data;
  752. drm_device_t *dev = priv->dev;
  753. drm_mga_private_t *dev_priv =
  754.     (drm_mga_private_t *) dev->dev_private;
  755. drm_device_dma_t *dma = dev->dma;
  756. drm_buf_t *buf;
  757. drm_mga_buf_priv_t *buf_priv;
  758. drm_mga_indices_t indices;
  759. if (copy_from_user(&indices,
  760.    (drm_mga_indices_t *)arg, sizeof(indices)))
  761. return -EFAULT;
  762. if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
  763. DRM_ERROR("mga_indices called without lock heldn");
  764. return -EINVAL;
  765. }
  766. if(indices.idx < 0 || indices.idx > dma->buf_count) return -EINVAL;
  767. buf = dma->buflist[indices.idx];
  768. buf_priv = buf->dev_private;
  769. buf_priv->discard = indices.discard;
  770. if (!mgaVerifyState(dev_priv)) {
  771. if (indices.discard) {
  772. if (buf_priv->dispatched == 1)
  773. AGEBUF(dev_priv, buf_priv);
  774. buf_priv->dispatched = 0;
  775. mga_freelist_put(dev, buf);
  776. }
  777. return -EINVAL;
  778. }
  779. mga_dma_dispatch_indices(dev, buf, indices.start, indices.end);
  780. PRIMUPDATE(dev_priv);
  781. mga_flush_write_combine();
  782. mga_dma_schedule(dev, 1);
  783. return 0;
  784. }
  785. static int mga_dma_get_buffers(drm_device_t * dev, drm_dma_t * d)
  786. {
  787. int i;
  788. drm_buf_t *buf;
  789. for (i = d->granted_count; i < d->request_count; i++) {
  790. buf = mga_freelist_get(dev);
  791. if (!buf)
  792. break;
  793. buf->pid = current->pid;
  794. if (copy_to_user(&d->request_indices[i],
  795.  &buf->idx, sizeof(buf->idx)))
  796. return -EFAULT;
  797. if (copy_to_user(&d->request_sizes[i],
  798.  &buf->total, sizeof(buf->total)))
  799. return -EFAULT;
  800. ++d->granted_count;
  801. }
  802. return 0;
  803. }
  804. int mga_dma(struct inode *inode, struct file *filp, unsigned int cmd,
  805.     unsigned long arg)
  806. {
  807. drm_file_t *priv = filp->private_data;
  808. drm_device_t *dev = priv->dev;
  809. drm_device_dma_t *dma = dev->dma;
  810. int retcode = 0;
  811. drm_dma_t d;
  812. if (copy_from_user(&d, (drm_dma_t *) arg, sizeof(d)))
  813. return -EFAULT;
  814. if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
  815. DRM_ERROR("mga_dma called without lock heldn");
  816. return -EINVAL;
  817. }
  818. /* Please don't send us buffers.
  819.  */
  820. if (d.send_count != 0) {
  821. DRM_ERROR
  822.     ("Process %d trying to send %d buffers via drmDMAn",
  823.      current->pid, d.send_count);
  824. return -EINVAL;
  825. }
  826. /* We'll send you buffers.
  827.  */
  828. if (d.request_count < 0 || d.request_count > dma->buf_count) {
  829. DRM_ERROR
  830.     ("Process %d trying to get %d buffers (of %d max)n",
  831.      current->pid, d.request_count, dma->buf_count);
  832. return -EINVAL;
  833. }
  834. d.granted_count = 0;
  835. if (d.request_count) {
  836. retcode = mga_dma_get_buffers(dev, &d);
  837. }
  838. if (copy_to_user((drm_dma_t *) arg, &d, sizeof(d)))
  839. return -EFAULT;
  840. return retcode;
  841. }