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 #include <drm/drm_device.h>
0032 #include <drm/drm_legacy.h>
0033 #include <drm/via_drm.h>
0034
0035 #include "via_3d_reg.h"
0036 #include "via_drv.h"
0037 #include "via_verifier.h"
0038
0039 typedef enum {
0040 state_command,
0041 state_header2,
0042 state_header1,
0043 state_vheader5,
0044 state_vheader6,
0045 state_error
0046 } verifier_state_t;
0047
0048 typedef enum {
0049 no_check = 0,
0050 check_for_header2,
0051 check_for_header1,
0052 check_for_header2_err,
0053 check_for_header1_err,
0054 check_for_fire,
0055 check_z_buffer_addr0,
0056 check_z_buffer_addr1,
0057 check_z_buffer_addr_mode,
0058 check_destination_addr0,
0059 check_destination_addr1,
0060 check_destination_addr_mode,
0061 check_for_dummy,
0062 check_for_dd,
0063 check_texture_addr0,
0064 check_texture_addr1,
0065 check_texture_addr2,
0066 check_texture_addr3,
0067 check_texture_addr4,
0068 check_texture_addr5,
0069 check_texture_addr6,
0070 check_texture_addr7,
0071 check_texture_addr8,
0072 check_texture_addr_mode,
0073 check_for_vertex_count,
0074 check_number_texunits,
0075 forbidden_command
0076 } hazard_t;
0077
0078
0079
0080
0081
0082
0083
0084
0085 static drm_via_sequence_t seqs[] = {
0086 no_sequence,
0087 no_sequence,
0088 no_sequence,
0089 no_sequence,
0090 no_sequence,
0091 no_sequence,
0092 z_address,
0093 z_address,
0094 z_address,
0095 dest_address,
0096 dest_address,
0097 dest_address,
0098 no_sequence,
0099 no_sequence,
0100 tex_address,
0101 tex_address,
0102 tex_address,
0103 tex_address,
0104 tex_address,
0105 tex_address,
0106 tex_address,
0107 tex_address,
0108 tex_address,
0109 tex_address,
0110 no_sequence
0111 };
0112
0113 typedef struct {
0114 unsigned int code;
0115 hazard_t hz;
0116 } hz_init_t;
0117
0118 static hz_init_t init_table1[] = {
0119 {0xf2, check_for_header2_err},
0120 {0xf0, check_for_header1_err},
0121 {0xee, check_for_fire},
0122 {0xcc, check_for_dummy},
0123 {0xdd, check_for_dd},
0124 {0x00, no_check},
0125 {0x10, check_z_buffer_addr0},
0126 {0x11, check_z_buffer_addr1},
0127 {0x12, check_z_buffer_addr_mode},
0128 {0x13, no_check},
0129 {0x14, no_check},
0130 {0x15, no_check},
0131 {0x23, no_check},
0132 {0x24, no_check},
0133 {0x33, no_check},
0134 {0x34, no_check},
0135 {0x35, no_check},
0136 {0x36, no_check},
0137 {0x37, no_check},
0138 {0x38, no_check},
0139 {0x39, no_check},
0140 {0x3A, no_check},
0141 {0x3B, no_check},
0142 {0x3C, no_check},
0143 {0x3D, no_check},
0144 {0x3E, no_check},
0145 {0x40, check_destination_addr0},
0146 {0x41, check_destination_addr1},
0147 {0x42, check_destination_addr_mode},
0148 {0x43, no_check},
0149 {0x44, no_check},
0150 {0x50, no_check},
0151 {0x51, no_check},
0152 {0x52, no_check},
0153 {0x53, no_check},
0154 {0x54, no_check},
0155 {0x55, no_check},
0156 {0x56, no_check},
0157 {0x57, no_check},
0158 {0x58, no_check},
0159 {0x70, no_check},
0160 {0x71, no_check},
0161 {0x78, no_check},
0162 {0x79, no_check},
0163 {0x7A, no_check},
0164 {0x7B, no_check},
0165 {0x7C, no_check},
0166 {0x7D, check_for_vertex_count}
0167 };
0168
0169 static hz_init_t init_table2[] = {
0170 {0xf2, check_for_header2_err},
0171 {0xf0, check_for_header1_err},
0172 {0xee, check_for_fire},
0173 {0xcc, check_for_dummy},
0174 {0x00, check_texture_addr0},
0175 {0x01, check_texture_addr0},
0176 {0x02, check_texture_addr0},
0177 {0x03, check_texture_addr0},
0178 {0x04, check_texture_addr0},
0179 {0x05, check_texture_addr0},
0180 {0x06, check_texture_addr0},
0181 {0x07, check_texture_addr0},
0182 {0x08, check_texture_addr0},
0183 {0x09, check_texture_addr0},
0184 {0x20, check_texture_addr1},
0185 {0x21, check_texture_addr1},
0186 {0x22, check_texture_addr1},
0187 {0x23, check_texture_addr4},
0188 {0x2B, check_texture_addr3},
0189 {0x2C, check_texture_addr3},
0190 {0x2D, check_texture_addr3},
0191 {0x2E, check_texture_addr3},
0192 {0x2F, check_texture_addr3},
0193 {0x30, check_texture_addr3},
0194 {0x31, check_texture_addr3},
0195 {0x32, check_texture_addr3},
0196 {0x33, check_texture_addr3},
0197 {0x34, check_texture_addr3},
0198 {0x4B, check_texture_addr5},
0199 {0x4C, check_texture_addr6},
0200 {0x51, check_texture_addr7},
0201 {0x52, check_texture_addr8},
0202 {0x77, check_texture_addr2},
0203 {0x78, no_check},
0204 {0x79, no_check},
0205 {0x7A, no_check},
0206 {0x7B, check_texture_addr_mode},
0207 {0x7C, no_check},
0208 {0x7D, no_check},
0209 {0x7E, no_check},
0210 {0x7F, no_check},
0211 {0x80, no_check},
0212 {0x81, no_check},
0213 {0x82, no_check},
0214 {0x83, no_check},
0215 {0x85, no_check},
0216 {0x86, no_check},
0217 {0x87, no_check},
0218 {0x88, no_check},
0219 {0x89, no_check},
0220 {0x8A, no_check},
0221 {0x90, no_check},
0222 {0x91, no_check},
0223 {0x92, no_check},
0224 {0x93, no_check}
0225 };
0226
0227 static hz_init_t init_table3[] = {
0228 {0xf2, check_for_header2_err},
0229 {0xf0, check_for_header1_err},
0230 {0xcc, check_for_dummy},
0231 {0x00, check_number_texunits}
0232 };
0233
0234 static hazard_t table1[256];
0235 static hazard_t table2[256];
0236 static hazard_t table3[256];
0237
0238 static __inline__ int
0239 eat_words(const uint32_t **buf, const uint32_t *buf_end, unsigned num_words)
0240 {
0241 if ((buf_end - *buf) >= num_words) {
0242 *buf += num_words;
0243 return 0;
0244 }
0245 DRM_ERROR("Illegal termination of DMA command buffer\n");
0246 return 1;
0247 }
0248
0249
0250
0251
0252
0253 static __inline__ drm_local_map_t *via_drm_lookup_agp_map(drm_via_state_t *seq,
0254 unsigned long offset,
0255 unsigned long size,
0256 struct drm_device *dev)
0257 {
0258 struct drm_map_list *r_list;
0259 drm_local_map_t *map = seq->map_cache;
0260
0261 if (map && map->offset <= offset
0262 && (offset + size) <= (map->offset + map->size)) {
0263 return map;
0264 }
0265
0266 list_for_each_entry(r_list, &dev->maplist, head) {
0267 map = r_list->map;
0268 if (!map)
0269 continue;
0270 if (map->offset <= offset
0271 && (offset + size) <= (map->offset + map->size)
0272 && !(map->flags & _DRM_RESTRICTED)
0273 && (map->type == _DRM_AGP)) {
0274 seq->map_cache = map;
0275 return map;
0276 }
0277 }
0278 return NULL;
0279 }
0280
0281
0282
0283
0284
0285
0286
0287
0288
0289
0290 static __inline__ int finish_current_sequence(drm_via_state_t * cur_seq)
0291 {
0292 switch (cur_seq->unfinished) {
0293 case z_address:
0294 DRM_DEBUG("Z Buffer start address is 0x%x\n", cur_seq->z_addr);
0295 break;
0296 case dest_address:
0297 DRM_DEBUG("Destination start address is 0x%x\n",
0298 cur_seq->d_addr);
0299 break;
0300 case tex_address:
0301 if (cur_seq->agp_texture) {
0302 unsigned start =
0303 cur_seq->tex_level_lo[cur_seq->texture];
0304 unsigned end = cur_seq->tex_level_hi[cur_seq->texture];
0305 unsigned long lo = ~0, hi = 0, tmp;
0306 uint32_t *addr, *pitch, *height, tex;
0307 unsigned i;
0308 int npot;
0309
0310 if (end > 9)
0311 end = 9;
0312 if (start > 9)
0313 start = 9;
0314
0315 addr =
0316 &(cur_seq->t_addr[tex = cur_seq->texture][start]);
0317 pitch = &(cur_seq->pitch[tex][start]);
0318 height = &(cur_seq->height[tex][start]);
0319 npot = cur_seq->tex_npot[tex];
0320 for (i = start; i <= end; ++i) {
0321 tmp = *addr++;
0322 if (tmp < lo)
0323 lo = tmp;
0324 if (i == 0 && npot)
0325 tmp += (*height++ * *pitch++);
0326 else
0327 tmp += (*height++ << *pitch++);
0328 if (tmp > hi)
0329 hi = tmp;
0330 }
0331
0332 if (!via_drm_lookup_agp_map
0333 (cur_seq, lo, hi - lo, cur_seq->dev)) {
0334 DRM_ERROR
0335 ("AGP texture is not in allowed map\n");
0336 return 2;
0337 }
0338 }
0339 break;
0340 default:
0341 break;
0342 }
0343 cur_seq->unfinished = no_sequence;
0344 return 0;
0345 }
0346
0347 static __inline__ int
0348 investigate_hazard(uint32_t cmd, hazard_t hz, drm_via_state_t *cur_seq)
0349 {
0350 register uint32_t tmp, *tmp_addr;
0351
0352 if (cur_seq->unfinished && (cur_seq->unfinished != seqs[hz])) {
0353 int ret;
0354 if ((ret = finish_current_sequence(cur_seq)))
0355 return ret;
0356 }
0357
0358 switch (hz) {
0359 case check_for_header2:
0360 if (cmd == HALCYON_HEADER2)
0361 return 1;
0362 return 0;
0363 case check_for_header1:
0364 if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1)
0365 return 1;
0366 return 0;
0367 case check_for_header2_err:
0368 if (cmd == HALCYON_HEADER2)
0369 return 1;
0370 DRM_ERROR("Illegal DMA HALCYON_HEADER2 command\n");
0371 break;
0372 case check_for_header1_err:
0373 if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1)
0374 return 1;
0375 DRM_ERROR("Illegal DMA HALCYON_HEADER1 command\n");
0376 break;
0377 case check_for_fire:
0378 if ((cmd & HALCYON_FIREMASK) == HALCYON_FIRECMD)
0379 return 1;
0380 DRM_ERROR("Illegal DMA HALCYON_FIRECMD command\n");
0381 break;
0382 case check_for_dummy:
0383 if (HC_DUMMY == cmd)
0384 return 0;
0385 DRM_ERROR("Illegal DMA HC_DUMMY command\n");
0386 break;
0387 case check_for_dd:
0388 if (0xdddddddd == cmd)
0389 return 0;
0390 DRM_ERROR("Illegal DMA 0xdddddddd command\n");
0391 break;
0392 case check_z_buffer_addr0:
0393 cur_seq->unfinished = z_address;
0394 cur_seq->z_addr = (cur_seq->z_addr & 0xFF000000) |
0395 (cmd & 0x00FFFFFF);
0396 return 0;
0397 case check_z_buffer_addr1:
0398 cur_seq->unfinished = z_address;
0399 cur_seq->z_addr = (cur_seq->z_addr & 0x00FFFFFF) |
0400 ((cmd & 0xFF) << 24);
0401 return 0;
0402 case check_z_buffer_addr_mode:
0403 cur_seq->unfinished = z_address;
0404 if ((cmd & 0x0000C000) == 0)
0405 return 0;
0406 DRM_ERROR("Attempt to place Z buffer in system memory\n");
0407 return 2;
0408 case check_destination_addr0:
0409 cur_seq->unfinished = dest_address;
0410 cur_seq->d_addr = (cur_seq->d_addr & 0xFF000000) |
0411 (cmd & 0x00FFFFFF);
0412 return 0;
0413 case check_destination_addr1:
0414 cur_seq->unfinished = dest_address;
0415 cur_seq->d_addr = (cur_seq->d_addr & 0x00FFFFFF) |
0416 ((cmd & 0xFF) << 24);
0417 return 0;
0418 case check_destination_addr_mode:
0419 cur_seq->unfinished = dest_address;
0420 if ((cmd & 0x0000C000) == 0)
0421 return 0;
0422 DRM_ERROR
0423 ("Attempt to place 3D drawing buffer in system memory\n");
0424 return 2;
0425 case check_texture_addr0:
0426 cur_seq->unfinished = tex_address;
0427 tmp = (cmd >> 24);
0428 tmp_addr = &cur_seq->t_addr[cur_seq->texture][tmp];
0429 *tmp_addr = (*tmp_addr & 0xFF000000) | (cmd & 0x00FFFFFF);
0430 return 0;
0431 case check_texture_addr1:
0432 cur_seq->unfinished = tex_address;
0433 tmp = ((cmd >> 24) - 0x20);
0434 tmp += tmp << 1;
0435 tmp_addr = &cur_seq->t_addr[cur_seq->texture][tmp];
0436 *tmp_addr = (*tmp_addr & 0x00FFFFFF) | ((cmd & 0xFF) << 24);
0437 tmp_addr++;
0438 *tmp_addr = (*tmp_addr & 0x00FFFFFF) | ((cmd & 0xFF00) << 16);
0439 tmp_addr++;
0440 *tmp_addr = (*tmp_addr & 0x00FFFFFF) | ((cmd & 0xFF0000) << 8);
0441 return 0;
0442 case check_texture_addr2:
0443 cur_seq->unfinished = tex_address;
0444 cur_seq->tex_level_lo[tmp = cur_seq->texture] = cmd & 0x3F;
0445 cur_seq->tex_level_hi[tmp] = (cmd & 0xFC0) >> 6;
0446 return 0;
0447 case check_texture_addr3:
0448 cur_seq->unfinished = tex_address;
0449 tmp = ((cmd >> 24) - HC_SubA_HTXnL0Pit);
0450 if (tmp == 0 &&
0451 (cmd & HC_HTXnEnPit_MASK)) {
0452 cur_seq->pitch[cur_seq->texture][tmp] =
0453 (cmd & HC_HTXnLnPit_MASK);
0454 cur_seq->tex_npot[cur_seq->texture] = 1;
0455 } else {
0456 cur_seq->pitch[cur_seq->texture][tmp] =
0457 (cmd & HC_HTXnLnPitE_MASK) >> HC_HTXnLnPitE_SHIFT;
0458 cur_seq->tex_npot[cur_seq->texture] = 0;
0459 if (cmd & 0x000FFFFF) {
0460 DRM_ERROR
0461 ("Unimplemented texture level 0 pitch mode.\n");
0462 return 2;
0463 }
0464 }
0465 return 0;
0466 case check_texture_addr4:
0467 cur_seq->unfinished = tex_address;
0468 tmp_addr = &cur_seq->t_addr[cur_seq->texture][9];
0469 *tmp_addr = (*tmp_addr & 0x00FFFFFF) | ((cmd & 0xFF) << 24);
0470 return 0;
0471 case check_texture_addr5:
0472 case check_texture_addr6:
0473 cur_seq->unfinished = tex_address;
0474
0475
0476
0477 return 0;
0478 case check_texture_addr7:
0479 cur_seq->unfinished = tex_address;
0480 tmp_addr = &(cur_seq->height[cur_seq->texture][0]);
0481 tmp_addr[5] = 1 << ((cmd & 0x00F00000) >> 20);
0482 tmp_addr[4] = 1 << ((cmd & 0x000F0000) >> 16);
0483 tmp_addr[3] = 1 << ((cmd & 0x0000F000) >> 12);
0484 tmp_addr[2] = 1 << ((cmd & 0x00000F00) >> 8);
0485 tmp_addr[1] = 1 << ((cmd & 0x000000F0) >> 4);
0486 tmp_addr[0] = 1 << (cmd & 0x0000000F);
0487 return 0;
0488 case check_texture_addr8:
0489 cur_seq->unfinished = tex_address;
0490 tmp_addr = &(cur_seq->height[cur_seq->texture][0]);
0491 tmp_addr[9] = 1 << ((cmd & 0x0000F000) >> 12);
0492 tmp_addr[8] = 1 << ((cmd & 0x00000F00) >> 8);
0493 tmp_addr[7] = 1 << ((cmd & 0x000000F0) >> 4);
0494 tmp_addr[6] = 1 << (cmd & 0x0000000F);
0495 return 0;
0496 case check_texture_addr_mode:
0497 cur_seq->unfinished = tex_address;
0498 if (2 == (tmp = cmd & 0x00000003)) {
0499 DRM_ERROR
0500 ("Attempt to fetch texture from system memory.\n");
0501 return 2;
0502 }
0503 cur_seq->agp_texture = (tmp == 3);
0504 cur_seq->tex_palette_size[cur_seq->texture] =
0505 (cmd >> 16) & 0x000000007;
0506 return 0;
0507 case check_for_vertex_count:
0508 cur_seq->vertex_count = cmd & 0x0000FFFF;
0509 return 0;
0510 case check_number_texunits:
0511 cur_seq->multitex = (cmd >> 3) & 1;
0512 return 0;
0513 default:
0514 DRM_ERROR("Illegal DMA data: 0x%x\n", cmd);
0515 return 2;
0516 }
0517 return 2;
0518 }
0519
0520 static __inline__ int
0521 via_check_prim_list(uint32_t const **buffer, const uint32_t * buf_end,
0522 drm_via_state_t *cur_seq)
0523 {
0524 drm_via_private_t *dev_priv =
0525 (drm_via_private_t *) cur_seq->dev->dev_private;
0526 uint32_t a_fire, bcmd, dw_count;
0527 int ret = 0;
0528 int have_fire;
0529 const uint32_t *buf = *buffer;
0530
0531 while (buf < buf_end) {
0532 have_fire = 0;
0533 if ((buf_end - buf) < 2) {
0534 DRM_ERROR
0535 ("Unexpected termination of primitive list.\n");
0536 ret = 1;
0537 break;
0538 }
0539 if ((*buf & HC_ACMD_MASK) != HC_ACMD_HCmdB)
0540 break;
0541 bcmd = *buf++;
0542 if ((*buf & HC_ACMD_MASK) != HC_ACMD_HCmdA) {
0543 DRM_ERROR("Expected Vertex List A command, got 0x%x\n",
0544 *buf);
0545 ret = 1;
0546 break;
0547 }
0548 a_fire =
0549 *buf++ | HC_HPLEND_MASK | HC_HPMValidN_MASK |
0550 HC_HE3Fire_MASK;
0551
0552
0553
0554
0555
0556 if (cur_seq->agp && ((bcmd & (0xF << 11)) == 0)) {
0557 DRM_ERROR("Illegal B command vertex data for AGP.\n");
0558 ret = 1;
0559 break;
0560 }
0561
0562 dw_count = 0;
0563 if (bcmd & (1 << 7))
0564 dw_count += (cur_seq->multitex) ? 2 : 1;
0565 if (bcmd & (1 << 8))
0566 dw_count += (cur_seq->multitex) ? 2 : 1;
0567 if (bcmd & (1 << 9))
0568 dw_count++;
0569 if (bcmd & (1 << 10))
0570 dw_count++;
0571 if (bcmd & (1 << 11))
0572 dw_count++;
0573 if (bcmd & (1 << 12))
0574 dw_count++;
0575 if (bcmd & (1 << 13))
0576 dw_count++;
0577 if (bcmd & (1 << 14))
0578 dw_count++;
0579
0580 while (buf < buf_end) {
0581 if (*buf == a_fire) {
0582 if (dev_priv->num_fire_offsets >=
0583 VIA_FIRE_BUF_SIZE) {
0584 DRM_ERROR("Fire offset buffer full.\n");
0585 ret = 1;
0586 break;
0587 }
0588 dev_priv->fire_offsets[dev_priv->
0589 num_fire_offsets++] =
0590 buf;
0591 have_fire = 1;
0592 buf++;
0593 if (buf < buf_end && *buf == a_fire)
0594 buf++;
0595 break;
0596 }
0597 if ((*buf == HALCYON_HEADER2) ||
0598 ((*buf & HALCYON_FIREMASK) == HALCYON_FIRECMD)) {
0599 DRM_ERROR("Missing Vertex Fire command, "
0600 "Stray Vertex Fire command or verifier "
0601 "lost sync.\n");
0602 ret = 1;
0603 break;
0604 }
0605 if ((ret = eat_words(&buf, buf_end, dw_count)))
0606 break;
0607 }
0608 if (buf >= buf_end && !have_fire) {
0609 DRM_ERROR("Missing Vertex Fire command or verifier "
0610 "lost sync.\n");
0611 ret = 1;
0612 break;
0613 }
0614 if (cur_seq->agp && ((buf - cur_seq->buf_start) & 0x01)) {
0615 DRM_ERROR("AGP Primitive list end misaligned.\n");
0616 ret = 1;
0617 break;
0618 }
0619 }
0620 *buffer = buf;
0621 return ret;
0622 }
0623
0624 static __inline__ verifier_state_t
0625 via_check_header2(uint32_t const **buffer, const uint32_t *buf_end,
0626 drm_via_state_t *hc_state)
0627 {
0628 uint32_t cmd;
0629 int hz_mode;
0630 hazard_t hz;
0631 const uint32_t *buf = *buffer;
0632 const hazard_t *hz_table;
0633
0634 if ((buf_end - buf) < 2) {
0635 DRM_ERROR
0636 ("Illegal termination of DMA HALCYON_HEADER2 sequence.\n");
0637 return state_error;
0638 }
0639 buf++;
0640 cmd = (*buf++ & 0xFFFF0000) >> 16;
0641
0642 switch (cmd) {
0643 case HC_ParaType_CmdVdata:
0644 if (via_check_prim_list(&buf, buf_end, hc_state))
0645 return state_error;
0646 *buffer = buf;
0647 return state_command;
0648 case HC_ParaType_NotTex:
0649 hz_table = table1;
0650 break;
0651 case HC_ParaType_Tex:
0652 hc_state->texture = 0;
0653 hz_table = table2;
0654 break;
0655 case (HC_ParaType_Tex | (HC_SubType_Tex1 << 8)):
0656 hc_state->texture = 1;
0657 hz_table = table2;
0658 break;
0659 case (HC_ParaType_Tex | (HC_SubType_TexGeneral << 8)):
0660 hz_table = table3;
0661 break;
0662 case HC_ParaType_Auto:
0663 if (eat_words(&buf, buf_end, 2))
0664 return state_error;
0665 *buffer = buf;
0666 return state_command;
0667 case (HC_ParaType_Palette | (HC_SubType_Stipple << 8)):
0668 if (eat_words(&buf, buf_end, 32))
0669 return state_error;
0670 *buffer = buf;
0671 return state_command;
0672 case (HC_ParaType_Palette | (HC_SubType_TexPalette0 << 8)):
0673 case (HC_ParaType_Palette | (HC_SubType_TexPalette1 << 8)):
0674 DRM_ERROR("Texture palettes are rejected because of "
0675 "lack of info how to determine their size.\n");
0676 return state_error;
0677 case (HC_ParaType_Palette | (HC_SubType_FogTable << 8)):
0678 DRM_ERROR("Fog factor palettes are rejected because of "
0679 "lack of info how to determine their size.\n");
0680 return state_error;
0681 default:
0682
0683
0684
0685
0686
0687
0688 DRM_ERROR("Invalid or unimplemented HALCYON_HEADER2 "
0689 "DMA subcommand: 0x%x. Previous dword: 0x%x\n",
0690 cmd, *(buf - 2));
0691 *buffer = buf;
0692 return state_error;
0693 }
0694
0695 while (buf < buf_end) {
0696 cmd = *buf++;
0697 if ((hz = hz_table[cmd >> 24])) {
0698 if ((hz_mode = investigate_hazard(cmd, hz, hc_state))) {
0699 if (hz_mode == 1) {
0700 buf--;
0701 break;
0702 }
0703 return state_error;
0704 }
0705 } else if (hc_state->unfinished &&
0706 finish_current_sequence(hc_state)) {
0707 return state_error;
0708 }
0709 }
0710 if (hc_state->unfinished && finish_current_sequence(hc_state))
0711 return state_error;
0712 *buffer = buf;
0713 return state_command;
0714 }
0715
0716 static __inline__ verifier_state_t
0717 via_parse_header2(drm_via_private_t *dev_priv, uint32_t const **buffer,
0718 const uint32_t *buf_end, int *fire_count)
0719 {
0720 uint32_t cmd;
0721 const uint32_t *buf = *buffer;
0722 const uint32_t *next_fire;
0723 int burst = 0;
0724
0725 next_fire = dev_priv->fire_offsets[*fire_count];
0726 buf++;
0727 cmd = (*buf & 0xFFFF0000) >> 16;
0728 via_write(dev_priv, HC_REG_TRANS_SET + HC_REG_BASE, *buf++);
0729 switch (cmd) {
0730 case HC_ParaType_CmdVdata:
0731 while ((buf < buf_end) &&
0732 (*fire_count < dev_priv->num_fire_offsets) &&
0733 (*buf & HC_ACMD_MASK) == HC_ACMD_HCmdB) {
0734 while (buf <= next_fire) {
0735 via_write(dev_priv, HC_REG_TRANS_SPACE + HC_REG_BASE +
0736 (burst & 63), *buf++);
0737 burst += 4;
0738 }
0739 if ((buf < buf_end)
0740 && ((*buf & HALCYON_FIREMASK) == HALCYON_FIRECMD))
0741 buf++;
0742
0743 if (++(*fire_count) < dev_priv->num_fire_offsets)
0744 next_fire = dev_priv->fire_offsets[*fire_count];
0745 }
0746 break;
0747 default:
0748 while (buf < buf_end) {
0749
0750 if (*buf == HC_HEADER2 ||
0751 (*buf & HALCYON_HEADER1MASK) == HALCYON_HEADER1 ||
0752 (*buf & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5 ||
0753 (*buf & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6)
0754 break;
0755
0756 via_write(dev_priv, HC_REG_TRANS_SPACE + HC_REG_BASE +
0757 (burst & 63), *buf++);
0758 burst += 4;
0759 }
0760 }
0761 *buffer = buf;
0762 return state_command;
0763 }
0764
0765 static __inline__ int verify_mmio_address(uint32_t address)
0766 {
0767 if ((address > 0x3FF) && (address < 0xC00)) {
0768 DRM_ERROR("Invalid VIDEO DMA command. "
0769 "Attempt to access 3D- or command burst area.\n");
0770 return 1;
0771 } else if ((address > 0xCFF) && (address < 0x1300)) {
0772 DRM_ERROR("Invalid VIDEO DMA command. "
0773 "Attempt to access PCI DMA area.\n");
0774 return 1;
0775 } else if (address > 0x13FF) {
0776 DRM_ERROR("Invalid VIDEO DMA command. "
0777 "Attempt to access VGA registers.\n");
0778 return 1;
0779 }
0780 return 0;
0781 }
0782
0783 static __inline__ int
0784 verify_video_tail(uint32_t const **buffer, const uint32_t * buf_end,
0785 uint32_t dwords)
0786 {
0787 const uint32_t *buf = *buffer;
0788
0789 if (buf_end - buf < dwords) {
0790 DRM_ERROR("Illegal termination of video command.\n");
0791 return 1;
0792 }
0793 while (dwords--) {
0794 if (*buf++) {
0795 DRM_ERROR("Illegal video command tail.\n");
0796 return 1;
0797 }
0798 }
0799 *buffer = buf;
0800 return 0;
0801 }
0802
0803 static __inline__ verifier_state_t
0804 via_check_header1(uint32_t const **buffer, const uint32_t * buf_end)
0805 {
0806 uint32_t cmd;
0807 const uint32_t *buf = *buffer;
0808 verifier_state_t ret = state_command;
0809
0810 while (buf < buf_end) {
0811 cmd = *buf;
0812 if ((cmd > ((0x3FF >> 2) | HALCYON_HEADER1)) &&
0813 (cmd < ((0xC00 >> 2) | HALCYON_HEADER1))) {
0814 if ((cmd & HALCYON_HEADER1MASK) != HALCYON_HEADER1)
0815 break;
0816 DRM_ERROR("Invalid HALCYON_HEADER1 command. "
0817 "Attempt to access 3D- or command burst area.\n");
0818 ret = state_error;
0819 break;
0820 } else if (cmd > ((0xCFF >> 2) | HALCYON_HEADER1)) {
0821 if ((cmd & HALCYON_HEADER1MASK) != HALCYON_HEADER1)
0822 break;
0823 DRM_ERROR("Invalid HALCYON_HEADER1 command. "
0824 "Attempt to access VGA registers.\n");
0825 ret = state_error;
0826 break;
0827 } else {
0828 buf += 2;
0829 }
0830 }
0831 *buffer = buf;
0832 return ret;
0833 }
0834
0835 static __inline__ verifier_state_t
0836 via_parse_header1(drm_via_private_t *dev_priv, uint32_t const **buffer,
0837 const uint32_t *buf_end)
0838 {
0839 register uint32_t cmd;
0840 const uint32_t *buf = *buffer;
0841
0842 while (buf < buf_end) {
0843 cmd = *buf;
0844 if ((cmd & HALCYON_HEADER1MASK) != HALCYON_HEADER1)
0845 break;
0846 via_write(dev_priv, (cmd & ~HALCYON_HEADER1MASK) << 2, *++buf);
0847 buf++;
0848 }
0849 *buffer = buf;
0850 return state_command;
0851 }
0852
0853 static __inline__ verifier_state_t
0854 via_check_vheader5(uint32_t const **buffer, const uint32_t *buf_end)
0855 {
0856 uint32_t data;
0857 const uint32_t *buf = *buffer;
0858
0859 if (buf_end - buf < 4) {
0860 DRM_ERROR("Illegal termination of video header5 command\n");
0861 return state_error;
0862 }
0863
0864 data = *buf++ & ~VIA_VIDEOMASK;
0865 if (verify_mmio_address(data))
0866 return state_error;
0867
0868 data = *buf++;
0869 if (*buf++ != 0x00F50000) {
0870 DRM_ERROR("Illegal header5 header data\n");
0871 return state_error;
0872 }
0873 if (*buf++ != 0x00000000) {
0874 DRM_ERROR("Illegal header5 header data\n");
0875 return state_error;
0876 }
0877 if (eat_words(&buf, buf_end, data))
0878 return state_error;
0879 if ((data & 3) && verify_video_tail(&buf, buf_end, 4 - (data & 3)))
0880 return state_error;
0881 *buffer = buf;
0882 return state_command;
0883
0884 }
0885
0886 static __inline__ verifier_state_t
0887 via_parse_vheader5(drm_via_private_t *dev_priv, uint32_t const **buffer,
0888 const uint32_t *buf_end)
0889 {
0890 uint32_t addr, count, i;
0891 const uint32_t *buf = *buffer;
0892
0893 addr = *buf++ & ~VIA_VIDEOMASK;
0894 i = count = *buf;
0895 buf += 3;
0896 while (i--)
0897 via_write(dev_priv, addr, *buf++);
0898 if (count & 3)
0899 buf += 4 - (count & 3);
0900 *buffer = buf;
0901 return state_command;
0902 }
0903
0904 static __inline__ verifier_state_t
0905 via_check_vheader6(uint32_t const **buffer, const uint32_t * buf_end)
0906 {
0907 uint32_t data;
0908 const uint32_t *buf = *buffer;
0909 uint32_t i;
0910
0911 if (buf_end - buf < 4) {
0912 DRM_ERROR("Illegal termination of video header6 command\n");
0913 return state_error;
0914 }
0915 buf++;
0916 data = *buf++;
0917 if (*buf++ != 0x00F60000) {
0918 DRM_ERROR("Illegal header6 header data\n");
0919 return state_error;
0920 }
0921 if (*buf++ != 0x00000000) {
0922 DRM_ERROR("Illegal header6 header data\n");
0923 return state_error;
0924 }
0925 if ((buf_end - buf) < (data << 1)) {
0926 DRM_ERROR("Illegal termination of video header6 command\n");
0927 return state_error;
0928 }
0929 for (i = 0; i < data; ++i) {
0930 if (verify_mmio_address(*buf++))
0931 return state_error;
0932 buf++;
0933 }
0934 data <<= 1;
0935 if ((data & 3) && verify_video_tail(&buf, buf_end, 4 - (data & 3)))
0936 return state_error;
0937 *buffer = buf;
0938 return state_command;
0939 }
0940
0941 static __inline__ verifier_state_t
0942 via_parse_vheader6(drm_via_private_t *dev_priv, uint32_t const **buffer,
0943 const uint32_t *buf_end)
0944 {
0945
0946 uint32_t addr, count, i;
0947 const uint32_t *buf = *buffer;
0948
0949 i = count = *++buf;
0950 buf += 3;
0951 while (i--) {
0952 addr = *buf++;
0953 via_write(dev_priv, addr, *buf++);
0954 }
0955 count <<= 1;
0956 if (count & 3)
0957 buf += 4 - (count & 3);
0958 *buffer = buf;
0959 return state_command;
0960 }
0961
0962 int
0963 via_verify_command_stream(const uint32_t * buf, unsigned int size,
0964 struct drm_device * dev, int agp)
0965 {
0966
0967 drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
0968 drm_via_state_t *hc_state = &dev_priv->hc_state;
0969 drm_via_state_t saved_state = *hc_state;
0970 uint32_t cmd;
0971 const uint32_t *buf_end = buf + (size >> 2);
0972 verifier_state_t state = state_command;
0973 int cme_video;
0974 int supported_3d;
0975
0976 cme_video = (dev_priv->chipset == VIA_PRO_GROUP_A ||
0977 dev_priv->chipset == VIA_DX9_0);
0978
0979 supported_3d = dev_priv->chipset != VIA_DX9_0;
0980
0981 hc_state->dev = dev;
0982 hc_state->unfinished = no_sequence;
0983 hc_state->map_cache = NULL;
0984 hc_state->agp = agp;
0985 hc_state->buf_start = buf;
0986 dev_priv->num_fire_offsets = 0;
0987
0988 while (buf < buf_end) {
0989
0990 switch (state) {
0991 case state_header2:
0992 state = via_check_header2(&buf, buf_end, hc_state);
0993 break;
0994 case state_header1:
0995 state = via_check_header1(&buf, buf_end);
0996 break;
0997 case state_vheader5:
0998 state = via_check_vheader5(&buf, buf_end);
0999 break;
1000 case state_vheader6:
1001 state = via_check_vheader6(&buf, buf_end);
1002 break;
1003 case state_command:
1004 cmd = *buf;
1005 if ((cmd == HALCYON_HEADER2) && supported_3d)
1006 state = state_header2;
1007 else if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1)
1008 state = state_header1;
1009 else if (cme_video
1010 && (cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5)
1011 state = state_vheader5;
1012 else if (cme_video
1013 && (cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6)
1014 state = state_vheader6;
1015 else if ((cmd == HALCYON_HEADER2) && !supported_3d) {
1016 DRM_ERROR("Accelerated 3D is not supported on this chipset yet.\n");
1017 state = state_error;
1018 } else {
1019 DRM_ERROR
1020 ("Invalid / Unimplemented DMA HEADER command. 0x%x\n",
1021 cmd);
1022 state = state_error;
1023 }
1024 break;
1025 case state_error:
1026 default:
1027 *hc_state = saved_state;
1028 return -EINVAL;
1029 }
1030 }
1031 if (state == state_error) {
1032 *hc_state = saved_state;
1033 return -EINVAL;
1034 }
1035 return 0;
1036 }
1037
1038 int
1039 via_parse_command_stream(struct drm_device *dev, const uint32_t *buf,
1040 unsigned int size)
1041 {
1042
1043 drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
1044 uint32_t cmd;
1045 const uint32_t *buf_end = buf + (size >> 2);
1046 verifier_state_t state = state_command;
1047 int fire_count = 0;
1048
1049 while (buf < buf_end) {
1050
1051 switch (state) {
1052 case state_header2:
1053 state =
1054 via_parse_header2(dev_priv, &buf, buf_end,
1055 &fire_count);
1056 break;
1057 case state_header1:
1058 state = via_parse_header1(dev_priv, &buf, buf_end);
1059 break;
1060 case state_vheader5:
1061 state = via_parse_vheader5(dev_priv, &buf, buf_end);
1062 break;
1063 case state_vheader6:
1064 state = via_parse_vheader6(dev_priv, &buf, buf_end);
1065 break;
1066 case state_command:
1067 cmd = *buf;
1068 if (cmd == HALCYON_HEADER2)
1069 state = state_header2;
1070 else if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1)
1071 state = state_header1;
1072 else if ((cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5)
1073 state = state_vheader5;
1074 else if ((cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6)
1075 state = state_vheader6;
1076 else {
1077 DRM_ERROR
1078 ("Invalid / Unimplemented DMA HEADER command. 0x%x\n",
1079 cmd);
1080 state = state_error;
1081 }
1082 break;
1083 case state_error:
1084 default:
1085 return -EINVAL;
1086 }
1087 }
1088 if (state == state_error)
1089 return -EINVAL;
1090 return 0;
1091 }
1092
1093 static void
1094 setup_hazard_table(hz_init_t init_table[], hazard_t table[], int size)
1095 {
1096 int i;
1097
1098 for (i = 0; i < 256; ++i)
1099 table[i] = forbidden_command;
1100
1101 for (i = 0; i < size; ++i)
1102 table[init_table[i].code] = init_table[i].hz;
1103 }
1104
1105 void via_init_command_verifier(void)
1106 {
1107 setup_hazard_table(init_table1, table1, ARRAY_SIZE(init_table1));
1108 setup_hazard_table(init_table2, table2, ARRAY_SIZE(init_table2));
1109 setup_hazard_table(init_table3, table3, ARRAY_SIZE(init_table3));
1110 }