diff options
Diffstat (limited to 'shared-core/via_dma.c')
| -rw-r--r-- | shared-core/via_dma.c | 74 | 
1 files changed, 42 insertions, 32 deletions
| diff --git a/shared-core/via_dma.c b/shared-core/via_dma.c index ee4a02ab..179636ea 100644 --- a/shared-core/via_dma.c +++ b/shared-core/via_dma.c @@ -26,7 +26,11 @@  	*vb++ = (w2);				\  	dev_priv->dma_low += 8;  -   +#define PCI_BUF_SIZE 1024000 + +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); @@ -203,6 +207,9 @@ int via_dma_init(DRM_IOCTL_ARGS)  	case VIA_CLEANUP_DMA:  		retcode = via_dma_cleanup(dev);  		break; +        case VIA_DMA_INITIALIZED: +	  retcode = (dev_priv->ring.virtual_start != NULL) ? 0: DRM_ERR( EFAULT ); +	        break;  	default:  		retcode = DRM_ERR(EINVAL);  		break; @@ -278,52 +285,55 @@ static int via_parse_pci_cmdbuffer(drm_device_t * dev, const char *buf,  				   unsigned int size)  {  	drm_via_private_t *dev_priv = dev->dev_private; -	uint32_t offset, value;  	const uint32_t *regbuf = (uint32_t *) buf; -	unsigned int i; +	const uint32_t *regend = regbuf + (size >> 2);  	int ret; +	int check_2d_cmd = 1;  	if ((ret = via_check_command_stream(regbuf, size)))  		return ret; -	size >>= 3; -	for (i = 0; i < size; ++i) { -		offset = (*regbuf++ & ~HALCYON_HEADER1) << 2; -		value = *regbuf++; -		VIA_WRITE(offset, value); -	} +	while (regbuf != regend) {	 +		if ( *regbuf == HALCYON_HEADER2 ) { +		   +			regbuf++; +			check_2d_cmd = ( *regbuf != HALCYON_SUB_ADDR0 ); +			VIA_WRITE(HC_REG_TRANS_SET + HC_REG_BASE, *regbuf++); +			 +		} else if ( check_2d_cmd && ((*regbuf & HALCYON_HEADER1MASK) == HALCYON_HEADER1 )) { + +			register uint32_t addr = ( (*regbuf++ ) & ~HALCYON_HEADER1MASK) << 2; +			VIA_WRITE( addr, *regbuf++ ); + +		} else if ( ( *regbuf & HALCYON_FIREMASK ) == HALCYON_FIRECMD ) { + +			VIA_WRITE(HC_REG_TRANS_SPACE + HC_REG_BASE, *regbuf++); +			if ( ( regbuf != regend ) &&  +			     ((*regbuf & HALCYON_FIREMASK) == HALCYON_FIRECMD)) +				regbuf++; +			if (( *regbuf & HALCYON_CMDBMASK ) != HC_ACMD_HCmdB ) +				check_2d_cmd = 1; +		} else { + +			VIA_WRITE(HC_REG_TRANS_SPACE + HC_REG_BASE , *regbuf++); + +		} +	}   	return 0; +  }  static int via_dispatch_pci_cmdbuffer(drm_device_t * dev,  				      drm_via_cmdbuffer_t * cmd)  { -	drm_via_private_t *dev_priv = dev->dev_private; -	char *hugebuf;  	int ret; -	/* -	 * We must be able to parse the buffer all at a time, so as -	 * to return an error on an invalid operation without doing -	 * anything. -	 * Small buffers must, on the other hand be handled fast. -	 */ - -	if (cmd->size > VIA_MAX_PCI_SIZE) { +	if (cmd->size > pci_bufsiz && pci_bufsiz > 0) {  		return DRM_ERR(ENOMEM); -	} else if (cmd->size > VIA_PREALLOCATED_PCI_SIZE) { -		if (NULL == (hugebuf = (char *)kmalloc(cmd->size, GFP_KERNEL))) -			return DRM_ERR(ENOMEM); -		if (DRM_COPY_FROM_USER(hugebuf, cmd->buf, cmd->size)) -			return DRM_ERR(EFAULT); -		ret = via_parse_pci_cmdbuffer(dev, hugebuf, cmd->size); -		kfree(hugebuf); -	} else { -		if (DRM_COPY_FROM_USER(dev_priv->pci_buf, cmd->buf, cmd->size)) -			return DRM_ERR(EFAULT); -		ret = -			via_parse_pci_cmdbuffer(dev, dev_priv->pci_buf, cmd->size); -	} +	}  +	if (DRM_COPY_FROM_USER(pci_buf, cmd->buf, cmd->size)) +		return DRM_ERR(EFAULT); +	ret = via_parse_pci_cmdbuffer(dev, pci_buf, cmd->size);  	return ret;  } | 
