From cd9ef39c769202f161619ee7a95674371c57cd48 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Thu, 27 Jan 2005 22:48:47 +0000 Subject: Fixed multiple devices DMA bug. Fixed PCI path FIRE command detection --- shared-core/via_dma.c | 32 +++++++++++++++++++------------- shared-core/via_drv.h | 10 ++++++++-- shared-core/via_verifier.c | 8 ++++++++ 3 files changed, 35 insertions(+), 15 deletions(-) (limited to 'shared-core') diff --git a/shared-core/via_dma.c b/shared-core/via_dma.c index 22cbcd28..3edefd76 100644 --- a/shared-core/via_dma.c +++ b/shared-core/via_dma.c @@ -37,7 +37,6 @@ #include "via_drv.h" #include "via_3d_reg.h" -#define PCI_BUF_SIZE 512000 #define CMDBUF_ALIGNMENT_SIZE (0x100) #define CMDBUF_ALIGNMENT_MASK (0xff) @@ -66,10 +65,6 @@ *vb++ = (w2); \ dev_priv->dma_low += 8; - -static char pci_buf[PCI_BUF_SIZE]; -static unsigned long pci_bufsiz = PCI_BUF_SIZE; - static void via_cmdbuf_start(drm_via_private_t * dev_priv); static void via_cmdbuf_pause(drm_via_private_t * dev_priv); static void via_cmdbuf_reset(drm_via_private_t * dev_priv); @@ -266,12 +261,12 @@ static int via_dispatch_cmdbuffer(drm_device_t * dev, drm_via_cmdbuffer_t * cmd) return DRM_ERR(EFAULT); } - if (cmd->size > pci_bufsiz && pci_bufsiz > 0) { + if (cmd->size > VIA_PCI_BUF_SIZE) { return DRM_ERR(ENOMEM); } - if (DRM_COPY_FROM_USER(pci_buf, cmd->buf, cmd->size)) + if (DRM_COPY_FROM_USER(dev_priv->pci_buf, cmd->buf, cmd->size)) return DRM_ERR(EFAULT); /* @@ -281,7 +276,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, 1))) { + if ((ret = via_verify_command_stream((uint32_t *)dev_priv->pci_buf, cmd->size, dev, 1))) { return ret; } @@ -290,7 +285,7 @@ static int via_dispatch_cmdbuffer(drm_device_t * dev, drm_via_cmdbuffer_t * cmd) return DRM_ERR(EAGAIN); } - memcpy(vb, pci_buf, cmd->size); + memcpy(vb, dev_priv->pci_buf, cmd->size); dev_priv->dma_low += cmd->size; via_cmdbuf_pause(dev_priv); @@ -344,12 +339,17 @@ static int via_parse_pci_cmdbuffer(drm_device_t * dev, const char *buf, drm_via_private_t *dev_priv = dev->dev_private; const uint32_t *regbuf = (const uint32_t *) buf; const uint32_t *regend = regbuf + (size >> 2); + const uint32_t *next_fire; + int fire_count = 0; int ret; int check_2d_cmd = 1; + + if ((ret = via_verify_command_stream(regbuf, size, dev, 0))) return ret; + next_fire = dev_priv->fire_offsets[fire_count]; while (regbuf != regend) { if ( *regbuf == HALCYON_HEADER2 ) { @@ -362,9 +362,14 @@ static int via_parse_pci_cmdbuffer(drm_device_t * dev, const char *buf, register uint32_t addr = ( (*regbuf++ ) & ~HALCYON_HEADER1MASK) << 2; VIA_WRITE( addr, *regbuf++ ); - } else if ( ( *regbuf & HALCYON_FIREMASK ) == HALCYON_FIRECMD ) { + } else if ( (fire_count < dev_priv->num_fire_offsets) && + (regbuf == next_fire) && + (( *regbuf & HALCYON_FIREMASK ) == HALCYON_FIRECMD) ) { + + next_fire = dev_priv->fire_offsets[++fire_count]; VIA_WRITE(HC_REG_TRANS_SPACE + HC_REG_BASE, *regbuf++); + if ( ( regbuf != regend ) && ((*regbuf & HALCYON_FIREMASK) == HALCYON_FIRECMD)) regbuf++; @@ -383,14 +388,15 @@ static int via_parse_pci_cmdbuffer(drm_device_t * dev, const char *buf, static int via_dispatch_pci_cmdbuffer(drm_device_t * dev, drm_via_cmdbuffer_t * cmd) { + drm_via_private_t *dev_priv = dev->dev_private; int ret; - if (cmd->size > pci_bufsiz && pci_bufsiz > 0) { + if (cmd->size > VIA_PCI_BUF_SIZE) { return DRM_ERR(ENOMEM); } - if (DRM_COPY_FROM_USER(pci_buf, cmd->buf, cmd->size)) + if (DRM_COPY_FROM_USER(dev_priv->pci_buf, cmd->buf, cmd->size)) return DRM_ERR(EFAULT); - ret = via_parse_pci_cmdbuffer(dev, pci_buf, cmd->size); + ret = via_parse_pci_cmdbuffer(dev, dev_priv->pci_buf, cmd->size); return ret; } diff --git a/shared-core/via_drv.h b/shared-core/via_drv.h index f8824301..ac90da5a 100644 --- a/shared-core/via_drv.h +++ b/shared-core/via_drv.h @@ -28,14 +28,17 @@ #define DRIVER_NAME "via" #define DRIVER_DESC "VIA Unichrome" -#define DRIVER_DATE "20050107" +#define DRIVER_DATE "20050127" #define DRIVER_MAJOR 2 #define DRIVER_MINOR 4 -#define DRIVER_PATCHLEVEL 3 +#define DRIVER_PATCHLEVEL 4 #include "via_verifier.h" +#define VIA_PCI_BUF_SIZE 120000 +#define VIA_FIRE_BUF_SIZE 2048 + typedef struct drm_via_ring_buffer { drm_map_t map; char *virtual_start; @@ -60,6 +63,9 @@ typedef struct drm_via_private { int last_vblank_valid; unsigned usec_per_vblank; drm_via_state_t hc_state; + char pci_buf[VIA_PCI_BUF_SIZE]; + const uint32_t *fire_offsets[VIA_FIRE_BUF_SIZE]; + uint32_t num_fire_offsets; } drm_via_private_t; /* VIA MMIO register access */ diff --git a/shared-core/via_verifier.c b/shared-core/via_verifier.c index ad32141e..6b08f5d8 100644 --- a/shared-core/via_verifier.c +++ b/shared-core/via_verifier.c @@ -496,6 +496,7 @@ static __inline__ int 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; int ret = 0; int have_fire; @@ -540,6 +541,12 @@ via_check_prim_list(uint32_t const **buffer, const uint32_t *buf_end, while(buf < buf_end) { if (*buf == a_fire) { + 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; buf++; if (buf < buf_end && *buf == a_fire) @@ -827,6 +834,7 @@ via_verify_command_stream(const uint32_t * buf, unsigned int size, drm_device_t hc_state->map_cache = NULL; hc_state->agp = agp; hc_state->buf_start = buf; + dev_priv->num_fire_offsets = 0; while (buf < buf_end) { -- cgit v1.2.3