diff options
-rw-r--r-- | linux-core/Makefile | 4 | ||||
-rw-r--r-- | shared-core/via_dma.c | 4 | ||||
-rw-r--r-- | shared-core/via_drv.h | 6 | ||||
-rw-r--r-- | shared-core/via_verifier.c | 104 | ||||
-rw-r--r-- | shared-core/via_verifier.h | 61 |
5 files changed, 116 insertions, 63 deletions
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 |