From fb6a4d0a7dfd8e996dca6d45bb820979f231c82c Mon Sep 17 00:00:00 2001
From: Thomas Hellstrom <unichrome@shipmail.org>
Date: Fri, 7 Jan 2005 11:37:01 +0000
Subject: via updates: moved the verifier state struct to dev_priv. Implemented
 AGP     alignment check.

---
 linux-core/Makefile        |   4 +-
 shared-core/via_dma.c      |   4 +-
 shared-core/via_drv.h      |   6 ++-
 shared-core/via_verifier.c | 104 ++++++++++++++++++++-------------------------
 shared-core/via_verifier.h |  61 ++++++++++++++++++++++++++
 5 files changed, 116 insertions(+), 63 deletions(-)
 create mode 100644 shared-core/via_verifier.h

diff --git a/linux-core/Makefile b/linux-core/Makefile
index 1b1bc043..af363466 100644
--- a/linux-core/Makefile
+++ b/linux-core/Makefile
@@ -90,10 +90,10 @@ SISSHARED=      sis_drv.h sis_drm.h sis_ds.c sis_ds.h sis_mm.c
 SAVAGEHEADERS=  savage_drv.h savage_drm.h $(DRMHEADERS)
 SAVAGESHARED=	savage_drv.h savage_drm.h savage_bci.c savage_state.c
 VIAHEADERS =	via_drm.h via_drv.h via_mm.h via_ds.h \
-		via_3d_reg.h $(DRMHEADERS)
+		via_3d_reg.h via_verifier.h $(DRMHEADERS)
 VIASHARED	= via_drm.h via_drv.h via_mm.h via_ds.h \
 		via_3d_reg.h via_drv.c via_ds.c via_irq.c via_map.c \
-		via_mm.c via_dma.c via_verifier.c
+		via_mm.c via_dma.c via_verifier.c via_verifier.h
 MACH64HEADERS = mach64_drv.h mach64_drm.h $(DRMHEADERS)
 MACH64SHARED = 	mach64_drv.h mach64_drm.h mach64_dma.c \
 		mach64_irq.c mach64_state.c
diff --git a/shared-core/via_dma.c b/shared-core/via_dma.c
index d514e4d7..22cbcd28 100644
--- a/shared-core/via_dma.c
+++ b/shared-core/via_dma.c
@@ -281,7 +281,7 @@ static int via_dispatch_cmdbuffer(drm_device_t * dev, drm_via_cmdbuffer_t * cmd)
 	 */
 
 	
