mga_state.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:28k
源码类别:

嵌入式Linux

开发平台:

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.  * VA LINUX SYSTEMS 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
  25.  * OTHER DEALINGS IN THE SOFTWARE.
  26.  *
  27.  * Authors:
  28.  *    Jeff Hartmann <jhartmann@valinux.com>
  29.  *    Keith Whitwell <keithw@valinux.com>
  30.  *
  31.  * Rewritten by:
  32.  *    Gareth Hughes <gareth@valinux.com>
  33.  */
  34. #define __NO_VERSION__
  35. #include "mga.h"
  36. #include "drmP.h"
  37. #include "mga_drv.h"
  38. #include "drm.h"
  39. /* ================================================================
  40.  * DMA hardware state programming functions
  41.  */
  42. static void mga_emit_clip_rect( drm_mga_private_t *dev_priv,
  43. drm_clip_rect_t *box )
  44. {
  45. drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
  46. drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
  47. unsigned int pitch = dev_priv->front_pitch;
  48. DMA_LOCALS;
  49. BEGIN_DMA( 2 );
  50. /* Force reset of DWGCTL on G400 (eliminates clip disable bit).
  51.  */
  52. if ( dev_priv->chipset == MGA_CARD_TYPE_G400 ) {
  53. DMA_BLOCK( MGA_DWGCTL, ctx->dwgctl,
  54.    MGA_LEN + MGA_EXEC, 0x80000000,
  55.    MGA_DWGCTL, ctx->dwgctl,
  56.    MGA_LEN + MGA_EXEC, 0x80000000 );
  57. }
  58. DMA_BLOCK( MGA_DMAPAD, 0x00000000,
  59.    MGA_CXBNDRY, (box->x2 << 16) | box->x1,
  60.    MGA_YTOP, box->y1 * pitch,
  61.    MGA_YBOT, box->y2 * pitch );
  62. ADVANCE_DMA();
  63. }
  64. static inline void mga_g200_emit_context( drm_mga_private_t *dev_priv )
  65. {
  66. drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
  67. drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
  68. DMA_LOCALS;
  69. BEGIN_DMA( 3 );
  70. DMA_BLOCK( MGA_DSTORG, ctx->dstorg,
  71.    MGA_MACCESS, ctx->maccess,
  72.    MGA_PLNWT, ctx->plnwt,
  73.    MGA_DWGCTL, ctx->dwgctl );
  74. DMA_BLOCK( MGA_ALPHACTRL, ctx->alphactrl,
  75.    MGA_FOGCOL, ctx->fogcolor,
  76.    MGA_WFLAG, ctx->wflag,
  77.    MGA_ZORG, dev_priv->depth_offset );
  78. DMA_BLOCK( MGA_FCOL, ctx->fcol,
  79.    MGA_DMAPAD, 0x00000000,
  80.    MGA_DMAPAD, 0x00000000,
  81.    MGA_DMAPAD, 0x00000000 );
  82. ADVANCE_DMA();
  83. }
  84. static inline void mga_g400_emit_context( drm_mga_private_t *dev_priv )
  85. {
  86. drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
  87. drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
  88. DMA_LOCALS;
  89. BEGIN_DMA( 4 );
  90. DMA_BLOCK( MGA_DSTORG, ctx->dstorg,
  91.    MGA_MACCESS, ctx->maccess,
  92.    MGA_PLNWT, ctx->plnwt,
  93.    MGA_DWGCTL, ctx->dwgctl );
  94. DMA_BLOCK( MGA_ALPHACTRL, ctx->alphactrl,
  95.    MGA_FOGCOL, ctx->fogcolor,
  96.    MGA_WFLAG, ctx->wflag,
  97.    MGA_ZORG, dev_priv->depth_offset );
  98. DMA_BLOCK( MGA_WFLAG1, ctx->wflag,
  99.    MGA_TDUALSTAGE0, ctx->tdualstage0,
  100.    MGA_TDUALSTAGE1, ctx->tdualstage1,
  101.    MGA_FCOL, ctx->fcol );
  102. DMA_BLOCK( MGA_STENCIL, ctx->stencil,
  103.    MGA_STENCILCTL, ctx->stencilctl,
  104.    MGA_DMAPAD, 0x00000000,
  105.    MGA_DMAPAD, 0x00000000 );
  106. ADVANCE_DMA();
  107. }
  108. static inline void mga_g200_emit_tex0( drm_mga_private_t *dev_priv )
  109. {
  110. drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
  111. drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[0];
  112. DMA_LOCALS;
  113. BEGIN_DMA( 4 );
  114. DMA_BLOCK( MGA_TEXCTL2, tex->texctl2,
  115.    MGA_TEXCTL, tex->texctl,
  116.    MGA_TEXFILTER, tex->texfilter,
  117.    MGA_TEXBORDERCOL, tex->texbordercol );
  118. DMA_BLOCK( MGA_TEXORG, tex->texorg,
  119.    MGA_TEXORG1, tex->texorg1,
  120.    MGA_TEXORG2, tex->texorg2,
  121.    MGA_TEXORG3, tex->texorg3 );
  122. DMA_BLOCK( MGA_TEXORG4, tex->texorg4,
  123.    MGA_TEXWIDTH, tex->texwidth,
  124.    MGA_TEXHEIGHT, tex->texheight,
  125.    MGA_WR24, tex->texwidth );
  126. DMA_BLOCK( MGA_WR34, tex->texheight,
  127.    MGA_TEXTRANS, 0x0000ffff,
  128.    MGA_TEXTRANSHIGH, 0x0000ffff,
  129.    MGA_DMAPAD, 0x00000000 );
  130. ADVANCE_DMA();
  131. }
  132. static inline void mga_g400_emit_tex0( drm_mga_private_t *dev_priv )
  133. {
  134. drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
  135. drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[0];
  136. DMA_LOCALS;
  137. BEGIN_DMA( 6 );
  138. DMA_BLOCK( MGA_TEXCTL2, tex->texctl2 | MGA_G400_TC2_MAGIC,
  139.    MGA_TEXCTL, tex->texctl,
  140.    MGA_TEXFILTER, tex->texfilter,
  141.    MGA_TEXBORDERCOL, tex->texbordercol );
  142. DMA_BLOCK( MGA_TEXORG, tex->texorg,
  143.    MGA_TEXORG1, tex->texorg1,
  144.    MGA_TEXORG2, tex->texorg2,
  145.    MGA_TEXORG3, tex->texorg3 );
  146. DMA_BLOCK( MGA_TEXORG4, tex->texorg4,
  147.    MGA_TEXWIDTH, tex->texwidth,
  148.    MGA_TEXHEIGHT, tex->texheight,
  149.    MGA_WR49, 0x00000000 );
  150. DMA_BLOCK( MGA_WR57, 0x00000000,
  151.    MGA_WR53, 0x00000000,
  152.    MGA_WR61, 0x00000000,
  153.    MGA_WR52, MGA_G400_WR_MAGIC );
  154. DMA_BLOCK( MGA_WR60, MGA_G400_WR_MAGIC,
  155.    MGA_WR54, tex->texwidth | MGA_G400_WR_MAGIC,
  156.    MGA_WR62, tex->texheight | MGA_G400_WR_MAGIC,
  157.    MGA_DMAPAD, 0x00000000 );
  158. DMA_BLOCK( MGA_DMAPAD, 0x00000000,
  159.    MGA_DMAPAD, 0x00000000,
  160.    MGA_TEXTRANS, 0x0000ffff,
  161.    MGA_TEXTRANSHIGH, 0x0000ffff );
  162. ADVANCE_DMA();
  163. }
  164. static inline void mga_g400_emit_tex1( drm_mga_private_t *dev_priv )
  165. {
  166. drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
  167. drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[1];
  168. DMA_LOCALS;
  169. BEGIN_DMA( 5 );
  170. DMA_BLOCK( MGA_TEXCTL2, (tex->texctl2 |
  171.  MGA_MAP1_ENABLE |
  172.  MGA_G400_TC2_MAGIC),
  173.    MGA_TEXCTL, tex->texctl,
  174.    MGA_TEXFILTER, tex->texfilter,
  175.    MGA_TEXBORDERCOL, tex->texbordercol );
  176. DMA_BLOCK( MGA_TEXORG, tex->texorg,
  177.    MGA_TEXORG1, tex->texorg1,
  178.    MGA_TEXORG2, tex->texorg2,
  179.    MGA_TEXORG3, tex->texorg3 );
  180. DMA_BLOCK( MGA_TEXORG4, tex->texorg4,
  181.    MGA_TEXWIDTH, tex->texwidth,
  182.    MGA_TEXHEIGHT, tex->texheight,
  183.    MGA_WR49, 0x00000000 );
  184. DMA_BLOCK( MGA_WR57, 0x00000000,
  185.    MGA_WR53, 0x00000000,
  186.    MGA_WR61, 0x00000000,
  187.    MGA_WR52, tex->texwidth | MGA_G400_WR_MAGIC );
  188. DMA_BLOCK( MGA_WR60, tex->texheight | MGA_G400_WR_MAGIC,
  189.    MGA_TEXTRANS, 0x0000ffff,
  190.    MGA_TEXTRANSHIGH, 0x0000ffff,
  191.    MGA_TEXCTL2, tex->texctl2 | MGA_G400_TC2_MAGIC );
  192. ADVANCE_DMA();
  193. }
  194. static inline void mga_g200_emit_pipe( drm_mga_private_t *dev_priv )
  195. {
  196. drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
  197. unsigned int pipe = sarea_priv->warp_pipe;
  198. DMA_LOCALS;
  199. BEGIN_DMA( 3 );
  200. DMA_BLOCK( MGA_WIADDR, MGA_WMODE_SUSPEND,
  201.    MGA_WVRTXSZ, 0x00000007,
  202.    MGA_WFLAG, 0x00000000,
  203.    MGA_WR24, 0x00000000 );
  204. DMA_BLOCK( MGA_WR25, 0x00000100,
  205.    MGA_WR34, 0x00000000,
  206.    MGA_WR42, 0x0000ffff,
  207.    MGA_WR60, 0x0000ffff );
  208. /* Padding required to to hardware bug.
  209.  */
  210. DMA_BLOCK( MGA_DMAPAD, 0xffffffff,
  211.    MGA_DMAPAD, 0xffffffff,
  212.    MGA_DMAPAD, 0xffffffff,
  213.    MGA_WIADDR, (dev_priv->warp_pipe_phys[pipe] |
  214.  MGA_WMODE_START |
  215.  MGA_WAGP_ENABLE) );
  216. ADVANCE_DMA();
  217. }
  218. static inline void mga_g400_emit_pipe( drm_mga_private_t *dev_priv )
  219. {
  220. drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
  221. unsigned int pipe = sarea_priv->warp_pipe;
  222. DMA_LOCALS;
  223. BEGIN_DMA( 10 );
  224. DMA_BLOCK( MGA_WIADDR2, MGA_WMODE_SUSPEND,
  225.    MGA_DMAPAD, 0x00000000,
  226.    MGA_DMAPAD, 0x00000000,
  227.    MGA_DMAPAD, 0x00000000 );
  228. if ( pipe & MGA_T2 ) {
  229. DMA_BLOCK( MGA_WVRTXSZ, 0x00001e09,
  230.    MGA_DMAPAD, 0x00000000,
  231.    MGA_DMAPAD, 0x00000000,
  232.    MGA_DMAPAD, 0x00000000 );
  233. DMA_BLOCK( MGA_WACCEPTSEQ, 0x00000000,
  234.    MGA_WACCEPTSEQ, 0x00000000,
  235.    MGA_WACCEPTSEQ, 0x00000000,
  236.    MGA_WACCEPTSEQ, 0x1e000000 );
  237. } else {
  238. if ( dev_priv->warp_pipe & MGA_T2 ) {
  239. /* Flush the WARP pipe */
  240. DMA_BLOCK( MGA_YDST, 0x00000000,
  241.    MGA_FXLEFT, 0x00000000,
  242.    MGA_FXRIGHT, 0x00000001,
  243.    MGA_DWGCTL, MGA_DWGCTL_FLUSH );
  244. DMA_BLOCK( MGA_LEN + MGA_EXEC, 0x00000001,
  245.    MGA_DWGSYNC, 0x00007000,
  246.    MGA_TEXCTL2, MGA_G400_TC2_MAGIC,
  247.    MGA_LEN + MGA_EXEC, 0x00000000 );
  248. DMA_BLOCK( MGA_TEXCTL2, (MGA_DUALTEX |
  249.  MGA_G400_TC2_MAGIC),
  250.    MGA_LEN + MGA_EXEC, 0x00000000,
  251.    MGA_TEXCTL2, MGA_G400_TC2_MAGIC,
  252.    MGA_DMAPAD, 0x00000000 );
  253. }
  254. DMA_BLOCK( MGA_WVRTXSZ, 0x00001807,
  255.    MGA_DMAPAD, 0x00000000,
  256.    MGA_DMAPAD, 0x00000000,
  257.    MGA_DMAPAD, 0x00000000 );
  258. DMA_BLOCK( MGA_WACCEPTSEQ, 0x00000000,
  259.    MGA_WACCEPTSEQ, 0x00000000,
  260.    MGA_WACCEPTSEQ, 0x00000000,
  261.    MGA_WACCEPTSEQ, 0x18000000 );
  262. }
  263. DMA_BLOCK( MGA_WFLAG, 0x00000000,
  264.    MGA_WFLAG1, 0x00000000,
  265.    MGA_WR56, MGA_G400_WR56_MAGIC,
  266.    MGA_DMAPAD, 0x00000000 );
  267. DMA_BLOCK( MGA_WR49, 0x00000000, /* tex0              */
  268.    MGA_WR57, 0x00000000, /* tex0              */
  269.    MGA_WR53, 0x00000000, /* tex1              */
  270.    MGA_WR61, 0x00000000 ); /* tex1              */
  271. DMA_BLOCK( MGA_WR54, MGA_G400_WR_MAGIC, /* tex0 width        */
  272.    MGA_WR62, MGA_G400_WR_MAGIC, /* tex0 height       */
  273.    MGA_WR52, MGA_G400_WR_MAGIC, /* tex1 width        */
  274.    MGA_WR60, MGA_G400_WR_MAGIC ); /* tex1 height       */
  275. /* Padding required to to hardware bug */
  276. DMA_BLOCK( MGA_DMAPAD, 0xffffffff,
  277.    MGA_DMAPAD, 0xffffffff,
  278.    MGA_DMAPAD, 0xffffffff,
  279.    MGA_WIADDR2, (dev_priv->warp_pipe_phys[pipe] |
  280.  MGA_WMODE_START |
  281.  MGA_WAGP_ENABLE) );
  282. ADVANCE_DMA();
  283. }
  284. static void mga_g200_emit_state( drm_mga_private_t *dev_priv )
  285. {
  286. drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
  287. unsigned int dirty = sarea_priv->dirty;
  288. if ( sarea_priv->warp_pipe != dev_priv->warp_pipe ) {
  289. mga_g200_emit_pipe( dev_priv );
  290. dev_priv->warp_pipe = sarea_priv->warp_pipe;
  291. }
  292. if ( dirty & MGA_UPLOAD_CONTEXT ) {
  293. mga_g200_emit_context( dev_priv );
  294. sarea_priv->dirty &= ~MGA_UPLOAD_CONTEXT;
  295. }
  296. if ( dirty & MGA_UPLOAD_TEX0 ) {
  297. mga_g200_emit_tex0( dev_priv );
  298. sarea_priv->dirty &= ~MGA_UPLOAD_TEX0;
  299. }
  300. }
  301. static void mga_g400_emit_state( drm_mga_private_t *dev_priv )
  302. {
  303. drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
  304. unsigned int dirty = sarea_priv->dirty;
  305. int multitex = sarea_priv->warp_pipe & MGA_T2;
  306. if ( sarea_priv->warp_pipe != dev_priv->warp_pipe ) {
  307. mga_g400_emit_pipe( dev_priv );
  308. dev_priv->warp_pipe = sarea_priv->warp_pipe;
  309. }
  310. if ( dirty & MGA_UPLOAD_CONTEXT ) {
  311. mga_g400_emit_context( dev_priv );
  312. sarea_priv->dirty &= ~MGA_UPLOAD_CONTEXT;
  313. }
  314. if ( dirty & MGA_UPLOAD_TEX0 ) {
  315. mga_g400_emit_tex0( dev_priv );
  316. sarea_priv->dirty &= ~MGA_UPLOAD_TEX0;
  317. }
  318. if ( (dirty & MGA_UPLOAD_TEX1) && multitex ) {
  319. mga_g400_emit_tex1( dev_priv );
  320. sarea_priv->dirty &= ~MGA_UPLOAD_TEX1;
  321. }
  322. }
  323. /* ================================================================
  324.  * SAREA state verification
  325.  */
  326. /* Disallow all write destinations except the front and backbuffer.
  327.  */
  328. static int mga_verify_context( drm_mga_private_t *dev_priv )
  329. {
  330. drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
  331. drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
  332. if ( ctx->dstorg != dev_priv->front_offset &&
  333.      ctx->dstorg != dev_priv->back_offset ) {
  334. DRM_ERROR( "*** bad DSTORG: %x (front %x, back %x)nn",
  335.    ctx->dstorg, dev_priv->front_offset,
  336.    dev_priv->back_offset );
  337. ctx->dstorg = 0;
  338. return -EINVAL;
  339. }
  340. return 0;
  341. }
  342. /* Disallow texture reads from PCI space.
  343.  */
  344. static int mga_verify_tex( drm_mga_private_t *dev_priv, int unit )
  345. {
  346. drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
  347. drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[unit];
  348. unsigned int org;
  349. org = tex->texorg & (MGA_TEXORGMAP_MASK | MGA_TEXORGACC_MASK);
  350. if ( org == (MGA_TEXORGMAP_SYSMEM | MGA_TEXORGACC_PCI) ) {
  351. DRM_ERROR( "*** bad TEXORG: 0x%x, unit %dn",
  352.    tex->texorg, unit );
  353. tex->texorg = 0;
  354. return -EINVAL;
  355. }
  356. return 0;
  357. }
  358. static int mga_verify_state( drm_mga_private_t *dev_priv )
  359. {
  360. drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
  361. unsigned int dirty = sarea_priv->dirty;
  362. int ret = 0;
  363. if ( sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS )
  364. sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
  365. if ( dirty & MGA_UPLOAD_CONTEXT )
  366. ret |= mga_verify_context( dev_priv );
  367. if ( dirty & MGA_UPLOAD_TEX0 )
  368. ret |= mga_verify_tex( dev_priv, 0 );
  369. if ( dev_priv->chipset == MGA_CARD_TYPE_G400 ) {
  370. if ( dirty & MGA_UPLOAD_TEX1 )
  371. ret |= mga_verify_tex( dev_priv, 1 );
  372. if ( dirty & MGA_UPLOAD_PIPE )
  373. ret |= ( sarea_priv->warp_pipe > MGA_MAX_G400_PIPES );
  374. } else {
  375. if ( dirty & MGA_UPLOAD_PIPE )
  376. ret |= ( sarea_priv->warp_pipe > MGA_MAX_G200_PIPES );
  377. }
  378. return ( ret == 0 );
  379. }
  380. static int mga_verify_iload( drm_mga_private_t *dev_priv,
  381.      unsigned int dstorg, unsigned int length )
  382. {
  383. if ( dstorg < dev_priv->texture_offset ||
  384.      dstorg + length > (dev_priv->texture_offset +
  385. dev_priv->texture_size) ) {
  386. DRM_ERROR( "*** bad iload DSTORG: 0x%xn", dstorg );
  387. return -EINVAL;
  388. }
  389. if ( length & MGA_ILOAD_MASK ) {
  390. DRM_ERROR( "*** bad iload length: 0x%xn",
  391.    length & MGA_ILOAD_MASK );
  392. return -EINVAL;
  393. }
  394. return 0;
  395. }
  396. static int mga_verify_blit( drm_mga_private_t *dev_priv,
  397.     unsigned int srcorg, unsigned int dstorg )
  398. {
  399. if ( (srcorg & 0x3) == (MGA_SRCACC_PCI | MGA_SRCMAP_SYSMEM) ||
  400.      (dstorg & 0x3) == (MGA_SRCACC_PCI | MGA_SRCMAP_SYSMEM) ) {
  401. DRM_ERROR( "*** bad blit: src=0x%x dst=0x%xn",
  402.    srcorg, dstorg );
  403. return -EINVAL;
  404. }
  405. return 0;
  406. }
  407. /* ================================================================
  408.  *
  409.  */
  410. static void mga_dma_dispatch_clear( drm_device_t *dev,
  411.     drm_mga_clear_t *clear )
  412. {
  413. drm_mga_private_t *dev_priv = dev->dev_private;
  414. drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
  415. drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
  416. drm_clip_rect_t *pbox = sarea_priv->boxes;
  417. int nbox = sarea_priv->nbox;
  418. int i;
  419. DMA_LOCALS;
  420. DRM_DEBUG( __FUNCTION__ ":n" );
  421. BEGIN_DMA( 1 );
  422. DMA_BLOCK( MGA_DMAPAD, 0x00000000,
  423.    MGA_DMAPAD, 0x00000000,
  424.    MGA_DWGSYNC, 0x00007100,
  425.    MGA_DWGSYNC, 0x00007000 );
  426. ADVANCE_DMA();
  427. for ( i = 0 ; i < nbox ; i++ ) {
  428. drm_clip_rect_t *box = &pbox[i];
  429. u32 height = box->y2 - box->y1;
  430. DRM_DEBUG( "   from=%d,%d to=%d,%dn",
  431.    box->x1, box->y1, box->x2, box->y2 );
  432. if ( clear->flags & MGA_FRONT ) {
  433. BEGIN_DMA( 2 );
  434. DMA_BLOCK( MGA_DMAPAD, 0x00000000,
  435.    MGA_PLNWT, clear->color_mask,
  436.    MGA_YDSTLEN, (box->y1 << 16) | height,
  437.    MGA_FXBNDRY, (box->x2 << 16) | box->x1 );
  438. DMA_BLOCK( MGA_DMAPAD, 0x00000000,
  439.    MGA_FCOL, clear->clear_color,
  440.    MGA_DSTORG, dev_priv->front_offset,
  441.    MGA_DWGCTL + MGA_EXEC,
  442. dev_priv->clear_cmd );
  443. ADVANCE_DMA();
  444. }
  445. if ( clear->flags & MGA_BACK ) {
  446. BEGIN_DMA( 2 );
  447. DMA_BLOCK( MGA_DMAPAD, 0x00000000,
  448.    MGA_PLNWT, clear->color_mask,
  449.    MGA_YDSTLEN, (box->y1 << 16) | height,
  450.    MGA_FXBNDRY, (box->x2 << 16) | box->x1 );
  451. DMA_BLOCK( MGA_DMAPAD, 0x00000000,
  452.    MGA_FCOL, clear->clear_color,
  453.    MGA_DSTORG, dev_priv->back_offset,
  454.    MGA_DWGCTL + MGA_EXEC,
  455. dev_priv->clear_cmd );
  456. ADVANCE_DMA();
  457. }
  458. if ( clear->flags & MGA_DEPTH ) {
  459. BEGIN_DMA( 2 );
  460. DMA_BLOCK( MGA_DMAPAD, 0x00000000,
  461.    MGA_PLNWT, clear->depth_mask,
  462.    MGA_YDSTLEN, (box->y1 << 16) | height,
  463.    MGA_FXBNDRY, (box->x2 << 16) | box->x1 );
  464. DMA_BLOCK( MGA_DMAPAD, 0x00000000,
  465.    MGA_FCOL, clear->clear_depth,
  466.    MGA_DSTORG, dev_priv->depth_offset,
  467.    MGA_DWGCTL + MGA_EXEC,
  468. dev_priv->clear_cmd );
  469. ADVANCE_DMA();
  470. }
  471. }
  472. BEGIN_DMA( 1 );
  473. /* Force reset of DWGCTL */
  474. DMA_BLOCK( MGA_DMAPAD, 0x00000000,
  475.    MGA_DMAPAD, 0x00000000,
  476.    MGA_PLNWT, ctx->plnwt,
  477.    MGA_DWGCTL, ctx->dwgctl );
  478. ADVANCE_DMA();
  479. FLUSH_DMA();
  480. }
  481. static void mga_dma_dispatch_swap( drm_device_t *dev )
  482. {
  483. drm_mga_private_t *dev_priv = dev->dev_private;
  484. drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
  485. drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
  486. drm_clip_rect_t *pbox = sarea_priv->boxes;
  487. int nbox = sarea_priv->nbox;
  488. int i;
  489. DMA_LOCALS;
  490. DRM_DEBUG( __FUNCTION__ ":n" );
  491. sarea_priv->last_frame.head = dev_priv->prim.tail;
  492. sarea_priv->last_frame.wrap = dev_priv->prim.last_wrap;
  493. BEGIN_DMA( 4 + nbox );
  494. DMA_BLOCK( MGA_DMAPAD, 0x00000000,
  495.    MGA_DMAPAD, 0x00000000,
  496.    MGA_DWGSYNC, 0x00007100,
  497.    MGA_DWGSYNC, 0x00007000 );
  498. DMA_BLOCK( MGA_DSTORG, dev_priv->front_offset,
  499.    MGA_MACCESS, dev_priv->maccess,
  500.    MGA_SRCORG, dev_priv->back_offset,
  501.    MGA_AR5, dev_priv->front_pitch );
  502. DMA_BLOCK( MGA_DMAPAD, 0x00000000,
  503.    MGA_DMAPAD, 0x00000000,
  504.    MGA_PLNWT, 0xffffffff,
  505.    MGA_DWGCTL, MGA_DWGCTL_COPY );
  506. for ( i = 0 ; i < nbox ; i++ ) {
  507. drm_clip_rect_t *box = &pbox[i];
  508. u32 height = box->y2 - box->y1;
  509. u32 start = box->y1 * dev_priv->front_pitch;
  510. DRM_DEBUG( "   from=%d,%d to=%d,%dn",
  511.    box->x1, box->y1, box->x2, box->y2 );
  512. DMA_BLOCK( MGA_AR0, start + box->x2 - 1,
  513.    MGA_AR3, start + box->x1,
  514.    MGA_FXBNDRY, ((box->x2 - 1) << 16) | box->x1,
  515.    MGA_YDSTLEN + MGA_EXEC,
  516. (box->y1 << 16) | height );
  517. }
  518. DMA_BLOCK( MGA_DMAPAD, 0x00000000,
  519.    MGA_PLNWT, ctx->plnwt,
  520.    MGA_SRCORG, dev_priv->front_offset,
  521.    MGA_DWGCTL, ctx->dwgctl );
  522. ADVANCE_DMA();
  523. FLUSH_DMA();
  524. DRM_DEBUG( "%s... done.n", __FUNCTION__ );
  525. }
  526. static void mga_dma_dispatch_vertex( drm_device_t *dev, drm_buf_t *buf )
  527. {
  528. drm_mga_private_t *dev_priv = dev->dev_private;
  529. drm_mga_buf_priv_t *buf_priv = buf->dev_private;
  530. drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
  531. u32 address = (u32) buf->bus_address;
  532. u32 length = (u32) buf->used;
  533. int i = 0;
  534. DMA_LOCALS;
  535. DRM_DEBUG( "vertex: buf=%d used=%dn", buf->idx, buf->used );
  536. if ( buf->used ) {
  537. buf_priv->dispatched = 1;
  538. MGA_EMIT_STATE( dev_priv, sarea_priv->dirty );
  539. do {
  540. if ( i < sarea_priv->nbox ) {
  541. mga_emit_clip_rect( dev_priv,
  542.     &sarea_priv->boxes[i] );
  543. }
  544. BEGIN_DMA( 1 );
  545. DMA_BLOCK( MGA_DMAPAD, 0x00000000,
  546.    MGA_DMAPAD, 0x00000000,
  547.    MGA_SECADDRESS, (address |
  548.  MGA_DMA_VERTEX),
  549.    MGA_SECEND, ((address + length) |
  550.  MGA_PAGPXFER) );
  551. ADVANCE_DMA();
  552. } while ( ++i < sarea_priv->nbox );
  553. }
  554. if ( buf_priv->discard ) {
  555. AGE_BUFFER( buf_priv );
  556. buf->pending = 0;
  557. buf->used = 0;
  558. buf_priv->dispatched = 0;
  559. mga_freelist_put( dev, buf );
  560. }
  561. FLUSH_DMA();
  562. }
  563. static void mga_dma_dispatch_indices( drm_device_t *dev, drm_buf_t *buf,
  564.       unsigned int start, unsigned int end )
  565. {
  566. drm_mga_private_t *dev_priv = dev->dev_private;
  567. drm_mga_buf_priv_t *buf_priv = buf->dev_private;
  568. drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
  569. u32 address = (u32) buf->bus_address;
  570. int i = 0;
  571. DMA_LOCALS;
  572. DRM_DEBUG( "indices: buf=%d start=%d end=%dn", buf->idx, start, end );
  573. if ( start != end ) {
  574. buf_priv->dispatched = 1;
  575. MGA_EMIT_STATE( dev_priv, sarea_priv->dirty );
  576. do {
  577. if ( i < sarea_priv->nbox ) {
  578. mga_emit_clip_rect( dev_priv,
  579.     &sarea_priv->boxes[i] );
  580. }
  581. BEGIN_DMA( 1 );
  582. DMA_BLOCK( MGA_DMAPAD, 0x00000000,
  583.    MGA_DMAPAD, 0x00000000,
  584.    MGA_SETUPADDRESS, address + start,
  585.    MGA_SETUPEND, ((address + end) |
  586.  MGA_PAGPXFER) );
  587. ADVANCE_DMA();
  588. } while ( ++i < sarea_priv->nbox );
  589. }
  590. if ( buf_priv->discard ) {
  591. AGE_BUFFER( buf_priv );
  592. buf->pending = 0;
  593. buf->used = 0;
  594. buf_priv->dispatched = 0;
  595. mga_freelist_put( dev, buf );
  596. }
  597. FLUSH_DMA();
  598. }
  599. /* This copies a 64 byte aligned agp region to the frambuffer with a
  600.  * standard blit, the ioctl needs to do checking.
  601.  */
  602. static void mga_dma_dispatch_iload( drm_device_t *dev, drm_buf_t *buf,
  603.     unsigned int dstorg, unsigned int length )
  604. {
  605. drm_mga_private_t *dev_priv = dev->dev_private;
  606. drm_mga_buf_priv_t *buf_priv = buf->dev_private;
  607. drm_mga_context_regs_t *ctx = &dev_priv->sarea_priv->context_state;
  608. u32 srcorg = buf->bus_address | MGA_SRCACC_AGP | MGA_SRCMAP_SYSMEM;
  609. u32 y2;
  610. DMA_LOCALS;
  611. DRM_DEBUG( "%s: buf=%d used=%dn",
  612.    __FUNCTION__, buf->idx, buf->used );
  613. y2 = length / 64;
  614. BEGIN_DMA( 5 );
  615. DMA_BLOCK( MGA_DMAPAD, 0x00000000,
  616.    MGA_DMAPAD, 0x00000000,
  617.    MGA_DWGSYNC, 0x00007100,
  618.    MGA_DWGSYNC, 0x00007000 );
  619. DMA_BLOCK( MGA_DSTORG, dstorg,
  620.    MGA_MACCESS, 0x00000000,
  621.    MGA_SRCORG, srcorg,
  622.    MGA_AR5, 64 );
  623. DMA_BLOCK( MGA_PITCH, 64,
  624.    MGA_PLNWT, 0xffffffff,
  625.    MGA_DMAPAD, 0x00000000,
  626.    MGA_DWGCTL, MGA_DWGCTL_COPY );
  627. DMA_BLOCK( MGA_AR0, 63,
  628.    MGA_AR3, 0,
  629.    MGA_FXBNDRY, (63 << 16) | 0,
  630.    MGA_YDSTLEN + MGA_EXEC, y2 );
  631. DMA_BLOCK( MGA_PLNWT, ctx->plnwt,
  632.    MGA_SRCORG, dev_priv->front_offset,
  633.    MGA_PITCH, dev_priv->front_pitch,
  634.    MGA_DWGSYNC, 0x00007000 );
  635. ADVANCE_DMA();
  636. AGE_BUFFER( buf_priv );
  637. buf->pending = 0;
  638. buf->used = 0;
  639. buf_priv->dispatched = 0;
  640. mga_freelist_put( dev, buf );
  641. FLUSH_DMA();
  642. }
  643. static void mga_dma_dispatch_blit( drm_device_t *dev,
  644.    drm_mga_blit_t *blit )
  645. {
  646. drm_mga_private_t *dev_priv = dev->dev_private;
  647. drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
  648. drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
  649. drm_clip_rect_t *pbox = sarea_priv->boxes;
  650. int nbox = sarea_priv->nbox;
  651. u32 scandir = 0, i;
  652. DMA_LOCALS;
  653. DRM_DEBUG( __FUNCTION__ ":n" );
  654. BEGIN_DMA( 4 + nbox );
  655. DMA_BLOCK( MGA_DMAPAD, 0x00000000,
  656.    MGA_DMAPAD, 0x00000000,
  657.    MGA_DWGSYNC, 0x00007100,
  658.    MGA_DWGSYNC, 0x00007000 );
  659. DMA_BLOCK( MGA_DWGCTL, MGA_DWGCTL_COPY,
  660.    MGA_PLNWT, blit->planemask,
  661.    MGA_SRCORG, blit->srcorg,
  662.    MGA_DSTORG, blit->dstorg );
  663. DMA_BLOCK( MGA_SGN, scandir,
  664.    MGA_MACCESS, dev_priv->maccess,
  665.    MGA_AR5, blit->ydir * blit->src_pitch,
  666.    MGA_PITCH, blit->dst_pitch );
  667. for ( i = 0 ; i < nbox ; i++ ) {
  668. int srcx = pbox[i].x1 + blit->delta_sx;
  669. int srcy = pbox[i].y1 + blit->delta_sy;
  670. int dstx = pbox[i].x1 + blit->delta_dx;
  671. int dsty = pbox[i].y1 + blit->delta_dy;
  672. int h = pbox[i].y2 - pbox[i].y1;
  673. int w = pbox[i].x2 - pbox[i].x1 - 1;
  674. int start;
  675. if ( blit->ydir == -1 ) {
  676. srcy = blit->height - srcy - 1;
  677. }
  678. start = srcy * blit->src_pitch + srcx;
  679. DMA_BLOCK( MGA_AR0, start + w,
  680.    MGA_AR3, start,
  681.    MGA_FXBNDRY, ((dstx + w) << 16) | (dstx & 0xffff),
  682.    MGA_YDSTLEN + MGA_EXEC, (dsty << 16) | h );
  683. }
  684. /* Do something to flush AGP?
  685.  */
  686. /* Force reset of DWGCTL */
  687. DMA_BLOCK( MGA_DMAPAD, 0x00000000,
  688.    MGA_PLNWT, ctx->plnwt,
  689.    MGA_PITCH, dev_priv->front_pitch,
  690.    MGA_DWGCTL, ctx->dwgctl );
  691. ADVANCE_DMA();
  692. }
  693. /* ================================================================
  694.  *
  695.  */
  696. int mga_dma_clear( struct inode *inode, struct file *filp,
  697.    unsigned int cmd, unsigned long arg )
  698. {
  699. drm_file_t *priv = filp->private_data;
  700. drm_device_t *dev = priv->dev;
  701. drm_mga_private_t *dev_priv = dev->dev_private;
  702. drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
  703. drm_mga_clear_t clear;
  704. LOCK_TEST_WITH_RETURN( dev );
  705. if ( copy_from_user( &clear, (drm_mga_clear_t *) arg, sizeof(clear) ) )
  706. return -EFAULT;
  707. if ( sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS )
  708. sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
  709. WRAP_TEST_WITH_RETURN( dev_priv );
  710. mga_dma_dispatch_clear( dev, &clear );
  711. /* Make sure we restore the 3D state next time.
  712.  */
  713. dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT;
  714. return 0;
  715. }
  716. int mga_dma_swap( struct inode *inode, struct file *filp,
  717.   unsigned int cmd, unsigned long arg )
  718. {
  719. drm_file_t *priv = filp->private_data;
  720. drm_device_t *dev = priv->dev;
  721. drm_mga_private_t *dev_priv = dev->dev_private;
  722. drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
  723. LOCK_TEST_WITH_RETURN( dev );
  724. if ( sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS )
  725. sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
  726. WRAP_TEST_WITH_RETURN( dev_priv );
  727. mga_dma_dispatch_swap( dev );
  728. /* Make sure we restore the 3D state next time.
  729.  */
  730. dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT;
  731. return 0;
  732. }
  733. int mga_dma_vertex( struct inode *inode, struct file *filp,
  734.     unsigned int cmd, unsigned long arg )
  735. {
  736. drm_file_t *priv = filp->private_data;
  737. drm_device_t *dev = priv->dev;
  738. drm_mga_private_t *dev_priv = dev->dev_private;
  739. drm_device_dma_t *dma = dev->dma;
  740. drm_buf_t *buf;
  741. drm_mga_buf_priv_t *buf_priv;
  742. drm_mga_vertex_t vertex;
  743. LOCK_TEST_WITH_RETURN( dev );
  744. if ( copy_from_user( &vertex,
  745.      (drm_mga_vertex_t *)arg,
  746.      sizeof(vertex) ) )
  747. return -EFAULT;
  748.         if(vertex.idx < 0 || vertex.idx > dma->buf_count) return -EINVAL;
  749. buf = dma->buflist[vertex.idx];
  750. buf_priv = buf->dev_private;
  751. buf->used = vertex.used;
  752. buf_priv->discard = vertex.discard;
  753. if ( !mga_verify_state( dev_priv ) ) {
  754. if ( vertex.discard ) {
  755. if ( buf_priv->dispatched == 1 )
  756. AGE_BUFFER( buf_priv );
  757. buf_priv->dispatched = 0;
  758. mga_freelist_put( dev, buf );
  759. }
  760. return -EINVAL;
  761. }
  762. WRAP_TEST_WITH_RETURN( dev_priv );
  763. mga_dma_dispatch_vertex( dev, buf );
  764. return 0;
  765. }
  766. int mga_dma_indices( struct inode *inode, struct file *filp,
  767.      unsigned int cmd, unsigned long arg )
  768. {
  769. drm_file_t *priv = filp->private_data;
  770. drm_device_t *dev = priv->dev;
  771. drm_mga_private_t *dev_priv = dev->dev_private;
  772. drm_device_dma_t *dma = dev->dma;
  773. drm_buf_t *buf;
  774. drm_mga_buf_priv_t *buf_priv;
  775. drm_mga_indices_t indices;
  776. LOCK_TEST_WITH_RETURN( dev );
  777. if ( copy_from_user( &indices,
  778.      (drm_mga_indices_t *)arg,
  779.      sizeof(indices) ) )
  780. return -EFAULT;
  781.         if(indices.idx < 0 || indices.idx > dma->buf_count) return -EINVAL;
  782. buf = dma->buflist[indices.idx];
  783. buf_priv = buf->dev_private;
  784. buf_priv->discard = indices.discard;
  785. if ( !mga_verify_state( dev_priv ) ) {
  786. if ( indices.discard ) {
  787. if ( buf_priv->dispatched == 1 )
  788. AGE_BUFFER( buf_priv );
  789. buf_priv->dispatched = 0;
  790. mga_freelist_put( dev, buf );
  791. }
  792. return -EINVAL;
  793. }
  794. WRAP_TEST_WITH_RETURN( dev_priv );
  795. mga_dma_dispatch_indices( dev, buf, indices.start, indices.end );
  796. return 0;
  797. }
  798. int mga_dma_iload( struct inode *inode, struct file *filp,
  799.    unsigned int cmd, unsigned long arg )
  800. {
  801. drm_file_t *priv = filp->private_data;
  802. drm_device_t *dev = priv->dev;
  803. drm_device_dma_t *dma = dev->dma;
  804. drm_mga_private_t *dev_priv = dev->dev_private;
  805. drm_buf_t *buf;
  806. drm_mga_buf_priv_t *buf_priv;
  807. drm_mga_iload_t iload;
  808. DRM_DEBUG( __FUNCTION__ ":n" );
  809. LOCK_TEST_WITH_RETURN( dev );
  810. if ( copy_from_user( &iload, (drm_mga_iload_t *)arg, sizeof(iload) ) )
  811. return -EFAULT;
  812. #if 0
  813. if ( mga_do_wait_for_idle( dev_priv ) < 0 ) {
  814. if ( MGA_DMA_DEBUG )
  815. DRM_INFO( __FUNCTION__": -EBUSYn" );
  816. return -EBUSY;
  817. }
  818. #endif
  819.         if(iload.idx < 0 || iload.idx > dma->buf_count) return -EINVAL;
  820. buf = dma->buflist[iload.idx];
  821. buf_priv = buf->dev_private;
  822. if ( mga_verify_iload( dev_priv, iload.dstorg, iload.length ) ) {
  823. mga_freelist_put( dev, buf );
  824. return -EINVAL;
  825. }
  826. WRAP_TEST_WITH_RETURN( dev_priv );
  827. mga_dma_dispatch_iload( dev, buf, iload.dstorg, iload.length );
  828. /* Make sure we restore the 3D state next time.
  829.  */
  830. dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT;
  831. return 0;
  832. }
  833. int mga_dma_blit( struct inode *inode, struct file *filp,
  834.   unsigned int cmd, unsigned long arg )
  835. {
  836. drm_file_t *priv = filp->private_data;
  837. drm_device_t *dev = priv->dev;
  838. drm_mga_private_t *dev_priv = dev->dev_private;
  839. drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
  840. drm_mga_blit_t blit;
  841. DRM_DEBUG( "%sn", __FUNCTION__ );
  842. LOCK_TEST_WITH_RETURN( dev );
  843. if ( copy_from_user( &blit, (drm_mga_blit_t *)arg, sizeof(blit) ) )
  844. return -EFAULT;
  845. if ( sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS )
  846. sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
  847. if ( mga_verify_blit( dev_priv, blit.srcorg, blit.dstorg ) )
  848. return -EINVAL;
  849. WRAP_TEST_WITH_RETURN( dev_priv );
  850. mga_dma_dispatch_blit( dev, &blit );
  851. /* Make sure we restore the 3D state next time.
  852.  */
  853. dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT;
  854. return 0;
  855. }