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
0029
0030
0031
0032
0033
0034
0035 #include "mga_drv.h"
0036
0037
0038
0039
0040
0041 static void mga_emit_clip_rect(drm_mga_private_t *dev_priv,
0042 struct drm_clip_rect *box)
0043 {
0044 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
0045 drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
0046 unsigned int pitch = dev_priv->front_pitch;
0047 DMA_LOCALS;
0048
0049 BEGIN_DMA(2);
0050
0051
0052
0053 if (dev_priv->chipset >= MGA_CARD_TYPE_G400) {
0054 DMA_BLOCK(MGA_DWGCTL, ctx->dwgctl,
0055 MGA_LEN + MGA_EXEC, 0x80000000,
0056 MGA_DWGCTL, ctx->dwgctl,
0057 MGA_LEN + MGA_EXEC, 0x80000000);
0058 }
0059 DMA_BLOCK(MGA_DMAPAD, 0x00000000,
0060 MGA_CXBNDRY, ((box->x2 - 1) << 16) | box->x1,
0061 MGA_YTOP, box->y1 * pitch, MGA_YBOT, (box->y2 - 1) * pitch);
0062
0063 ADVANCE_DMA();
0064 }
0065
0066 static __inline__ void mga_g200_emit_context(drm_mga_private_t *dev_priv)
0067 {
0068 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
0069 drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
0070 DMA_LOCALS;
0071
0072 BEGIN_DMA(3);
0073
0074 DMA_BLOCK(MGA_DSTORG, ctx->dstorg,
0075 MGA_MACCESS, ctx->maccess,
0076 MGA_PLNWT, ctx->plnwt, MGA_DWGCTL, ctx->dwgctl);
0077
0078 DMA_BLOCK(MGA_ALPHACTRL, ctx->alphactrl,
0079 MGA_FOGCOL, ctx->fogcolor,
0080 MGA_WFLAG, ctx->wflag, MGA_ZORG, dev_priv->depth_offset);
0081
0082 DMA_BLOCK(MGA_FCOL, ctx->fcol,
0083 MGA_DMAPAD, 0x00000000,
0084 MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000);
0085
0086 ADVANCE_DMA();
0087 }
0088
0089 static __inline__ void mga_g400_emit_context(drm_mga_private_t *dev_priv)
0090 {
0091 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
0092 drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
0093 DMA_LOCALS;
0094
0095 BEGIN_DMA(4);
0096
0097 DMA_BLOCK(MGA_DSTORG, ctx->dstorg,
0098 MGA_MACCESS, ctx->maccess,
0099 MGA_PLNWT, ctx->plnwt, MGA_DWGCTL, ctx->dwgctl);
0100
0101 DMA_BLOCK(MGA_ALPHACTRL, ctx->alphactrl,
0102 MGA_FOGCOL, ctx->fogcolor,
0103 MGA_WFLAG, ctx->wflag, MGA_ZORG, dev_priv->depth_offset);
0104
0105 DMA_BLOCK(MGA_WFLAG1, ctx->wflag,
0106 MGA_TDUALSTAGE0, ctx->tdualstage0,
0107 MGA_TDUALSTAGE1, ctx->tdualstage1, MGA_FCOL, ctx->fcol);
0108
0109 DMA_BLOCK(MGA_STENCIL, ctx->stencil,
0110 MGA_STENCILCTL, ctx->stencilctl,
0111 MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000);
0112
0113 ADVANCE_DMA();
0114 }
0115
0116 static __inline__ void mga_g200_emit_tex0(drm_mga_private_t *dev_priv)
0117 {
0118 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
0119 drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[0];
0120 DMA_LOCALS;
0121
0122 BEGIN_DMA(4);
0123
0124 DMA_BLOCK(MGA_TEXCTL2, tex->texctl2,
0125 MGA_TEXCTL, tex->texctl,
0126 MGA_TEXFILTER, tex->texfilter,
0127 MGA_TEXBORDERCOL, tex->texbordercol);
0128
0129 DMA_BLOCK(MGA_TEXORG, tex->texorg,
0130 MGA_TEXORG1, tex->texorg1,
0131 MGA_TEXORG2, tex->texorg2, MGA_TEXORG3, tex->texorg3);
0132
0133 DMA_BLOCK(MGA_TEXORG4, tex->texorg4,
0134 MGA_TEXWIDTH, tex->texwidth,
0135 MGA_TEXHEIGHT, tex->texheight, MGA_WR24, tex->texwidth);
0136
0137 DMA_BLOCK(MGA_WR34, tex->texheight,
0138 MGA_TEXTRANS, 0x0000ffff,
0139 MGA_TEXTRANSHIGH, 0x0000ffff, MGA_DMAPAD, 0x00000000);
0140
0141 ADVANCE_DMA();
0142 }
0143
0144 static __inline__ void mga_g400_emit_tex0(drm_mga_private_t *dev_priv)
0145 {
0146 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
0147 drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[0];
0148 DMA_LOCALS;
0149
0150
0151
0152
0153 BEGIN_DMA(6);
0154
0155 DMA_BLOCK(MGA_TEXCTL2, tex->texctl2 | MGA_G400_TC2_MAGIC,
0156 MGA_TEXCTL, tex->texctl,
0157 MGA_TEXFILTER, tex->texfilter,
0158 MGA_TEXBORDERCOL, tex->texbordercol);
0159
0160 DMA_BLOCK(MGA_TEXORG, tex->texorg,
0161 MGA_TEXORG1, tex->texorg1,
0162 MGA_TEXORG2, tex->texorg2, MGA_TEXORG3, tex->texorg3);
0163
0164 DMA_BLOCK(MGA_TEXORG4, tex->texorg4,
0165 MGA_TEXWIDTH, tex->texwidth,
0166 MGA_TEXHEIGHT, tex->texheight, MGA_WR49, 0x00000000);
0167
0168 DMA_BLOCK(MGA_WR57, 0x00000000,
0169 MGA_WR53, 0x00000000,
0170 MGA_WR61, 0x00000000, MGA_WR52, MGA_G400_WR_MAGIC);
0171
0172 DMA_BLOCK(MGA_WR60, MGA_G400_WR_MAGIC,
0173 MGA_WR54, tex->texwidth | MGA_G400_WR_MAGIC,
0174 MGA_WR62, tex->texheight | MGA_G400_WR_MAGIC,
0175 MGA_DMAPAD, 0x00000000);
0176
0177 DMA_BLOCK(MGA_DMAPAD, 0x00000000,
0178 MGA_DMAPAD, 0x00000000,
0179 MGA_TEXTRANS, 0x0000ffff, MGA_TEXTRANSHIGH, 0x0000ffff);
0180
0181 ADVANCE_DMA();
0182 }
0183
0184 static __inline__ void mga_g400_emit_tex1(drm_mga_private_t *dev_priv)
0185 {
0186 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
0187 drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[1];
0188 DMA_LOCALS;
0189
0190
0191
0192
0193 BEGIN_DMA(5);
0194
0195 DMA_BLOCK(MGA_TEXCTL2, (tex->texctl2 |
0196 MGA_MAP1_ENABLE |
0197 MGA_G400_TC2_MAGIC),
0198 MGA_TEXCTL, tex->texctl,
0199 MGA_TEXFILTER, tex->texfilter,
0200 MGA_TEXBORDERCOL, tex->texbordercol);
0201
0202 DMA_BLOCK(MGA_TEXORG, tex->texorg,
0203 MGA_TEXORG1, tex->texorg1,
0204 MGA_TEXORG2, tex->texorg2, MGA_TEXORG3, tex->texorg3);
0205
0206 DMA_BLOCK(MGA_TEXORG4, tex->texorg4,
0207 MGA_TEXWIDTH, tex->texwidth,
0208 MGA_TEXHEIGHT, tex->texheight, MGA_WR49, 0x00000000);
0209
0210 DMA_BLOCK(MGA_WR57, 0x00000000,
0211 MGA_WR53, 0x00000000,
0212 MGA_WR61, 0x00000000,
0213 MGA_WR52, tex->texwidth | MGA_G400_WR_MAGIC);
0214
0215 DMA_BLOCK(MGA_WR60, tex->texheight | MGA_G400_WR_MAGIC,
0216 MGA_TEXTRANS, 0x0000ffff,
0217 MGA_TEXTRANSHIGH, 0x0000ffff,
0218 MGA_TEXCTL2, tex->texctl2 | MGA_G400_TC2_MAGIC);
0219
0220 ADVANCE_DMA();
0221 }
0222
0223 static __inline__ void mga_g200_emit_pipe(drm_mga_private_t *dev_priv)
0224 {
0225 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
0226 unsigned int pipe = sarea_priv->warp_pipe;
0227 DMA_LOCALS;
0228
0229 BEGIN_DMA(3);
0230
0231 DMA_BLOCK(MGA_WIADDR, MGA_WMODE_SUSPEND,
0232 MGA_WVRTXSZ, 0x00000007,
0233 MGA_WFLAG, 0x00000000, MGA_WR24, 0x00000000);
0234
0235 DMA_BLOCK(MGA_WR25, 0x00000100,
0236 MGA_WR34, 0x00000000,
0237 MGA_WR42, 0x0000ffff, MGA_WR60, 0x0000ffff);
0238
0239
0240
0241 DMA_BLOCK(MGA_DMAPAD, 0xffffffff,
0242 MGA_DMAPAD, 0xffffffff,
0243 MGA_DMAPAD, 0xffffffff,
0244 MGA_WIADDR, (dev_priv->warp_pipe_phys[pipe] |
0245 MGA_WMODE_START | dev_priv->wagp_enable));
0246
0247 ADVANCE_DMA();
0248 }
0249
0250 static __inline__ void mga_g400_emit_pipe(drm_mga_private_t *dev_priv)
0251 {
0252 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
0253 unsigned int pipe = sarea_priv->warp_pipe;
0254 DMA_LOCALS;
0255
0256
0257
0258 BEGIN_DMA(10);
0259
0260 DMA_BLOCK(MGA_WIADDR2, MGA_WMODE_SUSPEND,
0261 MGA_DMAPAD, 0x00000000,
0262 MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000);
0263
0264 if (pipe & MGA_T2) {
0265 DMA_BLOCK(MGA_WVRTXSZ, 0x00001e09,
0266 MGA_DMAPAD, 0x00000000,
0267 MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000);
0268
0269 DMA_BLOCK(MGA_WACCEPTSEQ, 0x00000000,
0270 MGA_WACCEPTSEQ, 0x00000000,
0271 MGA_WACCEPTSEQ, 0x00000000,
0272 MGA_WACCEPTSEQ, 0x1e000000);
0273 } else {
0274 if (dev_priv->warp_pipe & MGA_T2) {
0275
0276 DMA_BLOCK(MGA_YDST, 0x00000000,
0277 MGA_FXLEFT, 0x00000000,
0278 MGA_FXRIGHT, 0x00000001,
0279 MGA_DWGCTL, MGA_DWGCTL_FLUSH);
0280
0281 DMA_BLOCK(MGA_LEN + MGA_EXEC, 0x00000001,
0282 MGA_DWGSYNC, 0x00007000,
0283 MGA_TEXCTL2, MGA_G400_TC2_MAGIC,
0284 MGA_LEN + MGA_EXEC, 0x00000000);
0285
0286 DMA_BLOCK(MGA_TEXCTL2, (MGA_DUALTEX |
0287 MGA_G400_TC2_MAGIC),
0288 MGA_LEN + MGA_EXEC, 0x00000000,
0289 MGA_TEXCTL2, MGA_G400_TC2_MAGIC,
0290 MGA_DMAPAD, 0x00000000);
0291 }
0292
0293 DMA_BLOCK(MGA_WVRTXSZ, 0x00001807,
0294 MGA_DMAPAD, 0x00000000,
0295 MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000);
0296
0297 DMA_BLOCK(MGA_WACCEPTSEQ, 0x00000000,
0298 MGA_WACCEPTSEQ, 0x00000000,
0299 MGA_WACCEPTSEQ, 0x00000000,
0300 MGA_WACCEPTSEQ, 0x18000000);
0301 }
0302
0303 DMA_BLOCK(MGA_WFLAG, 0x00000000,
0304 MGA_WFLAG1, 0x00000000,
0305 MGA_WR56, MGA_G400_WR56_MAGIC, MGA_DMAPAD, 0x00000000);
0306
0307 DMA_BLOCK(MGA_WR49, 0x00000000,
0308 MGA_WR57, 0x00000000,
0309 MGA_WR53, 0x00000000,
0310 MGA_WR61, 0x00000000);
0311
0312 DMA_BLOCK(MGA_WR54, MGA_G400_WR_MAGIC,
0313 MGA_WR62, MGA_G400_WR_MAGIC,
0314 MGA_WR52, MGA_G400_WR_MAGIC,
0315 MGA_WR60, MGA_G400_WR_MAGIC);
0316
0317
0318 DMA_BLOCK(MGA_DMAPAD, 0xffffffff,
0319 MGA_DMAPAD, 0xffffffff,
0320 MGA_DMAPAD, 0xffffffff,
0321 MGA_WIADDR2, (dev_priv->warp_pipe_phys[pipe] |
0322 MGA_WMODE_START | dev_priv->wagp_enable));
0323
0324 ADVANCE_DMA();
0325 }
0326
0327 static void mga_g200_emit_state(drm_mga_private_t *dev_priv)
0328 {
0329 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
0330 unsigned int dirty = sarea_priv->dirty;
0331
0332 if (sarea_priv->warp_pipe != dev_priv->warp_pipe) {
0333 mga_g200_emit_pipe(dev_priv);
0334 dev_priv->warp_pipe = sarea_priv->warp_pipe;
0335 }
0336
0337 if (dirty & MGA_UPLOAD_CONTEXT) {
0338 mga_g200_emit_context(dev_priv);
0339 sarea_priv->dirty &= ~MGA_UPLOAD_CONTEXT;
0340 }
0341
0342 if (dirty & MGA_UPLOAD_TEX0) {
0343 mga_g200_emit_tex0(dev_priv);
0344 sarea_priv->dirty &= ~MGA_UPLOAD_TEX0;
0345 }
0346 }
0347
0348 static void mga_g400_emit_state(drm_mga_private_t *dev_priv)
0349 {
0350 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
0351 unsigned int dirty = sarea_priv->dirty;
0352 int multitex = sarea_priv->warp_pipe & MGA_T2;
0353
0354 if (sarea_priv->warp_pipe != dev_priv->warp_pipe) {
0355 mga_g400_emit_pipe(dev_priv);
0356 dev_priv->warp_pipe = sarea_priv->warp_pipe;
0357 }
0358
0359 if (dirty & MGA_UPLOAD_CONTEXT) {
0360 mga_g400_emit_context(dev_priv);
0361 sarea_priv->dirty &= ~MGA_UPLOAD_CONTEXT;
0362 }
0363
0364 if (dirty & MGA_UPLOAD_TEX0) {
0365 mga_g400_emit_tex0(dev_priv);
0366 sarea_priv->dirty &= ~MGA_UPLOAD_TEX0;
0367 }
0368
0369 if ((dirty & MGA_UPLOAD_TEX1) && multitex) {
0370 mga_g400_emit_tex1(dev_priv);
0371 sarea_priv->dirty &= ~MGA_UPLOAD_TEX1;
0372 }
0373 }
0374
0375
0376
0377
0378
0379
0380
0381 static int mga_verify_context(drm_mga_private_t *dev_priv)
0382 {
0383 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
0384 drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
0385
0386 if (ctx->dstorg != dev_priv->front_offset &&
0387 ctx->dstorg != dev_priv->back_offset) {
0388 DRM_ERROR("*** bad DSTORG: %x (front %x, back %x)\n\n",
0389 ctx->dstorg, dev_priv->front_offset,
0390 dev_priv->back_offset);
0391 ctx->dstorg = 0;
0392 return -EINVAL;
0393 }
0394
0395 return 0;
0396 }
0397
0398
0399
0400 static int mga_verify_tex(drm_mga_private_t *dev_priv, int unit)
0401 {
0402 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
0403 drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[unit];
0404 unsigned int org;
0405
0406 org = tex->texorg & (MGA_TEXORGMAP_MASK | MGA_TEXORGACC_MASK);
0407
0408 if (org == (MGA_TEXORGMAP_SYSMEM | MGA_TEXORGACC_PCI)) {
0409 DRM_ERROR("*** bad TEXORG: 0x%x, unit %d\n", tex->texorg, unit);
0410 tex->texorg = 0;
0411 return -EINVAL;
0412 }
0413
0414 return 0;
0415 }
0416
0417 static int mga_verify_state(drm_mga_private_t *dev_priv)
0418 {
0419 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
0420 unsigned int dirty = sarea_priv->dirty;
0421 int ret = 0;
0422
0423 if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS)
0424 sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
0425
0426 if (dirty & MGA_UPLOAD_CONTEXT)
0427 ret |= mga_verify_context(dev_priv);
0428
0429 if (dirty & MGA_UPLOAD_TEX0)
0430 ret |= mga_verify_tex(dev_priv, 0);
0431
0432 if (dev_priv->chipset >= MGA_CARD_TYPE_G400) {
0433 if (dirty & MGA_UPLOAD_TEX1)
0434 ret |= mga_verify_tex(dev_priv, 1);
0435
0436 if (dirty & MGA_UPLOAD_PIPE)
0437 ret |= (sarea_priv->warp_pipe > MGA_MAX_G400_PIPES);
0438 } else {
0439 if (dirty & MGA_UPLOAD_PIPE)
0440 ret |= (sarea_priv->warp_pipe > MGA_MAX_G200_PIPES);
0441 }
0442
0443 return (ret == 0);
0444 }
0445
0446 static int mga_verify_iload(drm_mga_private_t *dev_priv,
0447 unsigned int dstorg, unsigned int length)
0448 {
0449 if (dstorg < dev_priv->texture_offset ||
0450 dstorg + length > (dev_priv->texture_offset +
0451 dev_priv->texture_size)) {
0452 DRM_ERROR("*** bad iload DSTORG: 0x%x\n", dstorg);
0453 return -EINVAL;
0454 }
0455
0456 if (length & MGA_ILOAD_MASK) {
0457 DRM_ERROR("*** bad iload length: 0x%x\n",
0458 length & MGA_ILOAD_MASK);
0459 return -EINVAL;
0460 }
0461
0462 return 0;
0463 }
0464
0465 static int mga_verify_blit(drm_mga_private_t *dev_priv,
0466 unsigned int srcorg, unsigned int dstorg)
0467 {
0468 if ((srcorg & 0x3) == (MGA_SRCACC_PCI | MGA_SRCMAP_SYSMEM) ||
0469 (dstorg & 0x3) == (MGA_SRCACC_PCI | MGA_SRCMAP_SYSMEM)) {
0470 DRM_ERROR("*** bad blit: src=0x%x dst=0x%x\n", srcorg, dstorg);
0471 return -EINVAL;
0472 }
0473 return 0;
0474 }
0475
0476
0477
0478
0479
0480 static void mga_dma_dispatch_clear(struct drm_device *dev, drm_mga_clear_t *clear)
0481 {
0482 drm_mga_private_t *dev_priv = dev->dev_private;
0483 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
0484 drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
0485 struct drm_clip_rect *pbox = sarea_priv->boxes;
0486 int nbox = sarea_priv->nbox;
0487 int i;
0488 DMA_LOCALS;
0489 DRM_DEBUG("\n");
0490
0491 BEGIN_DMA(1);
0492
0493 DMA_BLOCK(MGA_DMAPAD, 0x00000000,
0494 MGA_DMAPAD, 0x00000000,
0495 MGA_DWGSYNC, 0x00007100, MGA_DWGSYNC, 0x00007000);
0496
0497 ADVANCE_DMA();
0498
0499 for (i = 0; i < nbox; i++) {
0500 struct drm_clip_rect *box = &pbox[i];
0501 u32 height = box->y2 - box->y1;
0502
0503 DRM_DEBUG(" from=%d,%d to=%d,%d\n",
0504 box->x1, box->y1, box->x2, box->y2);
0505
0506 if (clear->flags & MGA_FRONT) {
0507 BEGIN_DMA(2);
0508
0509 DMA_BLOCK(MGA_DMAPAD, 0x00000000,
0510 MGA_PLNWT, clear->color_mask,
0511 MGA_YDSTLEN, (box->y1 << 16) | height,
0512 MGA_FXBNDRY, (box->x2 << 16) | box->x1);
0513
0514 DMA_BLOCK(MGA_DMAPAD, 0x00000000,
0515 MGA_FCOL, clear->clear_color,
0516 MGA_DSTORG, dev_priv->front_offset,
0517 MGA_DWGCTL + MGA_EXEC, dev_priv->clear_cmd);
0518
0519 ADVANCE_DMA();
0520 }
0521
0522 if (clear->flags & MGA_BACK) {
0523 BEGIN_DMA(2);
0524
0525 DMA_BLOCK(MGA_DMAPAD, 0x00000000,
0526 MGA_PLNWT, clear->color_mask,
0527 MGA_YDSTLEN, (box->y1 << 16) | height,
0528 MGA_FXBNDRY, (box->x2 << 16) | box->x1);
0529
0530 DMA_BLOCK(MGA_DMAPAD, 0x00000000,
0531 MGA_FCOL, clear->clear_color,
0532 MGA_DSTORG, dev_priv->back_offset,
0533 MGA_DWGCTL + MGA_EXEC, dev_priv->clear_cmd);
0534
0535 ADVANCE_DMA();
0536 }
0537
0538 if (clear->flags & MGA_DEPTH) {
0539 BEGIN_DMA(2);
0540
0541 DMA_BLOCK(MGA_DMAPAD, 0x00000000,
0542 MGA_PLNWT, clear->depth_mask,
0543 MGA_YDSTLEN, (box->y1 << 16) | height,
0544 MGA_FXBNDRY, (box->x2 << 16) | box->x1);
0545
0546 DMA_BLOCK(MGA_DMAPAD, 0x00000000,
0547 MGA_FCOL, clear->clear_depth,
0548 MGA_DSTORG, dev_priv->depth_offset,
0549 MGA_DWGCTL + MGA_EXEC, dev_priv->clear_cmd);
0550
0551 ADVANCE_DMA();
0552 }
0553
0554 }
0555
0556 BEGIN_DMA(1);
0557
0558
0559 DMA_BLOCK(MGA_DMAPAD, 0x00000000,
0560 MGA_DMAPAD, 0x00000000,
0561 MGA_PLNWT, ctx->plnwt, MGA_DWGCTL, ctx->dwgctl);
0562
0563 ADVANCE_DMA();
0564
0565 FLUSH_DMA();
0566 }
0567
0568 static void mga_dma_dispatch_swap(struct drm_device *dev)
0569 {
0570 drm_mga_private_t *dev_priv = dev->dev_private;
0571 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
0572 drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
0573 struct drm_clip_rect *pbox = sarea_priv->boxes;
0574 int nbox = sarea_priv->nbox;
0575 int i;
0576 DMA_LOCALS;
0577 DRM_DEBUG("\n");
0578
0579 sarea_priv->last_frame.head = dev_priv->prim.tail;
0580 sarea_priv->last_frame.wrap = dev_priv->prim.last_wrap;
0581
0582 BEGIN_DMA(4 + nbox);
0583
0584 DMA_BLOCK(MGA_DMAPAD, 0x00000000,
0585 MGA_DMAPAD, 0x00000000,
0586 MGA_DWGSYNC, 0x00007100, MGA_DWGSYNC, 0x00007000);
0587
0588 DMA_BLOCK(MGA_DSTORG, dev_priv->front_offset,
0589 MGA_MACCESS, dev_priv->maccess,
0590 MGA_SRCORG, dev_priv->back_offset,
0591 MGA_AR5, dev_priv->front_pitch);
0592
0593 DMA_BLOCK(MGA_DMAPAD, 0x00000000,
0594 MGA_DMAPAD, 0x00000000,
0595 MGA_PLNWT, 0xffffffff, MGA_DWGCTL, MGA_DWGCTL_COPY);
0596
0597 for (i = 0; i < nbox; i++) {
0598 struct drm_clip_rect *box = &pbox[i];
0599 u32 height = box->y2 - box->y1;
0600 u32 start = box->y1 * dev_priv->front_pitch;
0601
0602 DRM_DEBUG(" from=%d,%d to=%d,%d\n",
0603 box->x1, box->y1, box->x2, box->y2);
0604
0605 DMA_BLOCK(MGA_AR0, start + box->x2 - 1,
0606 MGA_AR3, start + box->x1,
0607 MGA_FXBNDRY, ((box->x2 - 1) << 16) | box->x1,
0608 MGA_YDSTLEN + MGA_EXEC, (box->y1 << 16) | height);
0609 }
0610
0611 DMA_BLOCK(MGA_DMAPAD, 0x00000000,
0612 MGA_PLNWT, ctx->plnwt,
0613 MGA_SRCORG, dev_priv->front_offset, MGA_DWGCTL, ctx->dwgctl);
0614
0615 ADVANCE_DMA();
0616
0617 FLUSH_DMA();
0618
0619 DRM_DEBUG("... done.\n");
0620 }
0621
0622 static void mga_dma_dispatch_vertex(struct drm_device *dev, struct drm_buf *buf)
0623 {
0624 drm_mga_private_t *dev_priv = dev->dev_private;
0625 drm_mga_buf_priv_t *buf_priv = buf->dev_private;
0626 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
0627 u32 address = (u32) buf->bus_address;
0628 u32 length = (u32) buf->used;
0629 int i = 0;
0630 DMA_LOCALS;
0631 DRM_DEBUG("buf=%d used=%d\n", buf->idx, buf->used);
0632
0633 if (buf->used) {
0634 buf_priv->dispatched = 1;
0635
0636 MGA_EMIT_STATE(dev_priv, sarea_priv->dirty);
0637
0638 do {
0639 if (i < sarea_priv->nbox) {
0640 mga_emit_clip_rect(dev_priv,
0641 &sarea_priv->boxes[i]);
0642 }
0643
0644 BEGIN_DMA(1);
0645
0646 DMA_BLOCK(MGA_DMAPAD, 0x00000000,
0647 MGA_DMAPAD, 0x00000000,
0648 MGA_SECADDRESS, (address |
0649 MGA_DMA_VERTEX),
0650 MGA_SECEND, ((address + length) |
0651 dev_priv->dma_access));
0652
0653 ADVANCE_DMA();
0654 } while (++i < sarea_priv->nbox);
0655 }
0656
0657 if (buf_priv->discard) {
0658 AGE_BUFFER(buf_priv);
0659 buf->pending = 0;
0660 buf->used = 0;
0661 buf_priv->dispatched = 0;
0662
0663 mga_freelist_put(dev, buf);
0664 }
0665
0666 FLUSH_DMA();
0667 }
0668
0669 static void mga_dma_dispatch_indices(struct drm_device *dev, struct drm_buf *buf,
0670 unsigned int start, unsigned int end)
0671 {
0672 drm_mga_private_t *dev_priv = dev->dev_private;
0673 drm_mga_buf_priv_t *buf_priv = buf->dev_private;
0674 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
0675 u32 address = (u32) buf->bus_address;
0676 int i = 0;
0677 DMA_LOCALS;
0678 DRM_DEBUG("buf=%d start=%d end=%d\n", buf->idx, start, end);
0679
0680 if (start != end) {
0681 buf_priv->dispatched = 1;
0682
0683 MGA_EMIT_STATE(dev_priv, sarea_priv->dirty);
0684
0685 do {
0686 if (i < sarea_priv->nbox) {
0687 mga_emit_clip_rect(dev_priv,
0688 &sarea_priv->boxes[i]);
0689 }
0690
0691 BEGIN_DMA(1);
0692
0693 DMA_BLOCK(MGA_DMAPAD, 0x00000000,
0694 MGA_DMAPAD, 0x00000000,
0695 MGA_SETUPADDRESS, address + start,
0696 MGA_SETUPEND, ((address + end) |
0697 dev_priv->dma_access));
0698
0699 ADVANCE_DMA();
0700 } while (++i < sarea_priv->nbox);
0701 }
0702
0703 if (buf_priv->discard) {
0704 AGE_BUFFER(buf_priv);
0705 buf->pending = 0;
0706 buf->used = 0;
0707 buf_priv->dispatched = 0;
0708
0709 mga_freelist_put(dev, buf);
0710 }
0711
0712 FLUSH_DMA();
0713 }
0714
0715
0716
0717
0718 static void mga_dma_dispatch_iload(struct drm_device *dev, struct drm_buf *buf,
0719 unsigned int dstorg, unsigned int length)
0720 {
0721 drm_mga_private_t *dev_priv = dev->dev_private;
0722 drm_mga_buf_priv_t *buf_priv = buf->dev_private;
0723 drm_mga_context_regs_t *ctx = &dev_priv->sarea_priv->context_state;
0724 u32 srcorg =
0725 buf->bus_address | dev_priv->dma_access | MGA_SRCMAP_SYSMEM;
0726 u32 y2;
0727 DMA_LOCALS;
0728 DRM_DEBUG("buf=%d used=%d\n", buf->idx, buf->used);
0729
0730 y2 = length / 64;
0731
0732 BEGIN_DMA(5);
0733
0734 DMA_BLOCK(MGA_DMAPAD, 0x00000000,
0735 MGA_DMAPAD, 0x00000000,
0736 MGA_DWGSYNC, 0x00007100, MGA_DWGSYNC, 0x00007000);
0737
0738 DMA_BLOCK(MGA_DSTORG, dstorg,
0739 MGA_MACCESS, 0x00000000, MGA_SRCORG, srcorg, MGA_AR5, 64);
0740
0741 DMA_BLOCK(MGA_PITCH, 64,
0742 MGA_PLNWT, 0xffffffff,
0743 MGA_DMAPAD, 0x00000000, MGA_DWGCTL, MGA_DWGCTL_COPY);
0744
0745 DMA_BLOCK(MGA_AR0, 63,
0746 MGA_AR3, 0,
0747 MGA_FXBNDRY, (63 << 16) | 0, MGA_YDSTLEN + MGA_EXEC, y2);
0748
0749 DMA_BLOCK(MGA_PLNWT, ctx->plnwt,
0750 MGA_SRCORG, dev_priv->front_offset,
0751 MGA_PITCH, dev_priv->front_pitch, MGA_DWGSYNC, 0x00007000);
0752
0753 ADVANCE_DMA();
0754
0755 AGE_BUFFER(buf_priv);
0756
0757 buf->pending = 0;
0758 buf->used = 0;
0759 buf_priv->dispatched = 0;
0760
0761 mga_freelist_put(dev, buf);
0762
0763 FLUSH_DMA();
0764 }
0765
0766 static void mga_dma_dispatch_blit(struct drm_device *dev, drm_mga_blit_t *blit)
0767 {
0768 drm_mga_private_t *dev_priv = dev->dev_private;
0769 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
0770 drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
0771 struct drm_clip_rect *pbox = sarea_priv->boxes;
0772 int nbox = sarea_priv->nbox;
0773 u32 scandir = 0, i;
0774 DMA_LOCALS;
0775 DRM_DEBUG("\n");
0776
0777 BEGIN_DMA(4 + nbox);
0778
0779 DMA_BLOCK(MGA_DMAPAD, 0x00000000,
0780 MGA_DMAPAD, 0x00000000,
0781 MGA_DWGSYNC, 0x00007100, MGA_DWGSYNC, 0x00007000);
0782
0783 DMA_BLOCK(MGA_DWGCTL, MGA_DWGCTL_COPY,
0784 MGA_PLNWT, blit->planemask,
0785 MGA_SRCORG, blit->srcorg, MGA_DSTORG, blit->dstorg);
0786
0787 DMA_BLOCK(MGA_SGN, scandir,
0788 MGA_MACCESS, dev_priv->maccess,
0789 MGA_AR5, blit->ydir * blit->src_pitch,
0790 MGA_PITCH, blit->dst_pitch);
0791
0792 for (i = 0; i < nbox; i++) {
0793 int srcx = pbox[i].x1 + blit->delta_sx;
0794 int srcy = pbox[i].y1 + blit->delta_sy;
0795 int dstx = pbox[i].x1 + blit->delta_dx;
0796 int dsty = pbox[i].y1 + blit->delta_dy;
0797 int h = pbox[i].y2 - pbox[i].y1;
0798 int w = pbox[i].x2 - pbox[i].x1 - 1;
0799 int start;
0800
0801 if (blit->ydir == -1)
0802 srcy = blit->height - srcy - 1;
0803
0804 start = srcy * blit->src_pitch + srcx;
0805
0806 DMA_BLOCK(MGA_AR0, start + w,
0807 MGA_AR3, start,
0808 MGA_FXBNDRY, ((dstx + w) << 16) | (dstx & 0xffff),
0809 MGA_YDSTLEN + MGA_EXEC, (dsty << 16) | h);
0810 }
0811
0812
0813
0814
0815
0816 DMA_BLOCK(MGA_DMAPAD, 0x00000000,
0817 MGA_PLNWT, ctx->plnwt,
0818 MGA_PITCH, dev_priv->front_pitch, MGA_DWGCTL, ctx->dwgctl);
0819
0820 ADVANCE_DMA();
0821 }
0822
0823
0824
0825
0826
0827 static int mga_dma_clear(struct drm_device *dev, void *data, struct drm_file *file_priv)
0828 {
0829 drm_mga_private_t *dev_priv = dev->dev_private;
0830 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
0831 drm_mga_clear_t *clear = data;
0832
0833 LOCK_TEST_WITH_RETURN(dev, file_priv);
0834
0835 if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS)
0836 sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
0837
0838 WRAP_TEST_WITH_RETURN(dev_priv);
0839
0840 mga_dma_dispatch_clear(dev, clear);
0841
0842
0843
0844 dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT;
0845
0846 return 0;
0847 }
0848
0849 static int mga_dma_swap(struct drm_device *dev, void *data, struct drm_file *file_priv)
0850 {
0851 drm_mga_private_t *dev_priv = dev->dev_private;
0852 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
0853
0854 LOCK_TEST_WITH_RETURN(dev, file_priv);
0855
0856 if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS)
0857 sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
0858
0859 WRAP_TEST_WITH_RETURN(dev_priv);
0860
0861 mga_dma_dispatch_swap(dev);
0862
0863
0864
0865 dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT;
0866
0867 return 0;
0868 }
0869
0870 static int mga_dma_vertex(struct drm_device *dev, void *data, struct drm_file *file_priv)
0871 {
0872 drm_mga_private_t *dev_priv = dev->dev_private;
0873 struct drm_device_dma *dma = dev->dma;
0874 struct drm_buf *buf;
0875 drm_mga_buf_priv_t *buf_priv;
0876 drm_mga_vertex_t *vertex = data;
0877
0878 LOCK_TEST_WITH_RETURN(dev, file_priv);
0879
0880 if (vertex->idx < 0 || vertex->idx > dma->buf_count)
0881 return -EINVAL;
0882 buf = dma->buflist[vertex->idx];
0883 buf_priv = buf->dev_private;
0884
0885 buf->used = vertex->used;
0886 buf_priv->discard = vertex->discard;
0887
0888 if (!mga_verify_state(dev_priv)) {
0889 if (vertex->discard) {
0890 if (buf_priv->dispatched == 1)
0891 AGE_BUFFER(buf_priv);
0892 buf_priv->dispatched = 0;
0893 mga_freelist_put(dev, buf);
0894 }
0895 return -EINVAL;
0896 }
0897
0898 WRAP_TEST_WITH_RETURN(dev_priv);
0899
0900 mga_dma_dispatch_vertex(dev, buf);
0901
0902 return 0;
0903 }
0904
0905 static int mga_dma_indices(struct drm_device *dev, void *data, struct drm_file *file_priv)
0906 {
0907 drm_mga_private_t *dev_priv = dev->dev_private;
0908 struct drm_device_dma *dma = dev->dma;
0909 struct drm_buf *buf;
0910 drm_mga_buf_priv_t *buf_priv;
0911 drm_mga_indices_t *indices = data;
0912
0913 LOCK_TEST_WITH_RETURN(dev, file_priv);
0914
0915 if (indices->idx < 0 || indices->idx > dma->buf_count)
0916 return -EINVAL;
0917
0918 buf = dma->buflist[indices->idx];
0919 buf_priv = buf->dev_private;
0920
0921 buf_priv->discard = indices->discard;
0922
0923 if (!mga_verify_state(dev_priv)) {
0924 if (indices->discard) {
0925 if (buf_priv->dispatched == 1)
0926 AGE_BUFFER(buf_priv);
0927 buf_priv->dispatched = 0;
0928 mga_freelist_put(dev, buf);
0929 }
0930 return -EINVAL;
0931 }
0932
0933 WRAP_TEST_WITH_RETURN(dev_priv);
0934
0935 mga_dma_dispatch_indices(dev, buf, indices->start, indices->end);
0936
0937 return 0;
0938 }
0939
0940 static int mga_dma_iload(struct drm_device *dev, void *data, struct drm_file *file_priv)
0941 {
0942 struct drm_device_dma *dma = dev->dma;
0943 drm_mga_private_t *dev_priv = dev->dev_private;
0944 struct drm_buf *buf;
0945 drm_mga_iload_t *iload = data;
0946 DRM_DEBUG("\n");
0947
0948 LOCK_TEST_WITH_RETURN(dev, file_priv);
0949
0950 #if 0
0951 if (mga_do_wait_for_idle(dev_priv) < 0) {
0952 if (MGA_DMA_DEBUG)
0953 DRM_INFO("-EBUSY\n");
0954 return -EBUSY;
0955 }
0956 #endif
0957 if (iload->idx < 0 || iload->idx > dma->buf_count)
0958 return -EINVAL;
0959
0960 buf = dma->buflist[iload->idx];
0961
0962 if (mga_verify_iload(dev_priv, iload->dstorg, iload->length)) {
0963 mga_freelist_put(dev, buf);
0964 return -EINVAL;
0965 }
0966
0967 WRAP_TEST_WITH_RETURN(dev_priv);
0968
0969 mga_dma_dispatch_iload(dev, buf, iload->dstorg, iload->length);
0970
0971
0972
0973 dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT;
0974
0975 return 0;
0976 }
0977
0978 static int mga_dma_blit(struct drm_device *dev, void *data, struct drm_file *file_priv)
0979 {
0980 drm_mga_private_t *dev_priv = dev->dev_private;
0981 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
0982 drm_mga_blit_t *blit = data;
0983 DRM_DEBUG("\n");
0984
0985 LOCK_TEST_WITH_RETURN(dev, file_priv);
0986
0987 if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS)
0988 sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
0989
0990 if (mga_verify_blit(dev_priv, blit->srcorg, blit->dstorg))
0991 return -EINVAL;
0992
0993 WRAP_TEST_WITH_RETURN(dev_priv);
0994
0995 mga_dma_dispatch_blit(dev, blit);
0996
0997
0998
0999 dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT;
1000
1001 return 0;
1002 }
1003
1004 int mga_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv)
1005 {
1006 drm_mga_private_t *dev_priv = dev->dev_private;
1007 drm_mga_getparam_t *param = data;
1008 struct pci_dev *pdev = to_pci_dev(dev->dev);
1009 int value;
1010
1011 if (!dev_priv) {
1012 DRM_ERROR("called with no initialization\n");
1013 return -EINVAL;
1014 }
1015
1016 DRM_DEBUG("pid=%d\n", task_pid_nr(current));
1017
1018 switch (param->param) {
1019 case MGA_PARAM_IRQ_NR:
1020 value = pdev->irq;
1021 break;
1022 case MGA_PARAM_CARD_TYPE:
1023 value = dev_priv->chipset;
1024 break;
1025 default:
1026 return -EINVAL;
1027 }
1028
1029 if (copy_to_user(param->value, &value, sizeof(int))) {
1030 DRM_ERROR("copy_to_user\n");
1031 return -EFAULT;
1032 }
1033
1034 return 0;
1035 }
1036
1037 static int mga_set_fence(struct drm_device *dev, void *data, struct drm_file *file_priv)
1038 {
1039 drm_mga_private_t *dev_priv = dev->dev_private;
1040 u32 *fence = data;
1041 DMA_LOCALS;
1042
1043 if (!dev_priv) {
1044 DRM_ERROR("called with no initialization\n");
1045 return -EINVAL;
1046 }
1047
1048 DRM_DEBUG("pid=%d\n", task_pid_nr(current));
1049
1050
1051
1052
1053
1054 *fence = dev_priv->next_fence_to_post;
1055 dev_priv->next_fence_to_post++;
1056
1057 BEGIN_DMA(1);
1058 DMA_BLOCK(MGA_DMAPAD, 0x00000000,
1059 MGA_DMAPAD, 0x00000000,
1060 MGA_DMAPAD, 0x00000000, MGA_SOFTRAP, 0x00000000);
1061 ADVANCE_DMA();
1062
1063 return 0;
1064 }
1065
1066 static int mga_wait_fence(struct drm_device *dev, void *data, struct drm_file *
1067 file_priv)
1068 {
1069 drm_mga_private_t *dev_priv = dev->dev_private;
1070 u32 *fence = data;
1071
1072 if (!dev_priv) {
1073 DRM_ERROR("called with no initialization\n");
1074 return -EINVAL;
1075 }
1076
1077 DRM_DEBUG("pid=%d\n", task_pid_nr(current));
1078
1079 mga_driver_fence_wait(dev, fence);
1080 return 0;
1081 }
1082
1083 const struct drm_ioctl_desc mga_ioctls[] = {
1084 DRM_IOCTL_DEF_DRV(MGA_INIT, mga_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
1085 DRM_IOCTL_DEF_DRV(MGA_FLUSH, mga_dma_flush, DRM_AUTH),
1086 DRM_IOCTL_DEF_DRV(MGA_RESET, mga_dma_reset, DRM_AUTH),
1087 DRM_IOCTL_DEF_DRV(MGA_SWAP, mga_dma_swap, DRM_AUTH),
1088 DRM_IOCTL_DEF_DRV(MGA_CLEAR, mga_dma_clear, DRM_AUTH),
1089 DRM_IOCTL_DEF_DRV(MGA_VERTEX, mga_dma_vertex, DRM_AUTH),
1090 DRM_IOCTL_DEF_DRV(MGA_INDICES, mga_dma_indices, DRM_AUTH),
1091 DRM_IOCTL_DEF_DRV(MGA_ILOAD, mga_dma_iload, DRM_AUTH),
1092 DRM_IOCTL_DEF_DRV(MGA_BLIT, mga_dma_blit, DRM_AUTH),
1093 DRM_IOCTL_DEF_DRV(MGA_GETPARAM, mga_getparam, DRM_AUTH),
1094 DRM_IOCTL_DEF_DRV(MGA_SET_FENCE, mga_set_fence, DRM_AUTH),
1095 DRM_IOCTL_DEF_DRV(MGA_WAIT_FENCE, mga_wait_fence, DRM_AUTH),
1096 DRM_IOCTL_DEF_DRV(MGA_DMA_BOOTSTRAP, mga_dma_bootstrap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
1097 };
1098
1099 int mga_max_ioctl = ARRAY_SIZE(mga_ioctls);