-	if ((ret = via_verify_command_stream((uint32_t *)pci_buf, cmd->size, dev))) {
+	if ((ret = via_verify_command_stream((uint32_t *)pci_buf, cmd->size, dev, 1))) {
 		return ret;
 	}
        	
@@ -347,7 +347,7 @@ static int via_parse_pci_cmdbuffer(drm_device_t * dev, const char *buf,
 	int ret;
 	int check_2d_cmd = 1;
 
-	if ((ret = via_verify_command_stream(regbuf, size, dev)))
+	if ((ret = via_verify_command_stream(regbuf, size, dev, 0)))
 		return ret;
 
 	while (regbuf != regend) {	
diff --git a/shared-core/via_drv.h b/shared-core/via_drv.h
index 05ae40ac..f8824301 100644
--- a/shared-core/via_drv.h
+++ b/shared-core/via_drv.h
@@ -32,7 +32,9 @@
 
 #define DRIVER_MAJOR		2
 #define DRIVER_MINOR		4
-#define DRIVER_PATCHLEVEL	2
+#define DRIVER_PATCHLEVEL	3
+
+#include "via_verifier.h"
 
 typedef struct drm_via_ring_buffer {
 	drm_map_t map;
@@ -57,6 +59,7 @@ typedef struct drm_via_private {
         struct timeval last_vblank;
         int last_vblank_valid;
         unsigned usec_per_vblank;
+	drm_via_state_t hc_state;
 } drm_via_private_t;
 
 /* VIA MMIO register access */
@@ -83,7 +86,6 @@ extern void via_driver_irq_uninstall(drm_device_t * dev);
 
 extern int via_dma_cleanup(drm_device_t * dev);
 extern void via_init_command_verifier(void);
-extern int via_verify_command_stream(const uint32_t * buf, unsigned int size, drm_device_t *dev);
 extern int via_wait_idle(drm_via_private_t * dev_priv);
 extern int via_driver_dma_quiescent(drm_device_t * dev);
 
diff --git a/shared-core/via_verifier.c b/shared-core/via_verifier.c
index 82a558cc..ad32141e 100644
--- a/shared-core/via_verifier.c
+++ b/shared-core/via_verifier.c
@@ -30,6 +30,10 @@
 
 #include "via_3d_reg.h"
 #include "drmP.h"
+#include "drm.h"
+#include "via_drm.h"
+#include "via_verifier.h"
+#include "via_drv.h"
 
 typedef enum{
 	state_command,
@@ -40,13 +44,6 @@ typedef enum{
 	state_error
 } verifier_state_t;
 
-typedef enum{
-	no_sequence = 0, 
-	z_address,
-	dest_address,
-	tex_address
-}sequence_t;
-
 
 typedef enum{
 	no_check = 0,
@@ -85,7 +82,7 @@ typedef enum{
  * that does not include any part of the address.
  */
 
-static sequence_t seqs[] = { 
+static drm_via_sequence_t seqs[] = { 
 	no_sequence,
 	no_sequence,
 	no_sequence,
@@ -245,27 +242,6 @@ static hazard_t table3[256];
 
 
 
-typedef struct{
-	unsigned texture;
-	uint32_t z_addr; 
-	uint32_t d_addr; 
-        uint32_t t_addr[2][10];
-	uint32_t pitch[2][10];
-	uint32_t height[2][10];
-	uint32_t tex_level_lo[2]; 
-	uint32_t tex_level_hi[2];
-	uint32_t tex_palette_size[2];
-	sequence_t unfinished;
-	int agp_texture;
-	int multitex;
-	drm_device_t *dev;
-	drm_map_t *map_cache;
-	uint32_t vertex_count;
-} sequence_context_t;
-
-static sequence_context_t hc_sequence;
-
-
 static __inline__ int
 eat_words(const uint32_t **buf, const uint32_t *buf_end, unsigned num_words)
 {
@@ -283,7 +259,7 @@ eat_words(const uint32_t **buf, const uint32_t *buf_end, unsigned num_words)
  */
 
 static __inline__ drm_map_t *
-via_drm_lookup_agp_map (sequence_context_t *seq, unsigned long offset, unsigned long size, 
+via_drm_lookup_agp_map (drm_via_state_t *seq, unsigned long offset, unsigned long size, 
 			drm_device_t *dev)
 {
 	struct list_head *list;
@@ -320,7 +296,7 @@ via_drm_lookup_agp_map (sequence_context_t *seq, unsigned long offset, unsigned
 
 
 static __inline__ int
-finish_current_sequence(sequence_context_t *cur_seq) 
+finish_current_sequence(drm_via_state_t *cur_seq) 
 {
 	switch(cur_seq->unfinished) {
 	case z_address:
@@ -365,7 +341,7 @@ finish_current_sequence(sequence_context_t *cur_seq)
 }
 
 static __inline__ int 
-investigate_hazard( uint32_t cmd, hazard_t hz, sequence_context_t *cur_seq)
+investigate_hazard( uint32_t cmd, hazard_t hz, drm_via_state_t *cur_seq)
 {
 	register uint32_t tmp, *tmp_addr;
 
@@ -518,7 +494,7 @@ investigate_hazard( uint32_t cmd, hazard_t hz, sequence_context_t *cur_seq)
 
 static __inline__ int
 via_check_prim_list(uint32_t const **buffer, const uint32_t *buf_end,
-		    sequence_context_t *cur_seq)
+		    drm_via_state_t *cur_seq)
 {
 	uint32_t a_fire, bcmd , dw_count;
 	int ret = 0;
@@ -546,7 +522,7 @@ via_check_prim_list(uint32_t const **buffer, const uint32_t *buf_end,
 		 * How many dwords per vertex ?
 		 */ 
 		
-		if ((bcmd & (0xF << 11)) == 0) {
+		if (cur_seq->agp && ((bcmd & (0xF << 11)) == 0)) {
 			DRM_ERROR("Illegal B command vertex data for AGP.\n");
 			ret = 1;
 			break;
@@ -563,12 +539,6 @@ via_check_prim_list(uint32_t const **buffer, const uint32_t *buf_end,
 		if (bcmd & (1 << 14)) dw_count++;
 
 		while(buf < buf_end) {
-			if (*buf == HALCYON_HEADER2) {
-				DRM_ERROR("Missing Vertex Fire command or verifier "
-					  "lost sync.\n");
-				ret = 1;
-				break;
-			}
 			if (*buf == a_fire) {
 			        have_fire = 1;
 				buf++;
@@ -576,8 +546,11 @@ via_check_prim_list(uint32_t const **buffer, const uint32_t *buf_end,
 					buf++;
 				break;
 			}
-			if ((*buf & HALCYON_FIREMASK) == HALCYON_FIRECMD) {
-				DRM_ERROR("Stray Vertex Fire command encountered.\n");
+			if ((*buf == HALCYON_HEADER2) || 
+			    ((*buf & HALCYON_FIREMASK) == HALCYON_FIRECMD)) {
+				DRM_ERROR("Missing Vertex Fire command, "
+					  "Stray Vertex Fire command  or verifier "
+					  "lost sync.\n");
 				ret = 1;
 				break;
 			}
@@ -590,6 +563,11 @@ via_check_prim_list(uint32_t const **buffer, const uint32_t *buf_end,
 			ret = 1;
 			break;
 		}
+		if (cur_seq->agp && ((buf - cur_seq->buf_start) & 0x01)) {
+			DRM_ERROR("AGP Primitive list end misaligned.\n");
+			ret = 1;
+			break;
+		}
 	} 
 	*buffer = buf;
 	return ret;
@@ -600,7 +578,8 @@ via_check_prim_list(uint32_t const **buffer, const uint32_t *buf_end,
 
 
 static __inline__ verifier_state_t
-via_check_header2( uint32_t const **buffer, const uint32_t *buf_end )
+via_check_header2( uint32_t const **buffer, const uint32_t *buf_end, 
+		   drm_via_state_t *hc_state)
 {
 	uint32_t cmd;
 	int hz_mode;
@@ -618,7 +597,7 @@ via_check_header2( uint32_t const **buffer, const uint32_t *buf_end )
 
 	switch(cmd) {
 	case HC_ParaType_CmdVdata:
-		if (via_check_prim_list(&buf, buf_end, &hc_sequence )) 
+		if (via_check_prim_list(&buf, buf_end, hc_state )) 
 			return state_error;
 		*buffer = buf;
 		return state_command;
@@ -626,11 +605,11 @@ via_check_header2( uint32_t const **buffer, const uint32_t *buf_end )
 		hz_table = table1;
 		break;
 	case HC_ParaType_Tex:
-		hc_sequence.texture = 0;
+		hc_state->texture = 0;
 		hz_table = table2;
 		break;
 	case (HC_ParaType_Tex | (HC_SubType_Tex1 << 8)):
-		hc_sequence.texture = 1;
+		hc_state->texture = 1;
 		hz_table = table2;
 		break;
 	case (HC_ParaType_Tex | (HC_SubType_TexGeneral << 8)):
@@ -672,19 +651,19 @@ via_check_header2( uint32_t const **buffer, const uint32_t *buf_end )
 	while(buf < buf_end) {
 		cmd = *buf++;
 		if ((hz = hz_table[cmd >> 24])) {
-			if ((hz_mode = investigate_hazard(cmd, hz, &hc_sequence))) {
+			if ((hz_mode = investigate_hazard(cmd, hz, hc_state))) {
 				if (hz_mode == 1) {
 					buf--;
 					break;
 				}
 				return state_error;
 			}
-		} else if (hc_sequence.unfinished && 
-			   finish_current_sequence(&hc_sequence)) {
+		} else if (hc_state->unfinished && 
+			   finish_current_sequence(hc_state)) {
 			return state_error;
 		}
 	}
-	if (hc_sequence.unfinished && finish_current_sequence(&hc_sequence)) {
+	if (hc_state->unfinished && finish_current_sequence(hc_state)) {
 		return state_error;
 	}
 	*buffer = buf;
@@ -831,22 +810,29 @@ via_check_vheader6( uint32_t const **buffer, const uint32_t *buf_end )
 
 
 int 
-via_verify_command_stream(const uint32_t * buf, unsigned int size, drm_device_t *dev)
+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 );
 	verifier_state_t state = state_command;
 	
-	hc_sequence.dev = dev;
-	hc_sequence.unfinished = no_sequence;
-	hc_sequence.map_cache = NULL;
+	
+	hc_state->dev = dev;
+	hc_state->unfinished = no_sequence;
+	hc_state->map_cache = NULL;
+	hc_state->agp = agp;
+	hc_state->buf_start = buf;
 
 	while (buf < buf_end) {
 
 		switch (state) {
 		case state_header2:
-			state = via_check_header2( &buf, buf_end );
+			state = via_check_header2( &buf, buf_end, hc_state );
 			break;
 		case state_header1:
 			state = via_check_header1( &buf, buf_end );
@@ -874,10 +860,15 @@ via_verify_command_stream(const uint32_t * buf, unsigned int size, drm_device_t
 			break;
 		case state_error:
 		default:
+			*hc_state = saved_state;
 			return DRM_ERR(EINVAL);			
 		}
 	}	
-	return (state == state_error) ? DRM_ERR(EINVAL) : 0;
+	if (state == state_error) {
+		*hc_state = saved_state;
+		return DRM_ERR(EINVAL);
+	}
+	return 0;
 }
 
 static void 
@@ -897,7 +888,6 @@ setup_hazard_table(hz_init_t init_table[], hazard_t table[], int size)
 void 
 via_init_command_verifier( void )
 {
-	hc_sequence.texture = 0;
 	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));
diff --git a/shared-core/via_verifier.h b/shared-core/via_verifier.h
new file mode 100644
index 00000000..a8e13592
--- /dev/null
+++ b/shared-core/via_verifier.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2004 The Unichrome Project. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE UNICHROME PROJECT, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Author: Thomas Hellstr�m 2004.
+ */
+
+#ifndef _VIA_VERIFIER_H_
+#define _VIA_VERIFIER_H_
+
+typedef enum{
+	no_sequence = 0, 
+	z_address,
+	dest_address,
+	tex_address
+}drm_via_sequence_t;
+
+
+
+typedef struct{
+	unsigned texture;
+	uint32_t z_addr; 
+	uint32_t d_addr; 
+        uint32_t t_addr[2][10];
+	uint32_t pitch[2][10];
+	uint32_t height[2][10];
+	uint32_t tex_level_lo[2]; 
+	uint32_t tex_level_hi[2];
+	uint32_t tex_palette_size[2];
+	drm_via_sequence_t unfinished;
+	int agp_texture;
+	int multitex;
+	drm_device_t *dev;
+	drm_map_t *map_cache;
+	uint32_t vertex_count;
+	int agp;
+	const uint32_t *buf_start;
+} drm_via_state_t;
+
+extern int via_verify_command_stream(const uint32_t * buf, unsigned int size, 
+				     drm_device_t *dev, int agp);
+
+#endif
-- 
cgit v1.2.3