2  * Copyright 2004 The Unichrome Project. All Rights Reserved.
 
   3  * Copyright 2005 Thomas Hellstrom. All Rights Reserved.
 
   5  * Permission is hereby granted, free of charge, to any person obtaining a
 
   6  * copy of this software and associated documentation files (the "Software"),
 
   7  * to deal in the Software without restriction, including without limitation
 
   8  * the rights to use, copy, modify, merge, publish, distribute, sub license,
 
   9  * and/or sell copies of the Software, and to permit persons to whom the
 
  10  * Software is furnished to do so, subject to the following conditions:
 
  12  * The above copyright notice and this permission notice (including the
 
  13  * next paragraph) shall be included in all copies or substantial portions
 
  16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
  17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
  18  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
 
  19  * THE AUTHOR(S), AND/OR THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
 
  20  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 
  21  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 
  22  * DEALINGS IN THE SOFTWARE.
 
  24  * Author: Thomas Hellstrom 2004, 2005.
 
  25  * This code was written using docs obtained under NDA from VIA Inc.
 
  27  * Don't run this code directly on an AGP buffer. Due to cache problems it will
 
  31 #include "via_3d_reg.h"
 
  35 #include "via_verifier.h"
 
  51         check_for_header2_err,
 
  52         check_for_header1_err,
 
  56         check_z_buffer_addr_mode,
 
  57         check_destination_addr0,
 
  58         check_destination_addr1,
 
  59         check_destination_addr_mode,
 
  71         check_texture_addr_mode,
 
  72         check_for_vertex_count,
 
  73         check_number_texunits,
 
  78  * Associates each hazard above with a possible multi-command
 
  79  * sequence. For example an address that is split over multiple
 
  80  * commands and that needs to be checked at the first command
 
  81  * that does not include any part of the address.
 
  84 static drm_via_sequence_t seqs[] = {
 
 117 static hz_init_t init_table1[] = {
 
 118         {0xf2, check_for_header2_err},
 
 119         {0xf0, check_for_header1_err},
 
 120         {0xee, check_for_fire},
 
 121         {0xcc, check_for_dummy},
 
 122         {0xdd, check_for_dd},
 
 124         {0x10, check_z_buffer_addr0},
 
 125         {0x11, check_z_buffer_addr1},
 
 126         {0x12, check_z_buffer_addr_mode},
 
 144         {0x40, check_destination_addr0},
 
 145         {0x41, check_destination_addr1},
 
 146         {0x42, check_destination_addr_mode},
 
 165         {0x7D, check_for_vertex_count}
 
 168 static hz_init_t init_table2[] = {
 
 169         {0xf2, check_for_header2_err},
 
 170         {0xf0, check_for_header1_err},
 
 171         {0xee, check_for_fire},
 
 172         {0xcc, check_for_dummy},
 
 173         {0x00, check_texture_addr0},
 
 174         {0x01, check_texture_addr0},
 
 175         {0x02, check_texture_addr0},
 
 176         {0x03, check_texture_addr0},
 
 177         {0x04, check_texture_addr0},
 
 178         {0x05, check_texture_addr0},
 
 179         {0x06, check_texture_addr0},
 
 180         {0x07, check_texture_addr0},
 
 181         {0x08, check_texture_addr0},
 
 182         {0x09, check_texture_addr0},
 
 183         {0x20, check_texture_addr1},
 
 184         {0x21, check_texture_addr1},
 
 185         {0x22, check_texture_addr1},
 
 186         {0x23, check_texture_addr4},
 
 187         {0x2B, check_texture_addr3},
 
 188         {0x2C, check_texture_addr3},
 
 189         {0x2D, check_texture_addr3},
 
 190         {0x2E, check_texture_addr3},
 
 191         {0x2F, check_texture_addr3},
 
 192         {0x30, check_texture_addr3},
 
 193         {0x31, check_texture_addr3},
 
 194         {0x32, check_texture_addr3},
 
 195         {0x33, check_texture_addr3},
 
 196         {0x34, check_texture_addr3},
 
 197         {0x4B, check_texture_addr5},
 
 198         {0x4C, check_texture_addr6},
 
 199         {0x51, check_texture_addr7},
 
 200         {0x52, check_texture_addr8},
 
 201         {0x77, check_texture_addr2},
 
 205         {0x7B, check_texture_addr_mode},
 
 226 static hz_init_t init_table3[] = {
 
 227         {0xf2, check_for_header2_err},
 
 228         {0xf0, check_for_header1_err},
 
 229         {0xcc, check_for_dummy},
 
 230         {0x00, check_number_texunits}
 
 233 static hazard_t table1[256];
 
 234 static hazard_t table2[256];
 
 235 static hazard_t table3[256];
 
 237 static __inline__ int
 
 238 eat_words(const uint32_t ** buf, const uint32_t * buf_end, unsigned num_words)
 
 240         if ((buf_end - *buf) >= num_words) {
 
 244         DRM_ERROR("Illegal termination of DMA command buffer\n");
 
 249  * Partially stolen from drm_memory.h
 
 252 static __inline__ drm_local_map_t *via_drm_lookup_agp_map(drm_via_state_t *seq,
 
 253                                                     unsigned long offset,
 
 255                                                     struct drm_device * dev)
 
 257         struct drm_map_list *r_list;
 
 258         drm_local_map_t *map = seq->map_cache;
 
 260         if (map && map->offset <= offset
 
 261             && (offset + size) <= (map->offset + map->size)) {
 
 265         list_for_each_entry(r_list, &dev->maplist, head) {
 
 269                 if (map->offset <= offset
 
 270                     && (offset + size) <= (map->offset + map->size)
 
 271                     && !(map->flags & _DRM_RESTRICTED)
 
 272                     && (map->type == _DRM_AGP)) {
 
 273                         seq->map_cache = map;
 
 281  * Require that all AGP texture levels reside in the same AGP map which should
 
 282  * be mappable by the client. This is not a big restriction.
 
 283  * FIXME: To actually enforce this security policy strictly, drm_rmmap
 
 284  * would have to wait for dma quiescent before removing an AGP map.
 
 285  * The via_drm_lookup_agp_map call in reality seems to take
 
 286  * very little CPU time.
 
 289 static __inline__ int finish_current_sequence(drm_via_state_t * cur_seq)
 
 291         switch (cur_seq->unfinished) {
 
 293                 DRM_DEBUG("Z Buffer start address is 0x%x\n", cur_seq->z_addr);
 
 296                 DRM_DEBUG("Destination start address is 0x%x\n",
 
 300                 if (cur_seq->agp_texture) {
 
 302                             cur_seq->tex_level_lo[cur_seq->texture];
 
 303                         unsigned end = cur_seq->tex_level_hi[cur_seq->texture];
 
 304                         unsigned long lo = ~0, hi = 0, tmp;
 
 305                         uint32_t *addr, *pitch, *height, tex;
 
 315                             &(cur_seq->t_addr[tex = cur_seq->texture][start]);
 
 316                         pitch = &(cur_seq->pitch[tex][start]);
 
 317                         height = &(cur_seq->height[tex][start]);
 
 318                         npot = cur_seq->tex_npot[tex];
 
 319                         for (i = start; i <= end; ++i) {
 
 324                                         tmp += (*height++ * *pitch++);
 
 326                                         tmp += (*height++ << *pitch++);
 
 331                         if (!via_drm_lookup_agp_map
 
 332                             (cur_seq, lo, hi - lo, cur_seq->dev)) {
 
 334                                     ("AGP texture is not in allowed map\n");
 
 342         cur_seq->unfinished = no_sequence;
 
 346 static __inline__ int
 
 347 investigate_hazard(uint32_t cmd, hazard_t hz, drm_via_state_t * cur_seq)
 
 349         register uint32_t tmp, *tmp_addr;
 
 351         if (cur_seq->unfinished && (cur_seq->unfinished != seqs[hz])) {
 
 353                 if ((ret = finish_current_sequence(cur_seq)))
 
 358         case check_for_header2:
 
 359                 if (cmd == HALCYON_HEADER2)
 
 362         case check_for_header1:
 
 363                 if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1)
 
 366         case check_for_header2_err:
 
 367                 if (cmd == HALCYON_HEADER2)
 
 369                 DRM_ERROR("Illegal DMA HALCYON_HEADER2 command\n");
 
 371         case check_for_header1_err:
 
 372                 if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1)
 
 374                 DRM_ERROR("Illegal DMA HALCYON_HEADER1 command\n");
 
 377                 if ((cmd & HALCYON_FIREMASK) == HALCYON_FIRECMD)
 
 379                 DRM_ERROR("Illegal DMA HALCYON_FIRECMD command\n");
 
 381         case check_for_dummy:
 
 384                 DRM_ERROR("Illegal DMA HC_DUMMY command\n");
 
 387                 if (0xdddddddd == cmd)
 
 389                 DRM_ERROR("Illegal DMA 0xdddddddd command\n");
 
 391         case check_z_buffer_addr0:
 
 392                 cur_seq->unfinished = z_address;
 
 393                 cur_seq->z_addr = (cur_seq->z_addr & 0xFF000000) |
 
 396         case check_z_buffer_addr1:
 
 397                 cur_seq->unfinished = z_address;
 
 398                 cur_seq->z_addr = (cur_seq->z_addr & 0x00FFFFFF) |
 
 399                     ((cmd & 0xFF) << 24);
 
 401         case check_z_buffer_addr_mode:
 
 402                 cur_seq->unfinished = z_address;
 
 403                 if ((cmd & 0x0000C000) == 0)
 
 405                 DRM_ERROR("Attempt to place Z buffer in system memory\n");
 
 407         case check_destination_addr0:
 
 408                 cur_seq->unfinished = dest_address;
 
 409                 cur_seq->d_addr = (cur_seq->d_addr & 0xFF000000) |
 
 412         case check_destination_addr1:
 
 413                 cur_seq->unfinished = dest_address;
 
 414                 cur_seq->d_addr = (cur_seq->d_addr & 0x00FFFFFF) |
 
 415                     ((cmd & 0xFF) << 24);
 
 417         case check_destination_addr_mode:
 
 418                 cur_seq->unfinished = dest_address;
 
 419                 if ((cmd & 0x0000C000) == 0)
 
 422                     ("Attempt to place 3D drawing buffer in system memory\n");
 
 424         case check_texture_addr0:
 
 425                 cur_seq->unfinished = tex_address;
 
 427                 tmp_addr = &cur_seq->t_addr[cur_seq->texture][tmp];
 
 428                 *tmp_addr = (*tmp_addr & 0xFF000000) | (cmd & 0x00FFFFFF);
 
 430         case check_texture_addr1:
 
 431                 cur_seq->unfinished = tex_address;
 
 432                 tmp = ((cmd >> 24) - 0x20);
 
 434                 tmp_addr = &cur_seq->t_addr[cur_seq->texture][tmp];
 
 435                 *tmp_addr = (*tmp_addr & 0x00FFFFFF) | ((cmd & 0xFF) << 24);
 
 437                 *tmp_addr = (*tmp_addr & 0x00FFFFFF) | ((cmd & 0xFF00) << 16);
 
 439                 *tmp_addr = (*tmp_addr & 0x00FFFFFF) | ((cmd & 0xFF0000) << 8);
 
 441         case check_texture_addr2:
 
 442                 cur_seq->unfinished = tex_address;
 
 443                 cur_seq->tex_level_lo[tmp = cur_seq->texture] = cmd & 0x3F;
 
 444                 cur_seq->tex_level_hi[tmp] = (cmd & 0xFC0) >> 6;
 
 446         case check_texture_addr3:
 
 447                 cur_seq->unfinished = tex_address;
 
 448                 tmp = ((cmd >> 24) - HC_SubA_HTXnL0Pit);
 
 450                     (cmd & HC_HTXnEnPit_MASK)) {
 
 451                         cur_seq->pitch[cur_seq->texture][tmp] =
 
 452                                 (cmd & HC_HTXnLnPit_MASK);
 
 453                         cur_seq->tex_npot[cur_seq->texture] = 1;
 
 455                         cur_seq->pitch[cur_seq->texture][tmp] =
 
 456                                 (cmd & HC_HTXnLnPitE_MASK) >> HC_HTXnLnPitE_SHIFT;
 
 457                         cur_seq->tex_npot[cur_seq->texture] = 0;
 
 458                         if (cmd & 0x000FFFFF) {
 
 460                                         ("Unimplemented texture level 0 pitch mode.\n");
 
 465         case check_texture_addr4:
 
 466                 cur_seq->unfinished = tex_address;
 
 467                 tmp_addr = &cur_seq->t_addr[cur_seq->texture][9];
 
 468                 *tmp_addr = (*tmp_addr & 0x00FFFFFF) | ((cmd & 0xFF) << 24);
 
 470         case check_texture_addr5:
 
 471         case check_texture_addr6:
 
 472                 cur_seq->unfinished = tex_address;
 
 474                  * Texture width. We don't care since we have the pitch.
 
 477         case check_texture_addr7:
 
 478                 cur_seq->unfinished = tex_address;
 
 479                 tmp_addr = &(cur_seq->height[cur_seq->texture][0]);
 
 480                 tmp_addr[5] = 1 << ((cmd & 0x00F00000) >> 20);
 
 481                 tmp_addr[4] = 1 << ((cmd & 0x000F0000) >> 16);
 
 482                 tmp_addr[3] = 1 << ((cmd & 0x0000F000) >> 12);
 
 483                 tmp_addr[2] = 1 << ((cmd & 0x00000F00) >> 8);
 
 484                 tmp_addr[1] = 1 << ((cmd & 0x000000F0) >> 4);
 
 485                 tmp_addr[0] = 1 << (cmd & 0x0000000F);
 
 487         case check_texture_addr8:
 
 488                 cur_seq->unfinished = tex_address;
 
 489                 tmp_addr = &(cur_seq->height[cur_seq->texture][0]);
 
 490                 tmp_addr[9] = 1 << ((cmd & 0x0000F000) >> 12);
 
 491                 tmp_addr[8] = 1 << ((cmd & 0x00000F00) >> 8);
 
 492                 tmp_addr[7] = 1 << ((cmd & 0x000000F0) >> 4);
 
 493                 tmp_addr[6] = 1 << (cmd & 0x0000000F);
 
 495         case check_texture_addr_mode:
 
 496                 cur_seq->unfinished = tex_address;
 
 497                 if (2 == (tmp = cmd & 0x00000003)) {
 
 499                             ("Attempt to fetch texture from system memory.\n");
 
 502                 cur_seq->agp_texture = (tmp == 3);
 
 503                 cur_seq->tex_palette_size[cur_seq->texture] =
 
 504                     (cmd >> 16) & 0x000000007;
 
 506         case check_for_vertex_count:
 
 507                 cur_seq->vertex_count = cmd & 0x0000FFFF;
 
 509         case check_number_texunits:
 
 510                 cur_seq->multitex = (cmd >> 3) & 1;
 
 513                 DRM_ERROR("Illegal DMA data: 0x%x\n", cmd);
 
 519 static __inline__ int
 
 520 via_check_prim_list(uint32_t const **buffer, const uint32_t * buf_end,
 
 521                     drm_via_state_t * cur_seq)
 
 523         drm_via_private_t *dev_priv =
 
 524             (drm_via_private_t *) cur_seq->dev->dev_private;
 
 525         uint32_t a_fire, bcmd, dw_count;
 
 528         const uint32_t *buf = *buffer;
 
 530         while (buf < buf_end) {
 
 532                 if ((buf_end - buf) < 2) {
 
 534                             ("Unexpected termination of primitive list.\n");
 
 538                 if ((*buf & HC_ACMD_MASK) != HC_ACMD_HCmdB)
 
 541                 if ((*buf & HC_ACMD_MASK) != HC_ACMD_HCmdA) {
 
 542                         DRM_ERROR("Expected Vertex List A command, got 0x%x\n",
 
 548                     *buf++ | HC_HPLEND_MASK | HC_HPMValidN_MASK |
 
 552                  * How many dwords per vertex ?
 
 555                 if (cur_seq->agp && ((bcmd & (0xF << 11)) == 0)) {
 
 556                         DRM_ERROR("Illegal B command vertex data for AGP.\n");
 
 563                         dw_count += (cur_seq->multitex) ? 2 : 1;
 
 565                         dw_count += (cur_seq->multitex) ? 2 : 1;
 
 568                 if (bcmd & (1 << 10))
 
 570                 if (bcmd & (1 << 11))
 
 572                 if (bcmd & (1 << 12))
 
 574                 if (bcmd & (1 << 13))
 
 576                 if (bcmd & (1 << 14))
 
 579                 while (buf < buf_end) {
 
 580                         if (*buf == a_fire) {
 
 581                                 if (dev_priv->num_fire_offsets >=
 
 583                                         DRM_ERROR("Fire offset buffer full.\n");
 
 587                                 dev_priv->fire_offsets[dev_priv->
 
 588                                                        num_fire_offsets++] =
 
 592                                 if (buf < buf_end && *buf == a_fire)
 
 596                         if ((*buf == HALCYON_HEADER2) ||
 
 597                             ((*buf & HALCYON_FIREMASK) == HALCYON_FIRECMD)) {
 
 598                                 DRM_ERROR("Missing Vertex Fire command, "
 
 599                                           "Stray Vertex Fire command  or verifier "
 
 604                         if ((ret = eat_words(&buf, buf_end, dw_count)))
 
 607                 if (buf >= buf_end && !have_fire) {
 
 608                         DRM_ERROR("Missing Vertex Fire command or verifier "
 
 613                 if (cur_seq->agp && ((buf - cur_seq->buf_start) & 0x01)) {
 
 614                         DRM_ERROR("AGP Primitive list end misaligned.\n");
 
 623 static __inline__ verifier_state_t
 
 624 via_check_header2(uint32_t const **buffer, const uint32_t * buf_end,
 
 625                   drm_via_state_t * hc_state)
 
 630         const uint32_t *buf = *buffer;
 
 631         const hazard_t *hz_table;
 
 633         if ((buf_end - buf) < 2) {
 
 635                     ("Illegal termination of DMA HALCYON_HEADER2 sequence.\n");
 
 639         cmd = (*buf++ & 0xFFFF0000) >> 16;
 
 642         case HC_ParaType_CmdVdata:
 
 643                 if (via_check_prim_list(&buf, buf_end, hc_state))
 
 646                 return state_command;
 
 647         case HC_ParaType_NotTex:
 
 650         case HC_ParaType_Tex:
 
 651                 hc_state->texture = 0;
 
 654         case (HC_ParaType_Tex | (HC_SubType_Tex1 << 8)):
 
 655                 hc_state->texture = 1;
 
 658         case (HC_ParaType_Tex | (HC_SubType_TexGeneral << 8)):
 
 661         case HC_ParaType_Auto:
 
 662                 if (eat_words(&buf, buf_end, 2))
 
 665                 return state_command;
 
 666         case (HC_ParaType_Palette | (HC_SubType_Stipple << 8)):
 
 667                 if (eat_words(&buf, buf_end, 32))
 
 670                 return state_command;
 
 671         case (HC_ParaType_Palette | (HC_SubType_TexPalette0 << 8)):
 
 672         case (HC_ParaType_Palette | (HC_SubType_TexPalette1 << 8)):
 
 673                 DRM_ERROR("Texture palettes are rejected because of "
 
 674                           "lack of info how to determine their size.\n");
 
 676         case (HC_ParaType_Palette | (HC_SubType_FogTable << 8)):
 
 677                 DRM_ERROR("Fog factor palettes are rejected because of "
 
 678                           "lack of info how to determine their size.\n");
 
 683                  * There are some unimplemented HC_ParaTypes here, that
 
 684                  * need to be implemented if the Mesa driver is extended.
 
 687                 DRM_ERROR("Invalid or unimplemented HALCYON_HEADER2 "
 
 688                           "DMA subcommand: 0x%x. Previous dword: 0x%x\n",
 
 694         while (buf < buf_end) {
 
 696                 if ((hz = hz_table[cmd >> 24])) {
 
 697                         if ((hz_mode = investigate_hazard(cmd, hz, hc_state))) {
 
 704                 } else if (hc_state->unfinished &&
 
 705                            finish_current_sequence(hc_state)) {
 
 709         if (hc_state->unfinished && finish_current_sequence(hc_state)) {
 
 713         return state_command;
 
 716 static __inline__ verifier_state_t
 
 717 via_parse_header2(drm_via_private_t * dev_priv, uint32_t const **buffer,
 
 718                   const uint32_t * buf_end, int *fire_count)
 
 721         const uint32_t *buf = *buffer;
 
 722         const uint32_t *next_fire;
 
 725         next_fire = dev_priv->fire_offsets[*fire_count];
 
 727         cmd = (*buf & 0xFFFF0000) >> 16;
 
 728         VIA_WRITE(HC_REG_TRANS_SET + HC_REG_BASE, *buf++);
 
 730         case HC_ParaType_CmdVdata:
 
 731                 while ((buf < buf_end) &&
 
 732                        (*fire_count < dev_priv->num_fire_offsets) &&
 
 733                        (*buf & HC_ACMD_MASK) == HC_ACMD_HCmdB) {
 
 734                         while (buf <= next_fire) {
 
 735                                 VIA_WRITE(HC_REG_TRANS_SPACE + HC_REG_BASE +
 
 736                                           (burst & 63), *buf++);
 
 740                             && ((*buf & HALCYON_FIREMASK) == HALCYON_FIRECMD))
 
 743                         if (++(*fire_count) < dev_priv->num_fire_offsets)
 
 744                                 next_fire = dev_priv->fire_offsets[*fire_count];
 
 748                 while (buf < buf_end) {
 
 750                         if (*buf == HC_HEADER2 ||
 
 751                             (*buf & HALCYON_HEADER1MASK) == HALCYON_HEADER1 ||
 
 752                             (*buf & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5 ||
 
 753                             (*buf & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6)
 
 756                         VIA_WRITE(HC_REG_TRANS_SPACE + HC_REG_BASE +
 
 757                                   (burst & 63), *buf++);
 
 762         return state_command;
 
 765 static __inline__ int verify_mmio_address(uint32_t address)
 
 767         if ((address > 0x3FF) && (address < 0xC00)) {
 
 768                 DRM_ERROR("Invalid VIDEO DMA command. "
 
 769                           "Attempt to access 3D- or command burst area.\n");
 
 771         } else if ((address > 0xCFF) && (address < 0x1300)) {
 
 772                 DRM_ERROR("Invalid VIDEO DMA command. "
 
 773                           "Attempt to access PCI DMA area.\n");
 
 775         } else if (address > 0x13FF) {
 
 776                 DRM_ERROR("Invalid VIDEO DMA command. "
 
 777                           "Attempt to access VGA registers.\n");
 
 783 static __inline__ int
 
 784 verify_video_tail(uint32_t const **buffer, const uint32_t * buf_end,
 
 787         const uint32_t *buf = *buffer;
 
 789         if (buf_end - buf < dwords) {
 
 790                 DRM_ERROR("Illegal termination of video command.\n");
 
 795                         DRM_ERROR("Illegal video command tail.\n");
 
 803 static __inline__ verifier_state_t
 
 804 via_check_header1(uint32_t const **buffer, const uint32_t * buf_end)
 
 807         const uint32_t *buf = *buffer;
 
 808         verifier_state_t ret = state_command;
 
 810         while (buf < buf_end) {
 
 812                 if ((cmd > ((0x3FF >> 2) | HALCYON_HEADER1)) &&
 
 813                     (cmd < ((0xC00 >> 2) | HALCYON_HEADER1))) {
 
 814                         if ((cmd & HALCYON_HEADER1MASK) != HALCYON_HEADER1)
 
 816                         DRM_ERROR("Invalid HALCYON_HEADER1 command. "
 
 817                                   "Attempt to access 3D- or command burst area.\n");
 
 820                 } else if (cmd > ((0xCFF >> 2) | HALCYON_HEADER1)) {
 
 821                         if ((cmd & HALCYON_HEADER1MASK) != HALCYON_HEADER1)
 
 823                         DRM_ERROR("Invalid HALCYON_HEADER1 command. "
 
 824                                   "Attempt to access VGA registers.\n");
 
 835 static __inline__ verifier_state_t
 
 836 via_parse_header1(drm_via_private_t * dev_priv, uint32_t const **buffer,
 
 837                   const uint32_t * buf_end)
 
 839         register uint32_t cmd;
 
 840         const uint32_t *buf = *buffer;
 
 842         while (buf < buf_end) {
 
 844                 if ((cmd & HALCYON_HEADER1MASK) != HALCYON_HEADER1)
 
 846                 VIA_WRITE((cmd & ~HALCYON_HEADER1MASK) << 2, *++buf);
 
 850         return state_command;
 
 853 static __inline__ verifier_state_t
 
 854 via_check_vheader5(uint32_t const **buffer, const uint32_t * buf_end)
 
 857         const uint32_t *buf = *buffer;
 
 859         if (buf_end - buf < 4) {
 
 860                 DRM_ERROR("Illegal termination of video header5 command\n");
 
 864         data = *buf++ & ~VIA_VIDEOMASK;
 
 865         if (verify_mmio_address(data))
 
 869         if (*buf++ != 0x00F50000) {
 
 870                 DRM_ERROR("Illegal header5 header data\n");
 
 873         if (*buf++ != 0x00000000) {
 
 874                 DRM_ERROR("Illegal header5 header data\n");
 
 877         if (eat_words(&buf, buf_end, data))
 
 879         if ((data & 3) && verify_video_tail(&buf, buf_end, 4 - (data & 3)))
 
 882         return state_command;
 
 886 static __inline__ verifier_state_t
 
 887 via_parse_vheader5(drm_via_private_t * dev_priv, uint32_t const **buffer,
 
 888                    const uint32_t * buf_end)
 
 890         uint32_t addr, count, i;
 
 891         const uint32_t *buf = *buffer;
 
 893         addr = *buf++ & ~VIA_VIDEOMASK;
 
 897                 VIA_WRITE(addr, *buf++);
 
 900                 buf += 4 - (count & 3);
 
 902         return state_command;
 
 905 static __inline__ verifier_state_t
 
 906 via_check_vheader6(uint32_t const **buffer, const uint32_t * buf_end)
 
 909         const uint32_t *buf = *buffer;
 
 912         if (buf_end - buf < 4) {
 
 913                 DRM_ERROR("Illegal termination of video header6 command\n");
 
 918         if (*buf++ != 0x00F60000) {
 
 919                 DRM_ERROR("Illegal header6 header data\n");
 
 922         if (*buf++ != 0x00000000) {
 
 923                 DRM_ERROR("Illegal header6 header data\n");
 
 926         if ((buf_end - buf) < (data << 1)) {
 
 927                 DRM_ERROR("Illegal termination of video header6 command\n");
 
 930         for (i = 0; i < data; ++i) {
 
 931                 if (verify_mmio_address(*buf++))
 
 936         if ((data & 3) && verify_video_tail(&buf, buf_end, 4 - (data & 3)))
 
 939         return state_command;
 
 942 static __inline__ verifier_state_t
 
 943 via_parse_vheader6(drm_via_private_t * dev_priv, uint32_t const **buffer,
 
 944                    const uint32_t * buf_end)
 
 947         uint32_t addr, count, i;
 
 948         const uint32_t *buf = *buffer;
 
 954                 VIA_WRITE(addr, *buf++);
 
 958                 buf += 4 - (count & 3);
 
 960         return state_command;
 
 964 via_verify_command_stream(const uint32_t * buf, unsigned int size,
 
 965                           struct drm_device * dev, int agp)
 
 968         drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
 
 969         drm_via_state_t *hc_state = &dev_priv->hc_state;
 
 970         drm_via_state_t saved_state = *hc_state;
 
 972         const uint32_t *buf_end = buf + (size >> 2);
 
 973         verifier_state_t state = state_command;
 
 977         cme_video = (dev_priv->chipset == VIA_PRO_GROUP_A ||
 
 978                      dev_priv->chipset == VIA_DX9_0);
 
 980         supported_3d = dev_priv->chipset != VIA_DX9_0;
 
 983         hc_state->unfinished = no_sequence;
 
 984         hc_state->map_cache = NULL;
 
 986         hc_state->buf_start = buf;
 
 987         dev_priv->num_fire_offsets = 0;
 
 989         while (buf < buf_end) {
 
 993                         state = via_check_header2(&buf, buf_end, hc_state);
 
 996                         state = via_check_header1(&buf, buf_end);
 
 999                         state = via_check_vheader5(&buf, buf_end);
 
1001                 case state_vheader6:
 
1002                         state = via_check_vheader6(&buf, buf_end);
 
1005                         if ((HALCYON_HEADER2 == (cmd = *buf)) &&
 
1007                                 state = state_header2;
 
1008                         else if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1)
 
1009                                 state = state_header1;
 
1011                                  && (cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5)
 
1012                                 state = state_vheader5;
 
1014                                  && (cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6)
 
1015                                 state = state_vheader6;
 
1016                         else if ((cmd == HALCYON_HEADER2) && !supported_3d) {
 
1017                                 DRM_ERROR("Accelerated 3D is not supported on this chipset yet.\n");
 
1018                                 state = state_error;
 
1021                                     ("Invalid / Unimplemented DMA HEADER command. 0x%x\n",
 
1023                                 state = state_error;
 
1028                         *hc_state = saved_state;
 
1032         if (state == state_error) {
 
1033                 *hc_state = saved_state;
 
1040 via_parse_command_stream(struct drm_device * dev, const uint32_t * buf,
 
1044         drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
 
1046         const uint32_t *buf_end = buf + (size >> 2);
 
1047         verifier_state_t state = state_command;
 
1050         while (buf < buf_end) {
 
1055                             via_parse_header2(dev_priv, &buf, buf_end,
 
1059                         state = via_parse_header1(dev_priv, &buf, buf_end);
 
1061                 case state_vheader5:
 
1062                         state = via_parse_vheader5(dev_priv, &buf, buf_end);
 
1064                 case state_vheader6:
 
1065                         state = via_parse_vheader6(dev_priv, &buf, buf_end);
 
1068                         if (HALCYON_HEADER2 == (cmd = *buf))
 
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;
 
1078                                     ("Invalid / Unimplemented DMA HEADER command. 0x%x\n",
 
1080                                 state = state_error;
 
1088         if (state == state_error) {
 
1095 setup_hazard_table(hz_init_t init_table[], hazard_t table[], int size)
 
1099         for (i = 0; i < 256; ++i) {
 
1100                 table[i] = forbidden_command;
 
1103         for (i = 0; i < size; ++i) {
 
1104                 table[init_table[i].code] = init_table[i].hz;
 
1108 void via_init_command_verifier(void)
 
1110         setup_hazard_table(init_table1, table1,
 
1111                            sizeof(init_table1) / sizeof(hz_init_t));
 
1112         setup_hazard_table(init_table2, table2,
 
1113                            sizeof(init_table2) / sizeof(hz_init_t));
 
1114         setup_hazard_table(init_table3, table3,
 
1115                            sizeof(init_table3) / sizeof(hz_init_t));