]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/char/drm/via_verifier.c
Merge master.kernel.org:/pub/scm/linux/kernel/git/lethal/sh-2.6
[linux-2.6-omap-h63xx.git] / drivers / char / drm / via_verifier.c
index 07923b0c7a97c9faf0603730310396c5b2ccb288..2e7e080782874717d62ca38cb4ef2ae206d127ff 100644 (file)
@@ -28,7 +28,6 @@
  * be very slow.
  */
 
-
 #include "via_3d_reg.h"
 #include "drmP.h"
 #include "drm.h"
@@ -36,7 +35,7 @@
 #include "via_verifier.h"
 #include "via_drv.h"
 
-typedef enum{
+typedef enum {
        state_command,
        state_header2,
        state_header1,
@@ -45,8 +44,7 @@ typedef enum{
        state_error
 } verifier_state_t;
 
-
-typedef enum{
+typedef enum {
        no_check = 0,
        check_for_header2,
        check_for_header1,
@@ -74,16 +72,16 @@ typedef enum{
        check_for_vertex_count,
        check_number_texunits,
        forbidden_command
-}hazard_t;
+} hazard_t;
 
 /*
  * Associates each hazard above with a possible multi-command
  * sequence. For example an address that is split over multiple
- * commands and that needs to be checked at the first command 
+ * commands and that needs to be checked at the first command
  * that does not include any part of the address.
  */
 
-static drm_via_sequence_t seqs[] = { 
+static drm_via_sequence_t seqs[] = {
        no_sequence,
        no_sequence,
        no_sequence,
@@ -110,14 +108,12 @@ static drm_via_sequence_t seqs[] = {
        tex_address,
        no_sequence
 };
-    
-typedef struct{
+
+typedef struct {
        unsigned int code;
        hazard_t hz;
 } hz_init_t;
 
-
-
 static hz_init_t init_table1[] = {
        {0xf2, check_for_header2_err},
        {0xf0, check_for_header1_err},
@@ -169,8 +165,6 @@ static hz_init_t init_table1[] = {
        {0x7D, check_for_vertex_count}
 };
 
-   
-                      
 static hz_init_t init_table2[] = {
        {0xf2, check_for_header2_err},
        {0xf0, check_for_header1_err},
@@ -235,49 +229,49 @@ static hz_init_t init_table3[] = {
        {0xcc, check_for_dummy},
        {0x00, check_number_texunits}
 };
-   
-                      
-static hazard_t table1[256]; 
-static hazard_t table2[256]; 
-static hazard_t table3[256]; 
-
 
+static hazard_t table1[256];
+static hazard_t table2[256];
+static hazard_t table3[256];
 
 static __inline__ int
-eat_words(const uint32_t **buf, const uint32_t *buf_end, unsigned num_words)
+eat_words(const uint32_t ** buf, const uint32_t * buf_end, unsigned num_words)
 {
-       if ((*buf - buf_end) >= num_words) {
+       if ((buf_end - *buf) >= num_words) {
                *buf += num_words;
                return 0;
-       } 
+       }
        DRM_ERROR("Illegal termination of DMA command buffer\n");
        return 1;
 }
 
-
 /*
  * Partially stolen from drm_memory.h
  */
 
-static __inline__ drm_map_t *
-via_drm_lookup_agp_map (drm_via_state_t *seq, unsigned long offset, unsigned long size, 
-                       drm_device_t *dev)
+static __inline__ drm_local_map_t *via_drm_lookup_agp_map(drm_via_state_t *seq,
+                                                   unsigned long offset,
+                                                   unsigned long size,
+                                                   drm_device_t * dev)
 {
        struct list_head *list;
        drm_map_list_t *r_list;
-       drm_map_t *map = seq->map_cache;
+       drm_local_map_t *map = seq->map_cache;
 
-       if (map && map->offset <= offset && (offset + size) <= (map->offset + map->size)) {
+       if (map && map->offset <= offset
+           && (offset + size) <= (map->offset + map->size)) {
                return map;
        }
-               
+
        list_for_each(list, &dev->maplist->head) {
                r_list = (drm_map_list_t *) list;
                map = r_list->map;
                if (!map)
                        continue;
-               if (map->offset <= offset && (offset + size) <= (map->offset + map->size) && 
-                   !(map->flags & _DRM_RESTRICTED) && (map->type == _DRM_AGP)) {
+               if (map->offset <= offset
+                   && (offset + size) <= (map->offset + map->size)
+                   && !(map->flags & _DRM_RESTRICTED)
+                   && (map->type == _DRM_AGP)) {
                        seq->map_cache = map;
                        return map;
                }
@@ -285,54 +279,64 @@ via_drm_lookup_agp_map (drm_via_state_t *seq, unsigned long offset, unsigned lon
        return NULL;
 }
 
-
 /*
- * Require that all AGP texture levels reside in the same AGP map which should 
+ * Require that all AGP texture levels reside in the same AGP map which should
  * be mappable by the client. This is not a big restriction.
- * FIXME: To actually enforce this security policy strictly, drm_rmmap 
- * would have to wait for dma quiescent before removing an AGP map. 
+ * FIXME: To actually enforce this security policy strictly, drm_rmmap
+ * would have to wait for dma quiescent before removing an AGP map.
  * The via_drm_lookup_agp_map call in reality seems to take
  * very little CPU time.
  */
 
-
-static __inline__ int
-finish_current_sequence(drm_via_state_t *cur_seq) 
+static __inline__ int finish_current_sequence(drm_via_state_t * cur_seq)
 {
-       switch(cur_seq->unfinished) {
+       switch (cur_seq->unfinished) {
        case z_address:
                DRM_DEBUG("Z Buffer start address is 0x%x\n", cur_seq->z_addr);
                break;
        case dest_address:
-               DRM_DEBUG("Destination start address is 0x%x\n", cur_seq->d_addr);
+               DRM_DEBUG("Destination start address is 0x%x\n",
+                         cur_seq->d_addr);
                break;
        case tex_address:
-               if (cur_seq->agp_texture) {                      
-                       unsigned start = cur_seq->tex_level_lo[cur_seq->texture];
+               if (cur_seq->agp_texture) {
+                       unsigned start =
+                           cur_seq->tex_level_lo[cur_seq->texture];
                        unsigned end = cur_seq->tex_level_hi[cur_seq->texture];
-                       unsigned long lo=~0, hi=0, tmp;
+                       unsigned long lo = ~0, hi = 0, tmp;
                        uint32_t *addr, *pitch, *height, tex;
                        unsigned i;
+                       int npot;
 
-                       if (end > 9) end = 9;
-                       if (start > 9) start = 9;
+                       if (end > 9)
+                               end = 9;
+                       if (start > 9)
+                               start = 9;
 
-                       addr =&(cur_seq->t_addr[tex = cur_seq->texture][start]);
+                       addr =
+                           &(cur_seq->t_addr[tex = cur_seq->texture][start]);
                        pitch = &(cur_seq->pitch[tex][start]);
                        height = &(cur_seq->height[tex][start]);
-
-                       for (i=start; i<= end; ++i) {
+                       npot = cur_seq->tex_npot[tex];
+                       for (i = start; i <= end; ++i) {
                                tmp = *addr++;
-                               if (tmp < lo) lo = tmp;
-                               tmp += (*height++ << *pitch++);
-                               if (tmp > hi) hi = tmp;
+                               if (tmp < lo)
+                                       lo = tmp;
+                               if (i == 0 && npot)
+                                       tmp += (*height++ * *pitch++);
+                               else
+                                       tmp += (*height++ << *pitch++);
+                               if (tmp > hi)
+                                       hi = tmp;
                        }
 
-                       if (! via_drm_lookup_agp_map (cur_seq, lo, hi - lo, cur_seq->dev)) {
-                               DRM_ERROR("AGP texture is not in allowed map\n");
+                       if (!via_drm_lookup_agp_map
+                           (cur_seq, lo, hi - lo, cur_seq->dev)) {
+                               DRM_ERROR
+                                   ("AGP texture is not in allowed map\n");
                                return 2;
                        }
-               }       
+               }
                break;
        default:
                break;
@@ -341,73 +345,84 @@ finish_current_sequence(drm_via_state_t *cur_seq)
        return 0;
 }
 
-static __inline__ int 
-investigate_hazard( uint32_t cmd, hazard_t hz, drm_via_state_t *cur_seq)
+static __inline__ int
+investigate_hazard(uint32_t cmd, hazard_t hz, drm_via_state_t * cur_seq)
 {
        register uint32_t tmp, *tmp_addr;
 
        if (cur_seq->unfinished && (cur_seq->unfinished != seqs[hz])) {
                int ret;
-               if ((ret = finish_current_sequence(cur_seq))) return ret;
+               if ((ret = finish_current_sequence(cur_seq)))
+                       return ret;
        }
 
-       switch(hz) {
+       switch (hz) {
        case check_for_header2:
-               if (cmd == HALCYON_HEADER2) return 1;
+               if (cmd == HALCYON_HEADER2)
+                       return 1;
                return 0;
        case check_for_header1:
-               if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1) return 1;
+               if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1)
+                       return 1;
                return 0;
        case check_for_header2_err:
-               if (cmd == HALCYON_HEADER2) return 1;
+               if (cmd == HALCYON_HEADER2)
+                       return 1;
                DRM_ERROR("Illegal DMA HALCYON_HEADER2 command\n");
                break;
        case check_for_header1_err:
-               if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1) return 1;
+               if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1)
+                       return 1;
                DRM_ERROR("Illegal DMA HALCYON_HEADER1 command\n");
                break;
        case check_for_fire:
-               if ((cmd & HALCYON_FIREMASK) == HALCYON_FIRECMD) return 1; 
+               if ((cmd & HALCYON_FIREMASK) == HALCYON_FIRECMD)
+                       return 1;
                DRM_ERROR("Illegal DMA HALCYON_FIRECMD command\n");
                break;
        case check_for_dummy:
-               if (HC_DUMMY == cmd) return 0;
+               if (HC_DUMMY == cmd)
+                       return 0;
                DRM_ERROR("Illegal DMA HC_DUMMY command\n");
                break;
        case check_for_dd:
-               if (0xdddddddd == cmd) return 0;
+               if (0xdddddddd == cmd)
+                       return 0;
                DRM_ERROR("Illegal DMA 0xdddddddd command\n");
                break;
        case check_z_buffer_addr0:
                cur_seq->unfinished = z_address;
                cur_seq->z_addr = (cur_seq->z_addr & 0xFF000000) |
-                       (cmd & 0x00FFFFFF);
+                   (cmd & 0x00FFFFFF);
                return 0;
        case check_z_buffer_addr1:
                cur_seq->unfinished = z_address;
                cur_seq->z_addr = (cur_seq->z_addr & 0x00FFFFFF) |
-                       ((cmd & 0xFF) << 24);
+                   ((cmd & 0xFF) << 24);
                return 0;
        case check_z_buffer_addr_mode:
                cur_seq->unfinished = z_address;
-               if ((cmd & 0x0000C000) == 0) return 0;
+               if ((cmd & 0x0000C000) == 0)
+                       return 0;
                DRM_ERROR("Attempt to place Z buffer in system memory\n");
                return 2;
        case check_destination_addr0:
                cur_seq->unfinished = dest_address;
                cur_seq->d_addr = (cur_seq->d_addr & 0xFF000000) |
-                       (cmd & 0x00FFFFFF);
+                   (cmd & 0x00FFFFFF);
                return 0;
        case check_destination_addr1:
                cur_seq->unfinished = dest_address;
                cur_seq->d_addr = (cur_seq->d_addr & 0x00FFFFFF) |
-                       ((cmd & 0xFF) << 24);
+                   ((cmd & 0xFF) << 24);
                return 0;
        case check_destination_addr_mode:
                cur_seq->unfinished = dest_address;
-               if ((cmd & 0x0000C000) == 0) return 0;
-               DRM_ERROR("Attempt to place 3D drawing buffer in system memory\n");
-               return 2;           
+               if ((cmd & 0x0000C000) == 0)
+                       return 0;
+               DRM_ERROR
+                   ("Attempt to place 3D drawing buffer in system memory\n");
+               return 2;
        case check_texture_addr0:
                cur_seq->unfinished = tex_address;
                tmp = (cmd >> 24);
@@ -432,11 +447,21 @@ investigate_hazard( uint32_t cmd, hazard_t hz, drm_via_state_t *cur_seq)
                return 0;
        case check_texture_addr3:
                cur_seq->unfinished = tex_address;
-               tmp = ((cmd >> 24) - 0x2B);
-               cur_seq->pitch[cur_seq->texture][tmp] = (cmd & 0x00F00000) >> 20;
-               if (!tmp && (cmd & 0x000FFFFF)) {
-                       DRM_ERROR("Unimplemented texture level 0 pitch mode.\n");
-                       return 2;
+               tmp = ((cmd >> 24) - HC_SubA_HTXnL0Pit);
+               if (tmp == 0 &&
+                   (cmd & HC_HTXnEnPit_MASK)) {
+                       cur_seq->pitch[cur_seq->texture][tmp] =
+                               (cmd & HC_HTXnLnPit_MASK);
+                       cur_seq->tex_npot[cur_seq->texture] = 1;
+               } else {
+                       cur_seq->pitch[cur_seq->texture][tmp] =
+                               (cmd & HC_HTXnLnPitE_MASK) >> HC_HTXnLnPitE_SHIFT;
+                       cur_seq->tex_npot[cur_seq->texture] = 0;
+                       if (cmd & 0x000FFFFF) {
+                               DRM_ERROR
+                                       ("Unimplemented texture level 0 pitch mode.\n");
+                               return 2;
+                       }
                }
                return 0;
        case check_texture_addr4:
@@ -449,7 +474,7 @@ investigate_hazard( uint32_t cmd, hazard_t hz, drm_via_state_t *cur_seq)
                cur_seq->unfinished = tex_address;
                /*
                 * Texture width. We don't care since we have the pitch.
-                */  
+                */
                return 0;
        case check_texture_addr7:
                cur_seq->unfinished = tex_address;
@@ -465,25 +490,26 @@ investigate_hazard( uint32_t cmd, hazard_t hz, drm_via_state_t *cur_seq)
                cur_seq->unfinished = tex_address;
                tmp_addr = &(cur_seq->height[cur_seq->texture][0]);
                tmp_addr[9] = 1 << ((cmd & 0x0000F000) >> 12);
-               tmp_addr[8] = 1 << ((cmd & 0x00000F00) >> 8);
+               tmp_addr[8] = 1 << ((cmd & 0x00000F00) >> 8);
                tmp_addr[7] = 1 << ((cmd & 0x000000F0) >> 4);
                tmp_addr[6] = 1 << (cmd & 0x0000000F);
                return 0;
        case check_texture_addr_mode:
                cur_seq->unfinished = tex_address;
-               if ( 2 == (tmp = cmd & 0x00000003)) {
-                       DRM_ERROR("Attempt to fetch texture from system memory.\n"); 
+               if (2 == (tmp = cmd & 0x00000003)) {
+                       DRM_ERROR
+                           ("Attempt to fetch texture from system memory.\n");
                        return 2;
                }
                cur_seq->agp_texture = (tmp == 3);
-               cur_seq->tex_palette_size[cur_seq->texture] = 
-                       (cmd >> 16) & 0x000000007;
+               cur_seq->tex_palette_size[cur_seq->texture] =
+                   (cmd >> 16) & 0x000000007;
                return 0;
        case check_for_vertex_count:
                cur_seq->vertex_count = cmd & 0x0000FFFF;
                return 0;
        case check_number_texunits:
-               cur_seq->multitex = (cmd >> 3) & 1;
+               cur_seq->multitex = (cmd >> 3) & 1;
                return 0;
        default:
                DRM_ERROR("Illegal DMA data: 0x%x\n", cmd);
@@ -492,25 +518,27 @@ investigate_hazard( uint32_t cmd, hazard_t hz, drm_via_state_t *cur_seq)
        return 2;
 }
 
-
 static __inline__ int
-via_check_prim_list(uint32_t const **buffer, const uint32_t *buf_end,
-                   drm_via_state_t *cur_seq)
+via_check_prim_list(uint32_t const **buffer, const uint32_t * buf_end,
+                   drm_via_state_t * cur_seq)
 {
-       drm_via_private_t *dev_priv = (drm_via_private_t *) cur_seq->dev->dev_private;
-       uint32_t a_fire, bcmd , dw_count;
+       drm_via_private_t *dev_priv =
+           (drm_via_private_t *) cur_seq->dev->dev_private;
+       uint32_t a_fire, bcmd, dw_count;
        int ret = 0;
        int have_fire;
        const uint32_t *buf = *buffer;
 
-       while(buf < buf_end) {
-               have_fire = 0;
+       while (buf < buf_end) {
+               have_fire = 0;
                if ((buf_end - buf) < 2) {
-                       DRM_ERROR("Unexpected termination of primitive list.\n");
+                       DRM_ERROR
+                           ("Unexpected termination of primitive list.\n");
                        ret = 1;
                        break;
                }
-               if ((*buf & HC_ACMD_MASK) != HC_ACMD_HCmdB) break;
+               if ((*buf & HC_ACMD_MASK) != HC_ACMD_HCmdB)
+                       break;
                bcmd = *buf++;
                if ((*buf & HC_ACMD_MASK) != HC_ACMD_HCmdA) {
                        DRM_ERROR("Expected Vertex List A command, got 0x%x\n",
@@ -518,43 +546,56 @@ via_check_prim_list(uint32_t const **buffer, const uint32_t *buf_end,
                        ret = 1;
                        break;
                }
-               a_fire = *buf++ | HC_HPLEND_MASK | HC_HPMValidN_MASK | HC_HE3Fire_MASK; 
-       
+               a_fire =
+                   *buf++ | HC_HPLEND_MASK | HC_HPMValidN_MASK |
+                   HC_HE3Fire_MASK;
+
                /*
                 * How many dwords per vertex ?
-                */ 
-               
+                */
+
                if (cur_seq->agp && ((bcmd & (0xF << 11)) == 0)) {
                        DRM_ERROR("Illegal B command vertex data for AGP.\n");
                        ret = 1;
                        break;
-               } 
+               }
 
                dw_count = 0;
-               if (bcmd & (1 << 7)) dw_count += (cur_seq->multitex) ? 2:1;
-               if (bcmd & (1 << 8)) dw_count += (cur_seq->multitex) ? 2:1;
-               if (bcmd & (1 << 9)) dw_count++;
-               if (bcmd & (1 << 10)) dw_count++;
-               if (bcmd & (1 << 11)) dw_count++;
-               if (bcmd & (1 << 12)) dw_count++;
-               if (bcmd & (1 << 13)) dw_count++;
-               if (bcmd & (1 << 14)) dw_count++;
-
-               while(buf < buf_end) {
+               if (bcmd & (1 << 7))
+                       dw_count += (cur_seq->multitex) ? 2 : 1;
+               if (bcmd & (1 << 8))
+                       dw_count += (cur_seq->multitex) ? 2 : 1;
+               if (bcmd & (1 << 9))
+                       dw_count++;
+               if (bcmd & (1 << 10))
+                       dw_count++;
+               if (bcmd & (1 << 11))
+                       dw_count++;
+               if (bcmd & (1 << 12))
+                       dw_count++;
+               if (bcmd & (1 << 13))
+                       dw_count++;
+               if (bcmd & (1 << 14))
+                       dw_count++;
+
+               while (buf < buf_end) {
                        if (*buf == a_fire) {
-                               if (dev_priv->num_fire_offsets >= VIA_FIRE_BUF_SIZE) {
+                               if (dev_priv->num_fire_offsets >=
+                                   VIA_FIRE_BUF_SIZE) {
                                        DRM_ERROR("Fire offset buffer full.\n");
                                        ret = 1;
                                        break;
                                }
-                               dev_priv->fire_offsets[dev_priv->num_fire_offsets++] = buf;
-                               have_fire = 1;
+                               dev_priv->fire_offsets[dev_priv->
+                                                      num_fire_offsets++] =
+                                   buf;
+                               have_fire = 1;
                                buf++;
-                               if (buf < buf_end && *buf == a_fire) 
+                               if (buf < buf_end && *buf == a_fire)
                                        buf++;
                                break;
                        }
-                       if ((*buf == HALCYON_HEADER2) || 
+                       if ((*buf == HALCYON_HEADER2) ||
                            ((*buf & HALCYON_FIREMASK) == HALCYON_FIRECMD)) {
                                DRM_ERROR("Missing Vertex Fire command, "
                                          "Stray Vertex Fire command  or verifier "
@@ -576,18 +617,14 @@ via_check_prim_list(uint32_t const **buffer, const uint32_t *buf_end,
                        ret = 1;
                        break;
                }
-       } 
+       }
        *buffer = buf;
        return ret;
 }
 
-
-                      
-
-
 static __inline__ verifier_state_t
-via_check_header2( uint32_t const **buffer, const uint32_t *buf_end, 
-                  drm_via_state_t *hc_state)
+via_check_header2(uint32_t const **buffer, const uint32_t * buf_end,
+                 drm_via_state_t * hc_state)
 {
        uint32_t cmd;
        int hz_mode;
@@ -595,17 +632,17 @@ via_check_header2( uint32_t const **buffer, const uint32_t *buf_end,
        const uint32_t *buf = *buffer;
        const hazard_t *hz_table;
 
-
        if ((buf_end - buf) < 2) {
-               DRM_ERROR("Illegal termination of DMA HALCYON_HEADER2 sequence.\n");
+               DRM_ERROR
+                   ("Illegal termination of DMA HALCYON_HEADER2 sequence.\n");
                return state_error;
        }
        buf++;
        cmd = (*buf++ & 0xFFFF0000) >> 16;
 
-       switch(cmd) {
+       switch (cmd) {
        case HC_ParaType_CmdVdata:
-               if (via_check_prim_list(&buf, buf_end, hc_state )) 
+               if (via_check_prim_list(&buf, buf_end, hc_state))
                        return state_error;
                *buffer = buf;
                return state_command;
@@ -650,13 +687,13 @@ via_check_header2( uint32_t const **buffer, const uint32_t *buf_end,
                 */
 
                DRM_ERROR("Invalid or unimplemented HALCYON_HEADER2 "
-                         "DMA subcommand: 0x%x. Previous dword: 0x%x\n", 
-                         cmd, *(buf -2));
+                         "DMA subcommand: 0x%x. Previous dword: 0x%x\n",
+                         cmd, *(buf - 2));
                *buffer = buf;
                return state_error;
        }
 
-       while(buf < buf_end) {
+       while (buf < buf_end) {
                cmd = *buf++;
                if ((hz = hz_table[cmd >> 24])) {
                        if ((hz_mode = investigate_hazard(cmd, hz, hc_state))) {
@@ -666,7 +703,7 @@ via_check_header2( uint32_t const **buffer, const uint32_t *buf_end,
                                }
                                return state_error;
                        }
-               } else if (hc_state->unfinished && 
+               } else if (hc_state->unfinished &&
                           finish_current_sequence(hc_state)) {
                        return state_error;
                }
@@ -679,64 +716,65 @@ via_check_header2( uint32_t const **buffer, const uint32_t *buf_end,
 }
 
 static __inline__ verifier_state_t
-via_parse_header2( drm_via_private_t *dev_priv, uint32_t const **buffer, const uint32_t *buf_end,
-                  int *fire_count)
+via_parse_header2(drm_via_private_t * dev_priv, uint32_t const **buffer,
+                 const uint32_t * buf_end, int *fire_count)
 {
        uint32_t cmd;
        const uint32_t *buf = *buffer;
-       const uint32_t *next_fire; 
+       const uint32_t *next_fire;
        int burst = 0;
 
        next_fire = dev_priv->fire_offsets[*fire_count];
        buf++;
        cmd = (*buf & 0xFFFF0000) >> 16;
        VIA_WRITE(HC_REG_TRANS_SET + HC_REG_BASE, *buf++);
-       switch(cmd) {
+       switch (cmd) {
        case HC_ParaType_CmdVdata:
                while ((buf < buf_end) &&
-                      (*fire_count < dev_priv->num_fire_offsets) && 
-                      (*buf & HC_ACMD_MASK) == HC_ACMD_HCmdB ) {
-                       while(buf <= next_fire) {
-                               VIA_WRITE(HC_REG_TRANS_SPACE + HC_REG_BASE + (burst & 63), *buf++);
+                      (*fire_count < dev_priv->num_fire_offsets) &&
+                      (*buf & HC_ACMD_MASK) == HC_ACMD_HCmdB) {
+                       while (buf <= next_fire) {
+                               VIA_WRITE(HC_REG_TRANS_SPACE + HC_REG_BASE +
+                                         (burst & 63), *buf++);
                                burst += 4;
                        }
-                       if ( ( buf < buf_end ) && ((*buf & HALCYON_FIREMASK) == HALCYON_FIRECMD))
+                       if ((buf < buf_end)
+                           && ((*buf & HALCYON_FIREMASK) == HALCYON_FIRECMD))
                                buf++;
 
-                       if (++(*fire_count) < dev_priv->num_fire_offsets) 
+                       if (++(*fire_count) < dev_priv->num_fire_offsets)
                                next_fire = dev_priv->fire_offsets[*fire_count];
                }
                break;
        default:
-               while(buf < buf_end) {
-                       
-                       if ( *buf == HC_HEADER2 ||
-                            (*buf & HALCYON_HEADER1MASK) == HALCYON_HEADER1  ||
-                            (*buf & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5 ||
-                            (*buf & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6 ) break;
-                       
-                       VIA_WRITE(HC_REG_TRANS_SPACE + HC_REG_BASE + (burst & 63), *buf++);
-                       burst +=4;
+               while (buf < buf_end) {
+
+                       if (*buf == HC_HEADER2 ||
+                           (*buf & HALCYON_HEADER1MASK) == HALCYON_HEADER1 ||
+                           (*buf & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5 ||
+                           (*buf & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6)
+                               break;
+
+                       VIA_WRITE(HC_REG_TRANS_SPACE + HC_REG_BASE +
+                                 (burst & 63), *buf++);
+                       burst += 4;
                }
        }
        *buffer = buf;
        return state_command;
 }
 
-
-
-static __inline__ int
-verify_mmio_address( uint32_t address)
+static __inline__ int verify_mmio_address(uint32_t address)
 {
-       if ((address > 0x3FF) && (address < 0xC00 )) {
+       if ((address > 0x3FF) && (address < 0xC00)) {
                DRM_ERROR("Invalid VIDEO DMA command. "
                          "Attempt to access 3D- or command burst area.\n");
                return 1;
        } else if ((address > 0xCFF) && (address < 0x1300)) {
                DRM_ERROR("Invalid VIDEO DMA command. "
                          "Attempt to access PCI DMA area.\n");
-               return 1;               
-       } else if (address > 0x13FF ) {
+               return 1;
+       } else if (address > 0x13FF) {
                DRM_ERROR("Invalid VIDEO DMA command. "
                          "Attempt to access VGA registers.\n");
                return 1;
@@ -745,7 +783,8 @@ verify_mmio_address( uint32_t address)
 }
 
 static __inline__ int
-verify_video_tail( uint32_t const **buffer, const uint32_t *buf_end, uint32_t dwords) 
+verify_video_tail(uint32_t const **buffer, const uint32_t * buf_end,
+                 uint32_t dwords)
 {
        const uint32_t *buf = *buffer;
 
@@ -762,10 +801,9 @@ verify_video_tail( uint32_t const **buffer, const uint32_t *buf_end, uint32_t dw
        *buffer = buf;
        return 0;
 }
-               
 
 static __inline__ verifier_state_t
-via_check_header1( uint32_t const **buffer, const uint32_t *buf_end )
+via_check_header1(uint32_t const **buffer, const uint32_t * buf_end)
 {
        uint32_t cmd;
        const uint32_t *buf = *buffer;
@@ -774,21 +812,21 @@ via_check_header1( uint32_t const **buffer, const uint32_t *buf_end )
        while (buf < buf_end) {
                cmd = *buf;
                if ((cmd > ((0x3FF >> 2) | HALCYON_HEADER1)) &&
-                   (cmd < ((0xC00 >> 2) | HALCYON_HEADER1))) {                 
-                       if ((cmd & HALCYON_HEADER1MASK) != HALCYON_HEADER1) 
+                   (cmd < ((0xC00 >> 2) | HALCYON_HEADER1))) {
+                       if ((cmd & HALCYON_HEADER1MASK) != HALCYON_HEADER1)
                                break;
                        DRM_ERROR("Invalid HALCYON_HEADER1 command. "
                                  "Attempt to access 3D- or command burst area.\n");
                        ret = state_error;
                        break;
                } else if (cmd > ((0xCFF >> 2) | HALCYON_HEADER1)) {
-                       if ((cmd & HALCYON_HEADER1MASK) != HALCYON_HEADER1) 
+                       if ((cmd & HALCYON_HEADER1MASK) != HALCYON_HEADER1)
                                break;
                        DRM_ERROR("Invalid HALCYON_HEADER1 command. "
                                  "Attempt to access VGA registers.\n");
                        ret = state_error;
-                       break;                  
-               } else {                        
+                       break;
+               } else {
                        buf += 2;
                }
        }
@@ -797,15 +835,17 @@ via_check_header1( uint32_t const **buffer, const uint32_t *buf_end )
 }
 
 static __inline__ verifier_state_t
-via_parse_header1( drm_via_private_t *dev_priv, uint32_t const **buffer, const uint32_t *buf_end )
+via_parse_header1(drm_via_private_t * dev_priv, uint32_t const **buffer,
+                 const uint32_t * buf_end)
 {
        register uint32_t cmd;
        const uint32_t *buf = *buffer;
 
        while (buf < buf_end) {
                cmd = *buf;
-               if ((cmd & HALCYON_HEADER1MASK) != HALCYON_HEADER1) break;
-               VIA_WRITE( (cmd & ~HALCYON_HEADER1MASK) << 2, *++buf); 
+               if ((cmd & HALCYON_HEADER1MASK) != HALCYON_HEADER1)
+                       break;
+               VIA_WRITE((cmd & ~HALCYON_HEADER1MASK) << 2, *++buf);
                buf++;
        }
        *buffer = buf;
@@ -813,7 +853,7 @@ via_parse_header1( drm_via_private_t *dev_priv, uint32_t const **buffer, const u
 }
 
 static __inline__ verifier_state_t
-via_check_vheader5( uint32_t const **buffer, const uint32_t *buf_end )
+via_check_vheader5(uint32_t const **buffer, const uint32_t * buf_end)
 {
        uint32_t data;
        const uint32_t *buf = *buffer;
@@ -836,41 +876,41 @@ via_check_vheader5( uint32_t const **buffer, const uint32_t *buf_end )
                DRM_ERROR("Illegal header5 header data\n");
                return state_error;
        }
-       if (eat_words(&buf, buf_end, data)) 
+       if (eat_words(&buf, buf_end, data))
                return state_error;
-       if ((data & 3) && verify_video_tail(&buf, buf_end, 4 - (data & 3))) 
+       if ((data & 3) && verify_video_tail(&buf, buf_end, 4 - (data & 3)))
                return state_error;
        *buffer = buf;
        return state_command;
-              
-} 
+
+}
 
 static __inline__ verifier_state_t
-via_parse_vheader5( drm_via_private_t *dev_priv, uint32_t const **buffer, const uint32_t *buf_end )
+via_parse_vheader5(drm_via_private_t * dev_priv, uint32_t const **buffer,
+                  const uint32_t * buf_end)
 {
-  uint32_t addr, count, i;
+       uint32_t addr, count, i;
        const uint32_t *buf = *buffer;
-       
+
        addr = *buf++ & ~VIA_VIDEOMASK;
        i = count = *buf;
        buf += 3;
-       while(i--) {
+       while (i--) {
                VIA_WRITE(addr, *buf++);
        }
-       if (count & 3) buf += 4 - (count & 3);
+       if (count & 3)
+               buf += 4 - (count & 3);
        *buffer = buf;
-       return state_command;          
-} 
-
+       return state_command;
+}
 
 static __inline__ verifier_state_t
-via_check_vheader6( uint32_t const **buffer, const uint32_t *buf_end )
+via_check_vheader6(uint32_t const **buffer, const uint32_t * buf_end)
 {
        uint32_t data;
        const uint32_t *buf = *buffer;
        uint32_t i;
 
-
        if (buf_end - buf < 4) {
                DRM_ERROR("Illegal termination of video header6 command\n");
                return state_error;
@@ -889,7 +929,7 @@ via_check_vheader6( uint32_t const **buffer, const uint32_t *buf_end )
                DRM_ERROR("Illegal termination of video header6 command\n");
                return state_error;
        }
-       for (i=0; i<data; ++i) {
+       for (i = 0; i < data; ++i) {
                if (verify_mmio_address(*buf++))
                        return state_error;
                buf++;
@@ -899,42 +939,48 @@ via_check_vheader6( uint32_t const **buffer, const uint32_t *buf_end )
                return state_error;
        *buffer = buf;
        return state_command;
-} 
+}
 
 static __inline__ verifier_state_t
-via_parse_vheader6( drm_via_private_t *dev_priv, uint32_t const **buffer, const uint32_t *buf_end )
+via_parse_vheader6(drm_via_private_t * dev_priv, uint32_t const **buffer,
+                  const uint32_t * buf_end)
 {
 
-  uint32_t addr, count, i;
+       uint32_t addr, count, i;
        const uint32_t *buf = *buffer;
 
        i = count = *++buf;
        buf += 3;
-       while(i--) {
+       while (i--) {
                addr = *buf++;
                VIA_WRITE(addr, *buf++);
        }
        count <<= 1;
-       if (count & 3) buf += 4 - (count & 3);
+       if (count & 3)
+               buf += 4 - (count & 3);
        *buffer = buf;
        return state_command;
-} 
-
-
+}
 
-int 
-via_verify_command_stream(const uint32_t * buf, unsigned int size, drm_device_t *dev,
-                         int agp)
+int
+via_verify_command_stream(const uint32_t * buf, unsigned int size,
+                         drm_device_t * dev, int agp)
 {
 
        drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
        drm_via_state_t *hc_state = &dev_priv->hc_state;
        drm_via_state_t saved_state = *hc_state;
        uint32_t cmd;
-       const uint32_t *buf_end = buf + ( size >> 2 );
+       const uint32_t *buf_end = buf + (size >> 2);
        verifier_state_t state = state_command;
-       int pro_group_a = dev_priv->pro_group_a;
-       
+       int cme_video;
+       int supported_3d;
+
+       cme_video = (dev_priv->chipset == VIA_PRO_GROUP_A ||
+                    dev_priv->chipset == VIA_DX9_0);
+
+       supported_3d = dev_priv->chipset != VIA_DX9_0;
+
        hc_state->dev = dev;
        hc_state->unfinished = no_sequence;
        hc_state->map_cache = NULL;
@@ -946,38 +992,45 @@ via_verify_command_stream(const uint32_t * buf, unsigned int size, drm_device_t
 
                switch (state) {
                case state_header2:
-                 state = via_check_header2( &buf, buf_end, hc_state );
+                       state = via_check_header2(&buf, buf_end, hc_state);
                        break;
                case state_header1:
-                       state = via_check_header1( &buf, buf_end );
+                       state = via_check_header1(&buf, buf_end);
                        break;
                case state_vheader5:
-                       state = via_check_vheader5( &buf, buf_end );
+                       state = via_check_vheader5(&buf, buf_end);
                        break;
                case state_vheader6:
-                       state = via_check_vheader6( &buf, buf_end );
+                       state = via_check_vheader6(&buf, buf_end);
                        break;
                case state_command:
-                       if (HALCYON_HEADER2 == (cmd = *buf)) 
+                       if ((HALCYON_HEADER2 == (cmd = *buf)) &&
+                           supported_3d)
                                state = state_header2;
-                       else if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1) 
+                       else if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1)
                                state = state_header1;
-                       else if (pro_group_a && (cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5)
+                       else if (cme_video
+                                && (cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5)
                                state = state_vheader5;
-                       else if (pro_group_a && (cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6)
+                       else if (cme_video
+                                && (cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6)
                                state = state_vheader6;
-                       else {
-                               DRM_ERROR("Invalid / Unimplemented DMA HEADER command. 0x%x\n",
-                                         cmd);
+                       else if ((cmd == HALCYON_HEADER2) && !supported_3d) {
+                               DRM_ERROR("Accelerated 3D is not supported on this chipset yet.\n");
+                               state = state_error;
+                       } else {
+                               DRM_ERROR
+                                   ("Invalid / Unimplemented DMA HEADER command. 0x%x\n",
+                                    cmd);
                                state = state_error;
                        }
                        break;
                case state_error:
                default:
                        *hc_state = saved_state;
-                       return DRM_ERR(EINVAL);                 
+                       return DRM_ERR(EINVAL);
                }
-       }       
+       }
        if (state == state_error) {
                *hc_state = saved_state;
                return DRM_ERR(EINVAL);
@@ -985,77 +1038,81 @@ via_verify_command_stream(const uint32_t * buf, unsigned int size, drm_device_t
        return 0;
 }
 
-int 
-via_parse_command_stream(drm_device_t *dev, const uint32_t * buf, unsigned int size)
+int
+via_parse_command_stream(drm_device_t * dev, const uint32_t * buf,
+                        unsigned int size)
 {
 
        drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
        uint32_t cmd;
-       const uint32_t *buf_end = buf + ( size >> 2 );
+       const uint32_t *buf_end = buf + (size >> 2);
        verifier_state_t state = state_command;
        int fire_count = 0;
-       
+
        while (buf < buf_end) {
 
                switch (state) {
                case state_header2:
-                 state = via_parse_header2( dev_priv, &buf, buf_end, &fire_count );
+                       state =
+                           via_parse_header2(dev_priv, &buf, buf_end,
+                                             &fire_count);
                        break;
                case state_header1:
-                       state = via_parse_header1( dev_priv, &buf, buf_end );
+                       state = via_parse_header1(dev_priv, &buf, buf_end);
                        break;
                case state_vheader5:
-                       state = via_parse_vheader5( dev_priv, &buf, buf_end );
+                       state = via_parse_vheader5(dev_priv, &buf, buf_end);
                        break;
                case state_vheader6:
-                       state = via_parse_vheader6( dev_priv, &buf, buf_end );
+                       state = via_parse_vheader6(dev_priv, &buf, buf_end);
                        break;
                case state_command:
-                       if (HALCYON_HEADER2 == (cmd = *buf)) 
+                       if (HALCYON_HEADER2 == (cmd = *buf))
                                state = state_header2;
-                       else if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1) 
+                       else if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1)
                                state = state_header1;
                        else if ((cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5)
                                state = state_vheader5;
                        else if ((cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6)
                                state = state_vheader6;
                        else {
-                               DRM_ERROR("Invalid / Unimplemented DMA HEADER command. 0x%x\n",
-                                         cmd);
+                               DRM_ERROR
+                                   ("Invalid / Unimplemented DMA HEADER command. 0x%x\n",
+                                    cmd);
                                state = state_error;
                        }
                        break;
                case state_error:
                default:
-                       return DRM_ERR(EINVAL);                 
+                       return DRM_ERR(EINVAL);
                }
-       }       
+       }
        if (state == state_error) {
                return DRM_ERR(EINVAL);
        }
        return 0;
 }
 
-
-
-static void 
+static void
 setup_hazard_table(hz_init_t init_table[], hazard_t table[], int size)
 {
        int i;
 
-       for(i=0; i<256; ++i) {
+       for (i = 0; i < 256; ++i) {
                table[i] = forbidden_command;
        }
 
-       for(i=0; i<size; ++i) {
+       for (i = 0; i < size; ++i) {
                table[init_table[i].code] = init_table[i].hz;
        }
 }
 
-void 
-via_init_command_verifier( void )
+void via_init_command_verifier(void)
 {
-       setup_hazard_table(init_table1, table1, sizeof(init_table1) / sizeof(hz_init_t));
-       setup_hazard_table(init_table2, table2, sizeof(init_table2) / sizeof(hz_init_t));
-       setup_hazard_table(init_table3, table3, sizeof(init_table3) / sizeof(hz_init_t));
+       setup_hazard_table(init_table1, table1,
+                          sizeof(init_table1) / sizeof(hz_init_t));
+       setup_hazard_table(init_table2, table2,
+                          sizeof(init_table2) / sizeof(hz_init_t));
+       setup_hazard_table(init_table3, table3,
+                          sizeof(init_table3) / sizeof(hz_init_t));
 }