summaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
authorTodd Poynor <tpoynor@mvista.com>2005-07-12 03:34:39 +0100
committerThomas Gleixner <tglx@mtd.linutronix.de>2005-07-13 00:58:44 +0200
commita98a5d04f400ad112e59cadd739dbabf89417e60 (patch)
tree5eeb7f45c0090de40c7523e2b9dfd5e86b22169e /drivers/char
parent751382dd5cb2702368d281a50b55c2d6c4e8fbfc (diff)
parent7ac3db59fd4410405ce55e2a25c397aec440d8da (diff)
downloadblackbird-op-linux-a98a5d04f400ad112e59cadd739dbabf89417e60.tar.gz
blackbird-op-linux-a98a5d04f400ad112e59cadd739dbabf89417e60.zip
Merge with rsync://fileserver/linux
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/Makefile2
-rw-r--r--drivers/char/drm/Kconfig7
-rw-r--r--drivers/char/drm/Makefile5
-rw-r--r--drivers/char/drm/ati_pcigart.c2
-rw-r--r--drivers/char/drm/drm.h2
-rw-r--r--drivers/char/drm/drmP.h30
-rw-r--r--drivers/char/drm/drm_auth.c4
-rw-r--r--drivers/char/drm/drm_bufs.c12
-rw-r--r--drivers/char/drm/drm_context.c4
-rw-r--r--drivers/char/drm/drm_drv.c9
-rw-r--r--drivers/char/drm/drm_fops.c14
-rw-r--r--drivers/char/drm/drm_irq.c2
-rw-r--r--drivers/char/drm/drm_lock.c12
-rw-r--r--drivers/char/drm/drm_memory.c13
-rw-r--r--drivers/char/drm/drm_pciids.h7
-rw-r--r--drivers/char/drm/drm_proc.c2
-rw-r--r--drivers/char/drm/drm_stub.c92
-rw-r--r--drivers/char/drm/drm_vm.c10
-rw-r--r--drivers/char/drm/i810_dma.c24
-rw-r--r--drivers/char/drm/i810_drv.h1
-rw-r--r--drivers/char/drm/i830_dma.c20
-rw-r--r--drivers/char/drm/i830_drv.c2
-rw-r--r--drivers/char/drm/i830_drv.h2
-rw-r--r--drivers/char/drm/i830_irq.c5
-rw-r--r--drivers/char/drm/i915_dma.c60
-rw-r--r--drivers/char/drm/i915_drv.c5
-rw-r--r--drivers/char/drm/i915_drv.h14
-rw-r--r--drivers/char/drm/i915_ioc32.c221
-rw-r--r--drivers/char/drm/i915_irq.c4
-rw-r--r--drivers/char/drm/mga_drv.c3
-rw-r--r--drivers/char/drm/mga_drv.h2
-rw-r--r--drivers/char/drm/mga_ioc32.c167
-rw-r--r--drivers/char/drm/r128_drv.c3
-rw-r--r--drivers/char/drm/r128_drv.h3
-rw-r--r--drivers/char/drm/r128_ioc32.c219
-rw-r--r--drivers/char/drm/r128_state.c2
-rw-r--r--drivers/char/drm/via_3d_reg.h1651
-rw-r--r--drivers/char/drm/via_dma.c741
-rw-r--r--drivers/char/drm/via_drm.h243
-rw-r--r--drivers/char/drm/via_drv.c126
-rw-r--r--drivers/char/drm/via_drv.h118
-rw-r--r--drivers/char/drm/via_ds.c280
-rw-r--r--drivers/char/drm/via_ds.h104
-rw-r--r--drivers/char/drm/via_irq.c339
-rw-r--r--drivers/char/drm/via_map.c110
-rw-r--r--drivers/char/drm/via_mm.c358
-rw-r--r--drivers/char/drm/via_mm.h40
-rw-r--r--drivers/char/drm/via_verifier.c1061
-rw-r--r--drivers/char/drm/via_verifier.h61
-rw-r--r--drivers/char/drm/via_video.c97
-rw-r--r--drivers/char/hvc_console.c429
-rw-r--r--drivers/char/hvc_vio.c152
-rw-r--r--drivers/char/hvsi.c8
-rw-r--r--drivers/char/n_tty.c33
-rw-r--r--drivers/char/pcmcia/synclink_cs.c7
-rw-r--r--drivers/char/random.c2
-rw-r--r--drivers/char/sysrq.c2
57 files changed, 6527 insertions, 421 deletions
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 1aff819f3832..08f69287ea36 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -40,7 +40,7 @@ obj-$(CONFIG_N_HDLC) += n_hdlc.o
obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o
obj-$(CONFIG_SX) += sx.o generic_serial.o
obj-$(CONFIG_RIO) += rio/ generic_serial.o
-obj-$(CONFIG_HVC_CONSOLE) += hvc_console.o hvsi.o
+obj-$(CONFIG_HVC_CONSOLE) += hvc_console.o hvc_vio.o hvsi.o
obj-$(CONFIG_RAW_DRIVER) += raw.o
obj-$(CONFIG_SGI_SNSC) += snsc.o snsc_event.o
obj-$(CONFIG_MMTIMER) += mmtimer.o
diff --git a/drivers/char/drm/Kconfig b/drivers/char/drm/Kconfig
index c2b12eab67c9..123417e43040 100644
--- a/drivers/char/drm/Kconfig
+++ b/drivers/char/drm/Kconfig
@@ -96,3 +96,10 @@ config DRM_SIS
chipset. If M is selected the module will be called sis. AGP
support is required for this driver to work.
+config DRM_VIA
+ tristate "Via unichrome video cards"
+ depends on DRM
+ help
+ Choose this option if you have a Via unichrome or compatible video
+ chipset. If M is selected the module will be called via.
+
diff --git a/drivers/char/drm/Makefile b/drivers/char/drm/Makefile
index 7444dec40b94..ddd941045b1f 100644
--- a/drivers/char/drm/Makefile
+++ b/drivers/char/drm/Makefile
@@ -18,10 +18,14 @@ i915-objs := i915_drv.o i915_dma.o i915_irq.o i915_mem.o
radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o radeon_irq.o
ffb-objs := ffb_drv.o ffb_context.o
sis-objs := sis_drv.o sis_ds.o sis_mm.o
+via-objs := via_irq.o via_drv.o via_ds.o via_map.o via_mm.o via_dma.o via_verifier.o via_video.o
ifeq ($(CONFIG_COMPAT),y)
drm-objs += drm_ioc32.o
radeon-objs += radeon_ioc32.o
+mga-objs += mga_ioc32.o
+r128-objs += r128_ioc32.o
+i915-objs += i915_ioc32.o
endif
obj-$(CONFIG_DRM) += drm.o
@@ -35,4 +39,5 @@ obj-$(CONFIG_DRM_I830) += i830.o
obj-$(CONFIG_DRM_I915) += i915.o
obj-$(CONFIG_DRM_FFB) += ffb.o
obj-$(CONFIG_DRM_SIS) += sis.o
+obj-$(CONFIG_DRM_VIA) +=via.o
diff --git a/drivers/char/drm/ati_pcigart.c b/drivers/char/drm/ati_pcigart.c
index fdca1876ecd5..0aec5ef481b8 100644
--- a/drivers/char/drm/ati_pcigart.c
+++ b/drivers/char/drm/ati_pcigart.c
@@ -52,7 +52,7 @@
# define ATI_MAX_PCIGART_PAGES 8192 /**< 32 MB aperture, 4K pages */
# define ATI_PCIGART_PAGE_SIZE 4096 /**< PCI GART page size */
-unsigned long drm_ati_alloc_pcigart_table( void )
+static unsigned long drm_ati_alloc_pcigart_table( void )
{
unsigned long address;
struct page *page;
diff --git a/drivers/char/drm/drm.h b/drivers/char/drm/drm.h
index 587305282ea8..e8371dd87fbc 100644
--- a/drivers/char/drm/drm.h
+++ b/drivers/char/drm/drm.h
@@ -38,7 +38,9 @@
#define _DRM_H_
#if defined(__linux__)
+#if defined(__KERNEL__)
#include <linux/config.h>
+#endif
#include <asm/ioctl.h> /* For _IO* macros */
#define DRM_IOCTL_NR(n) _IOC_NR(n)
#define DRM_IOC_VOID _IOC_NONE
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h
index b04ddf12a0ff..5df09cc8c6db 100644
--- a/drivers/char/drm/drmP.h
+++ b/drivers/char/drm/drmP.h
@@ -774,8 +774,6 @@ extern int drm_cpu_valid( void );
/* Driver support (drm_drv.h) */
extern int drm_init(struct drm_driver *driver);
extern void drm_exit(struct drm_driver *driver);
-extern int drm_version(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
extern int drm_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern long drm_compat_ioctl(struct file *filp,
@@ -785,28 +783,19 @@ extern int drm_takedown(drm_device_t * dev);
/* Device support (drm_fops.h) */
extern int drm_open(struct inode *inode, struct file *filp);
extern int drm_stub_open(struct inode *inode, struct file *filp);
-extern int drm_open_helper(struct inode *inode, struct file *filp,
- drm_device_t *dev);
extern int drm_flush(struct file *filp);
extern int drm_fasync(int fd, struct file *filp, int on);
extern int drm_release(struct inode *inode, struct file *filp);
/* Mapping support (drm_vm.h) */
-extern void drm_vm_open(struct vm_area_struct *vma);
-extern void drm_vm_close(struct vm_area_struct *vma);
-extern void drm_vm_shm_close(struct vm_area_struct *vma);
-extern int drm_mmap_dma(struct file *filp,
- struct vm_area_struct *vma);
extern int drm_mmap(struct file *filp, struct vm_area_struct *vma);
extern unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait);
-extern ssize_t drm_read(struct file *filp, char __user *buf, size_t count, loff_t *off);
/* Memory management support (drm_memory.h) */
#include "drm_memory.h"
extern void drm_mem_init(void);
extern int drm_mem_info(char *buf, char **start, off_t offset,
int request, int *eof, void *data);
-extern void *drm_calloc(size_t nmemb, size_t size, int area);
extern void *drm_realloc(void *oldpt, size_t oldsize, size_t size,
int area);
extern unsigned long drm_alloc_pages(int order, int area);
@@ -854,9 +843,6 @@ extern int drm_newctx( struct inode *inode, struct file *filp,
extern int drm_rmctx( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg );
-extern int drm_context_switch(drm_device_t *dev, int old, int new);
-extern int drm_context_switch_complete(drm_device_t *dev, int new);
-
extern int drm_ctxbitmap_init( drm_device_t *dev );
extern void drm_ctxbitmap_cleanup( drm_device_t *dev );
extern void drm_ctxbitmap_free( drm_device_t *dev, int ctx_handle );
@@ -874,9 +860,6 @@ extern int drm_rmdraw(struct inode *inode, struct file *filp,
/* Authentication IOCTL support (drm_auth.h) */
-extern int drm_add_magic(drm_device_t *dev, drm_file_t *priv,
- drm_magic_t magic);
-extern int drm_remove_magic(drm_device_t *dev, drm_magic_t magic);
extern int drm_getmagic(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern int drm_authmagic(struct inode *inode, struct file *filp,
@@ -893,13 +876,9 @@ extern int drm_unlock(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern int drm_lock_take(__volatile__ unsigned int *lock,
unsigned int context);
-extern int drm_lock_transfer(drm_device_t *dev,
- __volatile__ unsigned int *lock,
- unsigned int context);
extern int drm_lock_free(drm_device_t *dev,
__volatile__ unsigned int *lock,
unsigned int context);
-extern int drm_notifier(void *priv);
/* Buffer management support (drm_bufs.h) */
extern int drm_order( unsigned long size );
@@ -927,7 +906,6 @@ extern void drm_core_reclaim_buffers(drm_device_t *dev, struct file *filp);
/* IRQ support (drm_irq.h) */
extern int drm_control( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg );
-extern int drm_irq_install( drm_device_t *dev );
extern int drm_irq_uninstall( drm_device_t *dev );
extern irqreturn_t drm_irq_handler( DRM_IRQ_ARGS );
extern void drm_driver_irq_preinstall( drm_device_t *dev );
@@ -967,7 +945,6 @@ extern int drm_agp_unbind_memory(DRM_AGP_MEM *handle);
extern int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
struct drm_driver *driver);
extern int drm_put_dev(drm_device_t * dev);
-extern int drm_get_head(drm_device_t * dev, drm_head_t *head);
extern int drm_put_head(drm_head_t * head);
extern unsigned int drm_debug;
extern unsigned int drm_cards_limit;
@@ -1064,9 +1041,16 @@ static __inline__ void drm_free(void *pt, size_t size, int area)
{
kfree(pt);
}
+
+/** Wrapper around kcalloc() */
+static __inline__ void *drm_calloc(size_t nmemb, size_t size, int area)
+{
+ return kcalloc(nmemb, size, GFP_KERNEL);
+}
#else
extern void *drm_alloc(size_t size, int area);
extern void drm_free(void *pt, size_t size, int area);
+extern void *drm_calloc(size_t nmemb, size_t size, int area);
#endif
/*@}*/
diff --git a/drivers/char/drm/drm_auth.c b/drivers/char/drm/drm_auth.c
index b428761c4e91..dd140bca8f71 100644
--- a/drivers/char/drm/drm_auth.c
+++ b/drivers/char/drm/drm_auth.c
@@ -87,7 +87,7 @@ static drm_file_t *drm_find_file(drm_device_t *dev, drm_magic_t magic)
* associated the magic number hash key in drm_device::magiclist, while holding
* the drm_device::struct_sem lock.
*/
-int drm_add_magic(drm_device_t *dev, drm_file_t *priv, drm_magic_t magic)
+static int drm_add_magic(drm_device_t *dev, drm_file_t *priv, drm_magic_t magic)
{
int hash;
drm_magic_entry_t *entry;
@@ -124,7 +124,7 @@ int drm_add_magic(drm_device_t *dev, drm_file_t *priv, drm_magic_t magic)
* Searches and unlinks the entry in drm_device::magiclist with the magic
* number hash key, while holding the drm_device::struct_sem lock.
*/
-int drm_remove_magic(drm_device_t *dev, drm_magic_t magic)
+static int drm_remove_magic(drm_device_t *dev, drm_magic_t magic)
{
drm_magic_entry_t *prev = NULL;
drm_magic_entry_t *pt;
diff --git a/drivers/char/drm/drm_bufs.c b/drivers/char/drm/drm_bufs.c
index 3407380b865a..4c6191d231b8 100644
--- a/drivers/char/drm/drm_bufs.c
+++ b/drivers/char/drm/drm_bufs.c
@@ -356,8 +356,8 @@ static void drm_cleanup_buf_error(drm_device_t *dev, drm_buf_entry_t *entry)
* reallocates the buffer list of the same size order to accommodate the new
* buffers.
*/
-int drm_addbufs_agp( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg )
+static int drm_addbufs_agp( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg )
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
@@ -521,8 +521,8 @@ int drm_addbufs_agp( struct inode *inode, struct file *filp,
}
#endif /* __OS_HAS_AGP */
-int drm_addbufs_pci( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg )
+static int drm_addbufs_pci( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg )
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
@@ -751,8 +751,8 @@ int drm_addbufs_pci( struct inode *inode, struct file *filp,
}
-int drm_addbufs_sg( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg )
+static int drm_addbufs_sg( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg )
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
diff --git a/drivers/char/drm/drm_context.c b/drivers/char/drm/drm_context.c
index fdf661f234ed..a7cfabd1ca2e 100644
--- a/drivers/char/drm/drm_context.c
+++ b/drivers/char/drm/drm_context.c
@@ -84,7 +84,7 @@ failed:
* drm_device::context_sareas to accommodate the new entry while holding the
* drm_device::struct_sem lock.
*/
-int drm_ctxbitmap_next( drm_device_t *dev )
+static int drm_ctxbitmap_next( drm_device_t *dev )
{
int bit;
@@ -326,7 +326,7 @@ int drm_context_switch( drm_device_t *dev, int old, int new )
* hardware lock is held, clears the drm_device::context_flag and wakes up
* drm_device::context_wait.
*/
-int drm_context_switch_complete( drm_device_t *dev, int new )
+static int drm_context_switch_complete( drm_device_t *dev, int new )
{
dev->last_context = new; /* PRE/POST: This is the _only_ writer. */
dev->last_switch = jiffies;
diff --git a/drivers/char/drm/drm_drv.c b/drivers/char/drm/drm_drv.c
index 1e37ed0c6b8d..3333c250c4d9 100644
--- a/drivers/char/drm/drm_drv.c
+++ b/drivers/char/drm/drm_drv.c
@@ -51,8 +51,11 @@
#include "drmP.h"
#include "drm_core.h"
+static int drm_version(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+
/** Ioctl table */
-drm_ioctl_desc_t drm_ioctls[] = {
+static drm_ioctl_desc_t drm_ioctls[] = {
[DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = { drm_version, 0, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = { drm_getunique, 0, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] = { drm_getmagic, 0, 0 },
@@ -447,8 +450,8 @@ module_exit( drm_core_exit );
*
* Fills in the version information in \p arg.
*/
-int drm_version( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg )
+static int drm_version( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg )
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
diff --git a/drivers/char/drm/drm_fops.c b/drivers/char/drm/drm_fops.c
index 906794247aeb..10e64fde8d78 100644
--- a/drivers/char/drm/drm_fops.c
+++ b/drivers/char/drm/drm_fops.c
@@ -37,6 +37,8 @@
#include "drmP.h"
#include <linux/poll.h>
+static int drm_open_helper(struct inode *inode, struct file *filp, drm_device_t *dev);
+
static int drm_setup( drm_device_t *dev )
{
int i;
@@ -251,7 +253,7 @@ int drm_release( struct inode *inode, struct file *filp )
}
}
- if (drm_core_check_feature(dev, DRIVER_HAVE_DMA))
+ if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) && !dev->driver->release)
{
dev->driver->reclaim_buffers(dev, filp);
}
@@ -259,7 +261,7 @@ int drm_release( struct inode *inode, struct file *filp )
drm_fasync( -1, filp, 0 );
down( &dev->ctxlist_sem );
- if ( !list_empty( &dev->ctxlist->head ) ) {
+ if ( dev->ctxlist && (!list_empty(&dev->ctxlist->head))) {
drm_ctx_list_t *pos, *n;
list_for_each_entry_safe( pos, n, &dev->ctxlist->head, head ) {
@@ -341,7 +343,7 @@ EXPORT_SYMBOL(drm_release);
* Creates and initializes a drm_file structure for the file private data in \p
* filp and add it into the double linked list in \p dev.
*/
-int drm_open_helper(struct inode *inode, struct file *filp, drm_device_t *dev)
+static int drm_open_helper(struct inode *inode, struct file *filp, drm_device_t *dev)
{
int minor = iminor(inode);
drm_file_t *priv;
@@ -443,9 +445,3 @@ unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait)
}
EXPORT_SYMBOL(drm_poll);
-
-/** No-op. */
-ssize_t drm_read(struct file *filp, char __user *buf, size_t count, loff_t *off)
-{
- return 0;
-}
diff --git a/drivers/char/drm/drm_irq.c b/drivers/char/drm/drm_irq.c
index 2e236ebcf27b..cdd4aecd25e2 100644
--- a/drivers/char/drm/drm_irq.c
+++ b/drivers/char/drm/drm_irq.c
@@ -89,7 +89,7 @@ int drm_irq_by_busid(struct inode *inode, struct file *filp,
* \c drm_driver_irq_preinstall() and \c drm_driver_irq_postinstall() functions
* before and after the installation.
*/
-int drm_irq_install( drm_device_t *dev )
+static int drm_irq_install( drm_device_t *dev )
{
int ret;
unsigned long sh_flags=0;
diff --git a/drivers/char/drm/drm_lock.c b/drivers/char/drm/drm_lock.c
index d0d6fc661625..4702d863bcc6 100644
--- a/drivers/char/drm/drm_lock.c
+++ b/drivers/char/drm/drm_lock.c
@@ -35,6 +35,11 @@
#include "drmP.h"
+static int drm_lock_transfer(drm_device_t *dev,
+ __volatile__ unsigned int *lock,
+ unsigned int context);
+static int drm_notifier(void *priv);
+
/**
* Lock ioctl.
*
@@ -225,8 +230,9 @@ int drm_lock_take(__volatile__ unsigned int *lock, unsigned int context)
* Resets the lock file pointer.
* Marks the lock as held by the given context, via the \p cmpxchg instruction.
*/
-int drm_lock_transfer(drm_device_t *dev,
- __volatile__ unsigned int *lock, unsigned int context)
+static int drm_lock_transfer(drm_device_t *dev,
+ __volatile__ unsigned int *lock,
+ unsigned int context)
{
unsigned int old, new, prev;
@@ -282,7 +288,7 @@ int drm_lock_free(drm_device_t *dev,
* \return one if the signal should be delivered normally, or zero if the
* signal should be blocked.
*/
-int drm_notifier(void *priv)
+static int drm_notifier(void *priv)
{
drm_sigdata_t *s = (drm_sigdata_t *)priv;
unsigned int old, new, prev;
diff --git a/drivers/char/drm/drm_memory.c b/drivers/char/drm/drm_memory.c
index 7f53f756c052..ace3d42f4407 100644
--- a/drivers/char/drm/drm_memory.c
+++ b/drivers/char/drm/drm_memory.c
@@ -65,19 +65,6 @@ int drm_mem_info(char *buf, char **start, off_t offset,
return 0;
}
-/** Wrapper around kmalloc() */
-void *drm_calloc(size_t nmemb, size_t size, int area)
-{
- void *addr;
-
- addr = kmalloc(size * nmemb, GFP_KERNEL);
- if (addr != NULL)
- memset((void *)addr, 0, size * nmemb);
-
- return addr;
-}
-EXPORT_SYMBOL(drm_calloc);
-
/** Wrapper around kmalloc() and kfree() */
void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area)
{
diff --git a/drivers/char/drm/drm_pciids.h b/drivers/char/drm/drm_pciids.h
index 11c6950158b3..70ca4fa55c9d 100644
--- a/drivers/char/drm/drm_pciids.h
+++ b/drivers/char/drm/drm_pciids.h
@@ -223,3 +223,10 @@
{0x8086, 0x2772, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
{0, 0, 0}
+#define viadrv_PCI_IDS \
+ {0x1106, 0x3022, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+ {0x1106, 0x3122, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+ {0x1106, 0x7205, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+ {0x1106, 0x7204, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+ {0, 0, 0}
+
diff --git a/drivers/char/drm/drm_proc.c b/drivers/char/drm/drm_proc.c
index 6e06e8c6a516..4774087d2e9e 100644
--- a/drivers/char/drm/drm_proc.c
+++ b/drivers/char/drm/drm_proc.c
@@ -57,7 +57,7 @@ static int drm_vma_info(char *buf, char **start, off_t offset,
/**
* Proc file list.
*/
-struct drm_proc_list {
+static struct drm_proc_list {
const char *name; /**< file name */
int (*f)(char *, char **, off_t, int, int *, void *); /**< proc callback*/
} drm_proc_list[] = {
diff --git a/drivers/char/drm/drm_stub.c b/drivers/char/drm/drm_stub.c
index 8ccbdef7bb3e..48829a1a086a 100644
--- a/drivers/char/drm/drm_stub.c
+++ b/drivers/char/drm/drm_stub.c
@@ -157,52 +157,6 @@ int drm_stub_open(struct inode *inode, struct file *filp)
return err;
}
-
-/**
- * Register.
- *
- * \param pdev - PCI device structure
- * \param ent entry from the PCI ID table with device type flags
- * \return zero on success or a negative number on failure.
- *
- * Attempt to gets inter module "drm" information. If we are first
- * then register the character device and inter module information.
- * Try and register, if we fail to register, backout previous work.
- */
-int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
- struct drm_driver *driver)
-{
- drm_device_t *dev;
- int ret;
-
- DRM_DEBUG("\n");
-
- dev = drm_calloc(1, sizeof(*dev), DRM_MEM_STUB);
- if (!dev)
- return -ENOMEM;
-
- pci_enable_device(pdev);
-
- if ((ret = drm_fill_in_dev(dev, pdev, ent, driver))) {
- printk(KERN_ERR "DRM: Fill_in_dev failed.\n");
- goto err_g1;
- }
- if ((ret = drm_get_head(dev, &dev->primary)))
- goto err_g1;
-
- /* postinit is a required function to display the signon banner */
- /* drivers add secondary heads here if needed */
- if ((ret = dev->driver->postinit(dev, ent->driver_data)))
- goto err_g1;
-
- return 0;
-
-err_g1:
- drm_free(dev, sizeof(*dev), DRM_MEM_STUB);
- return ret;
-}
-EXPORT_SYMBOL(drm_get_dev);
-
/**
* Get a secondary minor number.
*
@@ -214,7 +168,7 @@ EXPORT_SYMBOL(drm_get_dev);
* create the proc init entry via proc_init(). This routines assigns
* minor numbers to secondary heads of multi-headed cards
*/
-int drm_get_head(drm_device_t *dev, drm_head_t *head)
+static int drm_get_head(drm_device_t *dev, drm_head_t *head)
{
drm_head_t **heads = drm_heads;
int ret;
@@ -262,6 +216,50 @@ err_g1:
return ret;
}
+/**
+ * Register.
+ *
+ * \param pdev - PCI device structure
+ * \param ent entry from the PCI ID table with device type flags
+ * \return zero on success or a negative number on failure.
+ *
+ * Attempt to gets inter module "drm" information. If we are first
+ * then register the character device and inter module information.
+ * Try and register, if we fail to register, backout previous work.
+ */
+int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
+ struct drm_driver *driver)
+{
+ drm_device_t *dev;
+ int ret;
+
+ DRM_DEBUG("\n");
+
+ dev = drm_calloc(1, sizeof(*dev), DRM_MEM_STUB);
+ if (!dev)
+ return -ENOMEM;
+
+ pci_enable_device(pdev);
+
+ if ((ret = drm_fill_in_dev(dev, pdev, ent, driver))) {
+ printk(KERN_ERR "DRM: Fill_in_dev failed.\n");
+ goto err_g1;
+ }
+ if ((ret = drm_get_head(dev, &dev->primary)))
+ goto err_g1;
+
+ /* postinit is a required function to display the signon banner */
+ /* drivers add secondary heads here if needed */
+ if ((ret = dev->driver->postinit(dev, ent->driver_data)))
+ goto err_g1;
+
+ return 0;
+
+err_g1:
+ drm_free(dev, sizeof(*dev), DRM_MEM_STUB);
+ return ret;
+}
+EXPORT_SYMBOL(drm_get_dev);
/**
* Put a device minor number.
diff --git a/drivers/char/drm/drm_vm.c b/drivers/char/drm/drm_vm.c
index fc72f30f312b..621220f3f372 100644
--- a/drivers/char/drm/drm_vm.c
+++ b/drivers/char/drm/drm_vm.c
@@ -38,6 +38,8 @@
#include <linux/efi.h>
#endif
+static void drm_vm_open(struct vm_area_struct *vma);
+static void drm_vm_close(struct vm_area_struct *vma);
/**
* \c nopage method for AGP virtual memory.
@@ -163,7 +165,7 @@ static __inline__ struct page *drm_do_vm_shm_nopage(struct vm_area_struct *vma,
* Deletes map information if we are the last
* person to close a mapping and it's not in the global maplist.
*/
-void drm_vm_shm_close(struct vm_area_struct *vma)
+static void drm_vm_shm_close(struct vm_area_struct *vma)
{
drm_file_t *priv = vma->vm_file->private_data;
drm_device_t *dev = priv->head->dev;
@@ -399,7 +401,7 @@ static struct vm_operations_struct drm_vm_sg_ops = {
* Create a new drm_vma_entry structure as the \p vma private data entry and
* add it to drm_device::vmalist.
*/
-void drm_vm_open(struct vm_area_struct *vma)
+static void drm_vm_open(struct vm_area_struct *vma)
{
drm_file_t *priv = vma->vm_file->private_data;
drm_device_t *dev = priv->head->dev;
@@ -428,7 +430,7 @@ void drm_vm_open(struct vm_area_struct *vma)
* Search the \p vma private data entry in drm_device::vmalist, unlink it, and
* free it.
*/
-void drm_vm_close(struct vm_area_struct *vma)
+static void drm_vm_close(struct vm_area_struct *vma)
{
drm_file_t *priv = vma->vm_file->private_data;
drm_device_t *dev = priv->head->dev;
@@ -463,7 +465,7 @@ void drm_vm_close(struct vm_area_struct *vma)
* Sets the virtual memory area operations structure to vm_dma_ops, the file
* pointer, and calls vm_open().
*/
-int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma)
+static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev;
diff --git a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c
index 24857cc6c23b..18e0b7622893 100644
--- a/drivers/char/drm/i810_dma.c
+++ b/drivers/char/drm/i810_dma.c
@@ -90,16 +90,7 @@ static int i810_freelist_put(drm_device_t *dev, drm_buf_t *buf)
return 0;
}
-static struct file_operations i810_buffer_fops = {
- .open = drm_open,
- .flush = drm_flush,
- .release = drm_release,
- .ioctl = drm_ioctl,
- .mmap = i810_mmap_buffers,
- .fasync = drm_fasync,
-};
-
-int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
+static int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev;
@@ -126,6 +117,15 @@ int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
return 0;
}
+static struct file_operations i810_buffer_fops = {
+ .open = drm_open,
+ .flush = drm_flush,
+ .release = drm_release,
+ .ioctl = drm_ioctl,
+ .mmap = i810_mmap_buffers,
+ .fasync = drm_fasync,
+};
+
static int i810_map_buffer(drm_buf_t *buf, struct file *filp)
{
drm_file_t *priv = filp->private_data;
@@ -1003,8 +1003,8 @@ void i810_reclaim_buffers(drm_device_t *dev, struct file *filp)
}
}
-int i810_flush_ioctl(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+static int i810_flush_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
diff --git a/drivers/char/drm/i810_drv.h b/drivers/char/drm/i810_drv.h
index fa23ca454e57..1b40538d1725 100644
--- a/drivers/char/drm/i810_drv.h
+++ b/drivers/char/drm/i810_drv.h
@@ -115,7 +115,6 @@ typedef struct drm_i810_private {
/* i810_dma.c */
extern void i810_reclaim_buffers(drm_device_t *dev, struct file *filp);
-extern int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma);
extern int i810_driver_dma_quiescent(drm_device_t *dev);
extern void i810_driver_release(drm_device_t *dev, struct file *filp);
diff --git a/drivers/char/drm/i830_dma.c b/drivers/char/drm/i830_dma.c
index 98adccf8e434..dc7733035864 100644
--- a/drivers/char/drm/i830_dma.c
+++ b/drivers/char/drm/i830_dma.c
@@ -92,16 +92,7 @@ static int i830_freelist_put(drm_device_t *dev, drm_buf_t *buf)
return 0;
}
-static struct file_operations i830_buffer_fops = {
- .open = drm_open,
- .flush = drm_flush,
- .release = drm_release,
- .ioctl = drm_ioctl,
- .mmap = i830_mmap_buffers,
- .fasync = drm_fasync,
-};
-
-int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
+static int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev;
@@ -128,6 +119,15 @@ int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
return 0;
}
+static struct file_operations i830_buffer_fops = {
+ .open = drm_open,
+ .flush = drm_flush,
+ .release = drm_release,
+ .ioctl = drm_ioctl,
+ .mmap = i830_mmap_buffers,
+ .fasync = drm_fasync,
+};
+
static int i830_map_buffer(drm_buf_t *buf, struct file *filp)
{
drm_file_t *priv = filp->private_data;
diff --git a/drivers/char/drm/i830_drv.c b/drivers/char/drm/i830_drv.c
index aa80ad6a5ee0..bc36be76b8b2 100644
--- a/drivers/char/drm/i830_drv.c
+++ b/drivers/char/drm/i830_drv.c
@@ -40,7 +40,7 @@
#include "drm_pciids.h"
-int postinit( struct drm_device *dev, unsigned long flags )
+static int postinit( struct drm_device *dev, unsigned long flags )
{
dev->counters += 4;
dev->types[6] = _DRM_STAT_IRQ;
diff --git a/drivers/char/drm/i830_drv.h b/drivers/char/drm/i830_drv.h
index d4b2d093d6ab..df7746131dea 100644
--- a/drivers/char/drm/i830_drv.h
+++ b/drivers/char/drm/i830_drv.h
@@ -123,8 +123,6 @@ typedef struct drm_i830_private {
/* i830_dma.c */
extern void i830_reclaim_buffers(drm_device_t *dev, struct file *filp);
-extern int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma);
-
/* i830_irq.c */
extern int i830_irq_emit( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg );
diff --git a/drivers/char/drm/i830_irq.c b/drivers/char/drm/i830_irq.c
index 6d7729ffe2dc..a5923e5d0a77 100644
--- a/drivers/char/drm/i830_irq.c
+++ b/drivers/char/drm/i830_irq.c
@@ -54,8 +54,7 @@ irqreturn_t i830_driver_irq_handler( DRM_IRQ_ARGS )
return IRQ_HANDLED;
}
-
-int i830_emit_irq(drm_device_t *dev)
+static int i830_emit_irq(drm_device_t *dev)
{
drm_i830_private_t *dev_priv = dev->dev_private;
RING_LOCALS;
@@ -73,7 +72,7 @@ int i830_emit_irq(drm_device_t *dev)
}
-int i830_wait_irq(drm_device_t *dev, int irq_nr)
+static int i830_wait_irq(drm_device_t *dev, int irq_nr)
{
drm_i830_private_t *dev_priv =
(drm_i830_private_t *)dev->dev_private;
diff --git a/drivers/char/drm/i915_dma.c b/drivers/char/drm/i915_dma.c
index b5903f9f1423..acf9e52a9507 100644
--- a/drivers/char/drm/i915_dma.c
+++ b/drivers/char/drm/i915_dma.c
@@ -32,23 +32,6 @@
#include "i915_drm.h"
#include "i915_drv.h"
-drm_ioctl_desc_t i915_ioctls[] = {
- [DRM_IOCTL_NR(DRM_I915_INIT)] = {i915_dma_init, 1, 1},
- [DRM_IOCTL_NR(DRM_I915_FLUSH)] = {i915_flush_ioctl, 1, 0},
- [DRM_IOCTL_NR(DRM_I915_FLIP)] = {i915_flip_bufs, 1, 0},
- [DRM_IOCTL_NR(DRM_I915_BATCHBUFFER)] = {i915_batchbuffer, 1, 0},
- [DRM_IOCTL_NR(DRM_I915_IRQ_EMIT)] = {i915_irq_emit, 1, 0},
- [DRM_IOCTL_NR(DRM_I915_IRQ_WAIT)] = {i915_irq_wait, 1, 0},
- [DRM_IOCTL_NR(DRM_I915_GETPARAM)] = {i915_getparam, 1, 0},
- [DRM_IOCTL_NR(DRM_I915_SETPARAM)] = {i915_setparam, 1, 1},
- [DRM_IOCTL_NR(DRM_I915_ALLOC)] = {i915_mem_alloc, 1, 0},
- [DRM_IOCTL_NR(DRM_I915_FREE)] = {i915_mem_free, 1, 0},
- [DRM_IOCTL_NR(DRM_I915_INIT_HEAP)] = {i915_mem_init_heap, 1, 1},
- [DRM_IOCTL_NR(DRM_I915_CMDBUFFER)] = {i915_cmdbuffer, 1, 0}
-};
-
-int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
-
/* Really want an OS-independent resettable timer. Would like to have
* this loop run for (eg) 3 sec, but have the timer reset every time
* the head pointer changes, so that EBUSY only happens if the ring
@@ -95,7 +78,7 @@ void i915_kernel_lost_context(drm_device_t * dev)
dev_priv->sarea_priv->perf_boxes |= I915_BOX_RING_EMPTY;
}
-int i915_dma_cleanup(drm_device_t * dev)
+static int i915_dma_cleanup(drm_device_t * dev)
{
/* Make sure interrupts are disabled here because the uninstall ioctl
* may not have been called from userspace and after dev_private
@@ -247,7 +230,7 @@ static int i915_resume(drm_device_t * dev)
return 0;
}
-int i915_dma_init(DRM_IOCTL_ARGS)
+static int i915_dma_init(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_i915_private_t *dev_priv;
@@ -558,7 +541,7 @@ static int i915_quiescent(drm_device_t * dev)
return i915_wait_ring(dev, dev_priv->ring.Size - 8, __FUNCTION__);
}
-int i915_flush_ioctl(DRM_IOCTL_ARGS)
+static int i915_flush_ioctl(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
@@ -567,7 +550,7 @@ int i915_flush_ioctl(DRM_IOCTL_ARGS)
return i915_quiescent(dev);
}
-int i915_batchbuffer(DRM_IOCTL_ARGS)
+static int i915_batchbuffer(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
@@ -601,7 +584,7 @@ int i915_batchbuffer(DRM_IOCTL_ARGS)
return ret;
}
-int i915_cmdbuffer(DRM_IOCTL_ARGS)
+static int i915_cmdbuffer(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
@@ -637,18 +620,7 @@ int i915_cmdbuffer(DRM_IOCTL_ARGS)
return 0;
}
-int i915_do_cleanup_pageflip(drm_device_t * dev)
-{
- drm_i915_private_t *dev_priv = dev->dev_private;
-
- DRM_DEBUG("%s\n", __FUNCTION__);
- if (dev_priv->current_page != 0)
- i915_dispatch_flip(dev);
-
- return 0;
-}
-
-int i915_flip_bufs(DRM_IOCTL_ARGS)
+static int i915_flip_bufs(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
@@ -659,7 +631,7 @@ int i915_flip_bufs(DRM_IOCTL_ARGS)
return i915_dispatch_flip(dev);
}
-int i915_getparam(DRM_IOCTL_ARGS)
+static int i915_getparam(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_i915_private_t *dev_priv = dev->dev_private;
@@ -694,7 +666,7 @@ int i915_getparam(DRM_IOCTL_ARGS)
return 0;
}
-int i915_setparam(DRM_IOCTL_ARGS)
+static int i915_setparam(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_i915_private_t *dev_priv = dev->dev_private;
@@ -743,3 +715,19 @@ void i915_driver_prerelease(drm_device_t *dev, DRMFILE filp)
}
}
+drm_ioctl_desc_t i915_ioctls[] = {
+ [DRM_IOCTL_NR(DRM_I915_INIT)] = {i915_dma_init, 1, 1},
+ [DRM_IOCTL_NR(DRM_I915_FLUSH)] = {i915_flush_ioctl, 1, 0},
+ [DRM_IOCTL_NR(DRM_I915_FLIP)] = {i915_flip_bufs, 1, 0},
+ [DRM_IOCTL_NR(DRM_I915_BATCHBUFFER)] = {i915_batchbuffer, 1, 0},
+ [DRM_IOCTL_NR(DRM_I915_IRQ_EMIT)] = {i915_irq_emit, 1, 0},
+ [DRM_IOCTL_NR(DRM_I915_IRQ_WAIT)] = {i915_irq_wait, 1, 0},
+ [DRM_IOCTL_NR(DRM_I915_GETPARAM)] = {i915_getparam, 1, 0},
+ [DRM_IOCTL_NR(DRM_I915_SETPARAM)] = {i915_setparam, 1, 1},
+ [DRM_IOCTL_NR(DRM_I915_ALLOC)] = {i915_mem_alloc, 1, 0},
+ [DRM_IOCTL_NR(DRM_I915_FREE)] = {i915_mem_free, 1, 0},
+ [DRM_IOCTL_NR(DRM_I915_INIT_HEAP)] = {i915_mem_init_heap, 1, 1},
+ [DRM_IOCTL_NR(DRM_I915_CMDBUFFER)] = {i915_cmdbuffer, 1, 0}
+};
+
+int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
diff --git a/drivers/char/drm/i915_drv.c b/drivers/char/drm/i915_drv.c
index e6a9e1d1d283..1f59d3fc79bc 100644
--- a/drivers/char/drm/i915_drv.c
+++ b/drivers/char/drm/i915_drv.c
@@ -34,7 +34,7 @@
#include "drm_pciids.h"
-int postinit( struct drm_device *dev, unsigned long flags )
+static int postinit( struct drm_device *dev, unsigned long flags )
{
dev->counters += 4;
dev->types[6] = _DRM_STAT_IRQ;
@@ -97,6 +97,9 @@ static struct drm_driver driver = {
.mmap = drm_mmap,
.poll = drm_poll,
.fasync = drm_fasync,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = i915_compat_ioctl,
+#endif
},
.pci_driver = {
.name = DRIVER_NAME,
diff --git a/drivers/char/drm/i915_drv.h b/drivers/char/drm/i915_drv.h
index fa940d64b85d..9c37d2367dd5 100644
--- a/drivers/char/drm/i915_drv.h
+++ b/drivers/char/drm/i915_drv.h
@@ -99,14 +99,6 @@ typedef struct drm_i915_private {
} drm_i915_private_t;
/* i915_dma.c */
-extern int i915_dma_init(DRM_IOCTL_ARGS);
-extern int i915_dma_cleanup(drm_device_t * dev);
-extern int i915_flush_ioctl(DRM_IOCTL_ARGS);
-extern int i915_batchbuffer(DRM_IOCTL_ARGS);
-extern int i915_flip_bufs(DRM_IOCTL_ARGS);
-extern int i915_getparam(DRM_IOCTL_ARGS);
-extern int i915_setparam(DRM_IOCTL_ARGS);
-extern int i915_cmdbuffer(DRM_IOCTL_ARGS);
extern void i915_kernel_lost_context(drm_device_t * dev);
extern void i915_driver_pretakedown(drm_device_t *dev);
extern void i915_driver_prerelease(drm_device_t *dev, DRMFILE filp);
@@ -114,8 +106,6 @@ extern void i915_driver_prerelease(drm_device_t *dev, DRMFILE filp);
/* i915_irq.c */
extern int i915_irq_emit(DRM_IOCTL_ARGS);
extern int i915_irq_wait(DRM_IOCTL_ARGS);
-extern int i915_wait_irq(drm_device_t * dev, int irq_nr);
-extern int i915_emit_irq(drm_device_t * dev);
extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS);
extern void i915_driver_irq_preinstall(drm_device_t *dev);
@@ -130,6 +120,10 @@ extern void i915_mem_takedown(struct mem_block **heap);
extern void i915_mem_release(drm_device_t * dev,
DRMFILE filp, struct mem_block *heap);
+extern long i915_compat_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long arg);
+
+
#define I915_READ(reg) DRM_READ32(dev_priv->mmio_map, reg)
#define I915_WRITE(reg,val) DRM_WRITE32(dev_priv->mmio_map, reg, val)
#define I915_READ16(reg) DRM_READ16(dev_priv->mmio_map, reg)
diff --git a/drivers/char/drm/i915_ioc32.c b/drivers/char/drm/i915_ioc32.c
new file mode 100644
index 000000000000..fe009e1b3a3f
--- /dev/null
+++ b/drivers/char/drm/i915_ioc32.c
@@ -0,0 +1,221 @@
+/**
+ * \file i915_ioc32.c
+ *
+ * 32-bit ioctl compatibility routines for the i915 DRM.
+ *
+ * \author Alan Hourihane <alanh@fairlite.demon.co.uk>
+ *
+ *
+ * Copyright (C) Paul Mackerras 2005
+ * Copyright (C) Alan Hourihane 2005
+ * 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, sublicense,
+ * 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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR 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.
+ */
+#include <linux/compat.h>
+#include <linux/ioctl32.h>
+
+#include "drmP.h"
+#include "drm.h"
+#include "i915_drm.h"
+
+typedef struct _drm_i915_batchbuffer32 {
+ int start; /* agp offset */
+ int used; /* nr bytes in use */
+ int DR1; /* hw flags for GFX_OP_DRAWRECT_INFO */
+ int DR4; /* window origin for GFX_OP_DRAWRECT_INFO */
+ int num_cliprects; /* mulitpass with multiple cliprects? */
+ u32 cliprects; /* pointer to userspace cliprects */
+} drm_i915_batchbuffer32_t;
+
+static int compat_i915_batchbuffer(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_i915_batchbuffer32_t batchbuffer32;
+ drm_i915_batchbuffer_t __user *batchbuffer;
+
+ if (copy_from_user(&batchbuffer32, (void __user *)arg, sizeof(batchbuffer32)))
+ return -EFAULT;
+
+ batchbuffer = compat_alloc_user_space(sizeof(*batchbuffer));
+ if (!access_ok(VERIFY_WRITE, batchbuffer, sizeof(*batchbuffer))
+ || __put_user(batchbuffer32.start, &batchbuffer->start)
+ || __put_user(batchbuffer32.used, &batchbuffer->used)
+ || __put_user(batchbuffer32.DR1, &batchbuffer->DR1)
+ || __put_user(batchbuffer32.DR4, &batchbuffer->DR4)
+ || __put_user(batchbuffer32.num_cliprects, &batchbuffer->num_cliprects)
+ || __put_user((int __user *)(unsigned long)batchbuffer32.cliprects,
+ &batchbuffer->cliprects))
+ return -EFAULT;
+
+ return drm_ioctl(file->f_dentry->d_inode, file,
+ DRM_IOCTL_I915_BATCHBUFFER, (unsigned long) batchbuffer);
+}
+
+typedef struct _drm_i915_cmdbuffer32 {
+ u32 buf; /* pointer to userspace command buffer */
+ int sz; /* nr bytes in buf */
+ int DR1; /* hw flags for GFX_OP_DRAWRECT_INFO */
+ int DR4; /* window origin for GFX_OP_DRAWRECT_INFO */
+ int num_cliprects; /* mulitpass with multiple cliprects? */
+ u32 cliprects; /* pointer to userspace cliprects */
+} drm_i915_cmdbuffer32_t;
+
+static int compat_i915_cmdbuffer(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_i915_cmdbuffer32_t cmdbuffer32;
+ drm_i915_cmdbuffer_t __user *cmdbuffer;
+
+ if (copy_from_user(&cmdbuffer32, (void __user *)arg, sizeof(cmdbuffer32)))
+ return -EFAULT;
+
+ cmdbuffer = compat_alloc_user_space(sizeof(*cmdbuffer));
+ if (!access_ok(VERIFY_WRITE, cmdbuffer, sizeof(*cmdbuffer))
+ || __put_user((int __user *)(unsigned long)cmdbuffer32.buf,
+ &cmdbuffer->buf)
+ || __put_user(cmdbuffer32.sz, &cmdbuffer->sz)
+ || __put_user(cmdbuffer32.DR1, &cmdbuffer->DR1)
+ || __put_user(cmdbuffer32.DR4, &cmdbuffer->DR4)
+ || __put_user(cmdbuffer32.num_cliprects, &cmdbuffer->num_cliprects)
+ || __put_user((int __user *)(unsigned long)cmdbuffer32.cliprects,
+ &cmdbuffer->cliprects))
+ return -EFAULT;
+
+ return drm_ioctl(file->f_dentry->d_inode, file,
+ DRM_IOCTL_I915_CMDBUFFER, (unsigned long) cmdbuffer);
+}
+
+typedef struct drm_i915_irq_emit32 {
+ u32 irq_seq;
+} drm_i915_irq_emit32_t;
+
+static int compat_i915_irq_emit(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_i915_irq_emit32_t req32;
+ drm_i915_irq_emit_t __user *request;
+
+ if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
+ return -EFAULT;
+
+ request = compat_alloc_user_space(sizeof(*request));
+ if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
+ || __put_user((int __user *)(unsigned long)req32.irq_seq,
+ &request->irq_seq))
+ return -EFAULT;
+
+ return drm_ioctl(file->f_dentry->d_inode, file,
+ DRM_IOCTL_I915_IRQ_EMIT, (unsigned long) request);
+}
+typedef struct drm_i915_getparam32 {
+ int param;
+ u32 value;
+} drm_i915_getparam32_t;
+
+static int compat_i915_getparam(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_i915_getparam32_t req32;
+ drm_i915_getparam_t __user *request;
+
+ if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
+ return -EFAULT;
+
+ request = compat_alloc_user_space(sizeof(*request));
+ if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
+ || __put_user(req32.param, &request->param)
+ || __put_user((void __user *)(unsigned long)req32.value,
+ &request->value))
+ return -EFAULT;
+
+ return drm_ioctl(file->f_dentry->d_inode, file,
+ DRM_IOCTL_I915_GETPARAM, (unsigned long) request);
+}
+
+typedef struct drm_i915_mem_alloc32 {
+ int region;
+ int alignment;
+ int size;
+ u32 region_offset; /* offset from start of fb or agp */
+} drm_i915_mem_alloc32_t;
+
+static int compat_i915_alloc(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_i915_mem_alloc32_t req32;
+ drm_i915_mem_alloc_t __user *request;
+
+ if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
+ return -EFAULT;
+
+ request = compat_alloc_user_space(sizeof(*request));
+ if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
+ || __put_user(req32.region, &request->region)
+ || __put_user(req32.alignment, &request->alignment)
+ || __put_user(req32.size, &request->size)
+ || __put_user((void __user *)(unsigned long)req32.region_offset,
+ &request->region_offset))
+ return -EFAULT;
+
+ return drm_ioctl(file->f_dentry->d_inode, file,
+ DRM_IOCTL_I915_ALLOC, (unsigned long) request);
+}
+
+
+drm_ioctl_compat_t *i915_compat_ioctls[] = {
+ [DRM_I915_BATCHBUFFER] = compat_i915_batchbuffer,
+ [DRM_I915_CMDBUFFER] = compat_i915_cmdbuffer,
+ [DRM_I915_GETPARAM] = compat_i915_getparam,
+ [DRM_I915_IRQ_EMIT] = compat_i915_irq_emit,
+ [DRM_I915_ALLOC] = compat_i915_alloc
+};
+
+/**
+ * Called whenever a 32-bit process running under a 64-bit kernel
+ * performs an ioctl on /dev/dri/card<n>.
+ *
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument.
+ * \return zero on success or negative number on failure.
+ */
+long i915_compat_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ unsigned int nr = DRM_IOCTL_NR(cmd);
+ drm_ioctl_compat_t *fn = NULL;
+ int ret;
+
+ if (nr < DRM_COMMAND_BASE)
+ return drm_compat_ioctl(filp, cmd, arg);
+
+ if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(i915_compat_ioctls))
+ fn = i915_compat_ioctls[nr - DRM_COMMAND_BASE];
+
+ lock_kernel(); /* XXX for now */
+ if (fn != NULL)
+ ret = (*fn)(filp, cmd, arg);
+ else
+ ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
+ unlock_kernel();
+
+ return ret;
+}
diff --git a/drivers/char/drm/i915_irq.c b/drivers/char/drm/i915_irq.c
index a101cc9cfd7e..4fa448ee846b 100644
--- a/drivers/char/drm/i915_irq.c
+++ b/drivers/char/drm/i915_irq.c
@@ -56,7 +56,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
return IRQ_HANDLED;
}
-int i915_emit_irq(drm_device_t * dev)
+static int i915_emit_irq(drm_device_t * dev)
{
drm_i915_private_t *dev_priv = dev->dev_private;
u32 ret;
@@ -76,7 +76,7 @@ int i915_emit_irq(drm_device_t * dev)
return ret;
}
-int i915_wait_irq(drm_device_t * dev, int irq_nr)
+static int i915_wait_irq(drm_device_t * dev, int irq_nr)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
int ret = 0;
diff --git a/drivers/char/drm/mga_drv.c b/drivers/char/drm/mga_drv.c
index 22dab3e9d92a..844cca9cb29d 100644
--- a/drivers/char/drm/mga_drv.c
+++ b/drivers/char/drm/mga_drv.c
@@ -101,6 +101,9 @@ static struct drm_driver driver = {
.mmap = drm_mmap,
.poll = drm_poll,
.fasync = drm_fasync,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = mga_compat_ioctl,
+#endif
},
.pci_driver = {
.name = DRIVER_NAME,
diff --git a/drivers/char/drm/mga_drv.h b/drivers/char/drm/mga_drv.h
index 1d84a1eb34db..9412e2816eb7 100644
--- a/drivers/char/drm/mga_drv.h
+++ b/drivers/char/drm/mga_drv.h
@@ -137,6 +137,8 @@ extern irqreturn_t mga_driver_irq_handler( DRM_IRQ_ARGS );
extern void mga_driver_irq_preinstall( drm_device_t *dev );
extern void mga_driver_irq_postinstall( drm_device_t *dev );
extern void mga_driver_irq_uninstall( drm_device_t *dev );
+extern long mga_compat_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long arg);
#define mga_flush_write_combine() DRM_WRITEMEMORYBARRIER()
diff --git a/drivers/char/drm/mga_ioc32.c b/drivers/char/drm/mga_ioc32.c
new file mode 100644
index 000000000000..bc745cfa2095
--- /dev/null
+++ b/drivers/char/drm/mga_ioc32.c
@@ -0,0 +1,167 @@
+/**
+ * \file mga_ioc32.c
+ *
+ * 32-bit ioctl compatibility routines for the MGA DRM.
+ *
+ * \author Dave Airlie <airlied@linux.ie> with code from patches by Egbert Eich
+ *
+ *
+ * Copyright (C) Paul Mackerras 2005
+ * Copyright (C) Egbert Eich 2003,2004
+ * Copyright (C) Dave Airlie 2005
+ * 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, sublicense,
+ * 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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR 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.
+ */
+#include <linux/compat.h>
+#include <linux/ioctl32.h>
+
+#include "drmP.h"
+#include "drm.h"
+#include "mga_drm.h"
+
+typedef struct drm32_mga_init {
+ int func;
+ u32 sarea_priv_offset;
+ int chipset;
+ int sgram;
+ unsigned int maccess;
+ unsigned int fb_cpp;
+ unsigned int front_offset, front_pitch;
+ unsigned int back_offset, back_pitch;
+ unsigned int depth_cpp;
+ unsigned int depth_offset, depth_pitch;
+ unsigned int texture_offset[MGA_NR_TEX_HEAPS];
+ unsigned int texture_size[MGA_NR_TEX_HEAPS];
+ u32 fb_offset;
+ u32 mmio_offset;
+ u32 status_offset;
+ u32 warp_offset;
+ u32 primary_offset;
+ u32 buffers_offset;
+} drm_mga_init32_t;
+
+static int compat_mga_init(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_mga_init32_t init32;
+ drm_mga_init_t __user *init;
+ int err = 0, i;
+
+ if (copy_from_user(&init32, (void __user *)arg, sizeof(init32)))
+ return -EFAULT;
+
+ init = compat_alloc_user_space(sizeof(*init));
+ if (!access_ok(VERIFY_WRITE, init, sizeof(*init))
+ || __put_user(init32.func, &init->func)
+ || __put_user(init32.sarea_priv_offset, &init->sarea_priv_offset)
+ || __put_user(init32.chipset, &init->chipset)
+ || __put_user(init32.sgram, &init->sgram)
+ || __put_user(init32.maccess, &init->maccess)
+ || __put_user(init32.fb_cpp, &init->fb_cpp)
+ || __put_user(init32.front_offset, &init->front_offset)
+ || __put_user(init32.front_pitch, &init->front_pitch)
+ || __put_user(init32.back_offset, &init->back_offset)
+ || __put_user(init32.back_pitch, &init->back_pitch)
+ || __put_user(init32.depth_cpp, &init->depth_cpp)
+ || __put_user(init32.depth_offset, &init->depth_offset)
+ || __put_user(init32.depth_pitch, &init->depth_pitch)
+ || __put_user(init32.fb_offset, &init->fb_offset)
+ || __put_user(init32.mmio_offset, &init->mmio_offset)
+ || __put_user(init32.status_offset, &init->status_offset)
+ || __put_user(init32.warp_offset, &init->warp_offset)
+ || __put_user(init32.primary_offset, &init->primary_offset)
+ || __put_user(init32.buffers_offset, &init->buffers_offset))
+ return -EFAULT;
+
+ for (i=0; i<MGA_NR_TEX_HEAPS; i++)
+ {
+ err |= __put_user(init32.texture_offset[i], &init->texture_offset[i]);
+ err |= __put_user(init32.texture_size[i], &init->texture_size[i]);
+ }
+ if (err)
+ return -EFAULT;
+
+ return drm_ioctl(file->f_dentry->d_inode, file,
+ DRM_IOCTL_MGA_INIT, (unsigned long) init);
+}
+
+
+typedef struct drm_mga_getparam32 {
+ int param;
+ u32 value;
+} drm_mga_getparam32_t;
+
+
+static int compat_mga_getparam(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_mga_getparam32_t getparam32;
+ drm_mga_getparam_t __user *getparam;
+
+ if (copy_from_user(&getparam32, (void __user *)arg, sizeof(getparam32)))
+ return -EFAULT;
+
+ getparam = compat_alloc_user_space(sizeof(*getparam));
+ if (!access_ok(VERIFY_WRITE, getparam, sizeof(*getparam))
+ || __put_user(getparam32.param, &getparam->param)
+ || __put_user((void __user *)(unsigned long)getparam32.value, &getparam->value))
+ return -EFAULT;
+
+ return drm_ioctl(file->f_dentry->d_inode, file,
+ DRM_IOCTL_MGA_GETPARAM, (unsigned long)getparam);
+}
+
+drm_ioctl_compat_t *mga_compat_ioctls[] = {
+ [DRM_MGA_INIT] = compat_mga_init,
+ [DRM_MGA_GETPARAM] = compat_mga_getparam,
+};
+
+/**
+ * Called whenever a 32-bit process running under a 64-bit kernel
+ * performs an ioctl on /dev/dri/card<n>.
+ *
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument.
+ * \return zero on success or negative number on failure.
+ */
+long mga_compat_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ unsigned int nr = DRM_IOCTL_NR(cmd);
+ drm_ioctl_compat_t *fn = NULL;
+ int ret;
+
+ if (nr < DRM_COMMAND_BASE)
+ return drm_compat_ioctl(filp, cmd, arg);
+
+ if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(mga_compat_ioctls))
+ fn = mga_compat_ioctls[nr - DRM_COMMAND_BASE];
+
+ lock_kernel(); /* XXX for now */
+ if (fn != NULL)
+ ret = (*fn)(filp, cmd, arg);
+ else
+ ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
+ unlock_kernel();
+
+ return ret;
+}
diff --git a/drivers/char/drm/r128_drv.c b/drivers/char/drm/r128_drv.c
index ced63810237b..bc446da1b210 100644
--- a/drivers/char/drm/r128_drv.c
+++ b/drivers/char/drm/r128_drv.c
@@ -96,6 +96,9 @@ static struct drm_driver driver = {
.mmap = drm_mmap,
.poll = drm_poll,
.fasync = drm_fasync,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = r128_compat_ioctl,
+#endif
},
.pci_driver = {
.name = DRIVER_NAME,
diff --git a/drivers/char/drm/r128_drv.h b/drivers/char/drm/r128_drv.h
index cf1aa5df459e..0fb687c9505e 100644
--- a/drivers/char/drm/r128_drv.h
+++ b/drivers/char/drm/r128_drv.h
@@ -156,6 +156,9 @@ extern void r128_driver_irq_uninstall( drm_device_t *dev );
extern void r128_driver_pretakedown(drm_device_t *dev);
extern void r128_driver_prerelease(drm_device_t *dev, DRMFILE filp);
+extern long r128_compat_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long arg);
+
/* Register definitions, register access macros and drmAddMap constants
* for Rage 128 kernel driver.
*/
diff --git a/drivers/char/drm/r128_ioc32.c b/drivers/char/drm/r128_ioc32.c
new file mode 100644
index 000000000000..60598ef9475a
--- /dev/null
+++ b/drivers/char/drm/r128_ioc32.c
@@ -0,0 +1,219 @@
+/**
+ * \file r128_ioc32.c
+ *
+ * 32-bit ioctl compatibility routines for the R128 DRM.
+ *
+ * \author Dave Airlie <airlied@linux.ie> with code from patches by Egbert Eich
+ *
+ * Copyright (C) Paul Mackerras 2005
+ * Copyright (C) Egbert Eich 2003,2004
+ * Copyright (C) Dave Airlie 2005
+ * 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, sublicense,
+ * 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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR 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.
+ */
+#include <linux/compat.h>
+#include <linux/ioctl32.h>
+
+#include "drmP.h"
+#include "drm.h"
+#include "r128_drm.h"
+
+typedef struct drm_r128_init32 {
+ int func;
+ unsigned int sarea_priv_offset;
+ int is_pci;
+ int cce_mode;
+ int cce_secure;
+ int ring_size;
+ int usec_timeout;
+
+ unsigned int fb_bpp;
+ unsigned int front_offset, front_pitch;
+ unsigned int back_offset, back_pitch;
+ unsigned int depth_bpp;
+ unsigned int depth_offset, depth_pitch;
+ unsigned int span_offset;
+
+ unsigned int fb_offset;
+ unsigned int mmio_offset;
+ unsigned int ring_offset;
+ unsigned int ring_rptr_offset;
+ unsigned int buffers_offset;
+ unsigned int agp_textures_offset;
+} drm_r128_init32_t;
+
+static int compat_r128_init(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_r128_init32_t init32;
+ drm_r128_init_t __user *init;
+
+ if (copy_from_user(&init32, (void __user *)arg, sizeof(init32)))
+ return -EFAULT;
+
+ init = compat_alloc_user_space(sizeof(*init));
+ if (!access_ok(VERIFY_WRITE, init, sizeof(*init))
+ || __put_user(init32.func, &init->func)
+ || __put_user(init32.sarea_priv_offset, &init->sarea_priv_offset)
+ || __put_user(init32.is_pci, &init->is_pci)
+ || __put_user(init32.cce_mode, &init->cce_mode)
+ || __put_user(init32.cce_secure, &init->cce_secure)
+ || __put_user(init32.ring_size, &init->ring_size)
+ || __put_user(init32.usec_timeout, &init->usec_timeout)
+ || __put_user(init32.fb_bpp, &init->fb_bpp)
+ || __put_user(init32.front_offset, &init->front_offset)
+ || __put_user(init32.front_pitch, &init->front_pitch)
+ || __put_user(init32.back_offset, &init->back_offset)
+ || __put_user(init32.back_pitch, &init->back_pitch)
+ || __put_user(init32.depth_bpp, &init->depth_bpp)
+ || __put_user(init32.depth_offset, &init->depth_offset)
+ || __put_user(init32.depth_pitch, &init->depth_pitch)
+ || __put_user(init32.span_offset, &init->span_offset)
+ || __put_user(init32.fb_offset, &init->fb_offset)
+ || __put_user(init32.mmio_offset, &init->mmio_offset)
+ || __put_user(init32.ring_offset, &init->ring_offset)
+ || __put_user(init32.ring_rptr_offset, &init->ring_rptr_offset)
+ || __put_user(init32.buffers_offset, &init->buffers_offset)
+ || __put_user(init32.agp_textures_offset, &init->agp_textures_offset))
+ return -EFAULT;
+
+ return drm_ioctl(file->f_dentry->d_inode, file,
+ DRM_IOCTL_R128_INIT, (unsigned long)init);
+}
+
+
+typedef struct drm_r128_depth32 {
+ int func;
+ int n;
+ u32 x;
+ u32 y;
+ u32 buffer;
+ u32 mask;
+} drm_r128_depth32_t;
+
+static int compat_r128_depth(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_r128_depth32_t depth32;
+ drm_r128_depth_t __user *depth;
+
+ if (copy_from_user(&depth32, (void __user *)arg, sizeof(depth32)))
+ return -EFAULT;
+
+ depth = compat_alloc_user_space(sizeof(*depth));
+ if (!access_ok(VERIFY_WRITE, depth, sizeof(*depth))
+ || __put_user(depth32.func, &depth->func)
+ || __put_user(depth32.n, &depth->n)
+ || __put_user((int __user *)(unsigned long)depth32.x, &depth->x)
+ || __put_user((int __user *)(unsigned long)depth32.y, &depth->y)
+ || __put_user((unsigned int __user *)(unsigned long)depth32.buffer, &depth->buffer)
+ || __put_user((unsigned char __user *)(unsigned long)depth32.mask, &depth->mask))
+ return -EFAULT;
+
+ return drm_ioctl(file->f_dentry->d_inode, file,
+ DRM_IOCTL_R128_DEPTH, (unsigned long)depth);
+
+}
+
+typedef struct drm_r128_stipple32 {
+ u32 mask;
+} drm_r128_stipple32_t;
+
+static int compat_r128_stipple(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_r128_stipple32_t stipple32;
+ drm_r128_stipple_t __user *stipple;
+
+ if (copy_from_user(&stipple32, (void __user *)arg, sizeof(stipple32)))
+ return -EFAULT;
+
+ stipple = compat_alloc_user_space(sizeof(*stipple));
+ if (!access_ok(VERIFY_WRITE, stipple, sizeof(*stipple))
+ || __put_user((unsigned int __user *)(unsigned long)stipple32.mask, &stipple->mask))
+ return -EFAULT;
+
+ return drm_ioctl(file->f_dentry->d_inode, file,
+ DRM_IOCTL_R128_STIPPLE, (unsigned long)stipple);
+}
+
+typedef struct drm_r128_getparam32 {
+ int param;
+ u32 value;
+} drm_r128_getparam32_t;
+
+static int compat_r128_getparam(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_r128_getparam32_t getparam32;
+ drm_r128_getparam_t __user *getparam;
+
+ if (copy_from_user(&getparam32, (void __user *)arg, sizeof(getparam32)))
+ return -EFAULT;
+
+ getparam = compat_alloc_user_space(sizeof(*getparam));
+ if (!access_ok(VERIFY_WRITE, getparam, sizeof(*getparam))
+ || __put_user(getparam32.param, &getparam->param)
+ || __put_user((void __user *)(unsigned long)getparam32.value, &getparam->value))
+ return -EFAULT;
+
+ return drm_ioctl(file->f_dentry->d_inode, file,
+ DRM_IOCTL_R128_GETPARAM, (unsigned long)getparam);
+}
+
+drm_ioctl_compat_t *r128_compat_ioctls[] = {
+ [DRM_R128_INIT] = compat_r128_init,
+ [DRM_R128_DEPTH] = compat_r128_depth,
+ [DRM_R128_STIPPLE] = compat_r128_stipple,
+ [DRM_R128_GETPARAM] = compat_r128_getparam,
+};
+
+/**
+ * Called whenever a 32-bit process running under a 64-bit kernel
+ * performs an ioctl on /dev/dri/card<n>.
+ *
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument.
+ * \return zero on success or negative number on failure.
+ */
+long r128_compat_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ unsigned int nr = DRM_IOCTL_NR(cmd);
+ drm_ioctl_compat_t *fn = NULL;
+ int ret;
+
+ if (nr < DRM_COMMAND_BASE)
+ return drm_compat_ioctl(filp, cmd, arg);
+
+ if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(r128_compat_ioctls))
+ fn = r128_compat_ioctls[nr - DRM_COMMAND_BASE];
+
+ lock_kernel(); /* XXX for now */
+ if (fn != NULL)
+ ret = (*fn)(filp, cmd, arg);
+ else
+ ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
+ unlock_kernel();
+
+ return ret;
+}
diff --git a/drivers/char/drm/r128_state.c b/drivers/char/drm/r128_state.c
index 53af69162829..426a71c049d9 100644
--- a/drivers/char/drm/r128_state.c
+++ b/drivers/char/drm/r128_state.c
@@ -1307,7 +1307,7 @@ static int r128_do_init_pageflip( drm_device_t *dev )
return 0;
}
-int r128_do_cleanup_pageflip( drm_device_t *dev )
+static int r128_do_cleanup_pageflip( drm_device_t *dev )
{
drm_r128_private_t *dev_priv = dev->dev_private;
DRM_DEBUG( "\n" );
diff --git a/drivers/char/drm/via_3d_reg.h b/drivers/char/drm/via_3d_reg.h
new file mode 100644
index 000000000000..cf61bb514db1
--- /dev/null
+++ b/drivers/char/drm/via_3d_reg.h
@@ -0,0 +1,1651 @@
+/*
+ * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2003 S3 Graphics, Inc. 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
+ * VIA, S3 GRAPHICS, 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.
+ */
+
+#ifndef VIA_3D_REG_H
+#define VIA_3D_REG_H
+#define HC_REG_BASE 0x0400
+
+#define HC_REG_TRANS_SPACE 0x0040
+
+#define HC_ParaN_MASK 0xffffffff
+#define HC_Para_MASK 0x00ffffff
+#define HC_SubA_MASK 0xff000000
+#define HC_SubA_SHIFT 24
+/* Transmission Setting
+ */
+#define HC_REG_TRANS_SET 0x003c
+#define HC_ParaSubType_MASK 0xff000000
+#define HC_ParaType_MASK 0x00ff0000
+#define HC_ParaOS_MASK 0x0000ff00
+#define HC_ParaAdr_MASK 0x000000ff
+#define HC_ParaSubType_SHIFT 24
+#define HC_ParaType_SHIFT 16
+#define HC_ParaOS_SHIFT 8
+#define HC_ParaAdr_SHIFT 0
+
+#define HC_ParaType_CmdVdata 0x0000
+#define HC_ParaType_NotTex 0x0001
+#define HC_ParaType_Tex 0x0002
+#define HC_ParaType_Palette 0x0003
+#define HC_ParaType_PreCR 0x0010
+#define HC_ParaType_Auto 0x00fe
+
+/* Transmission Space
+ */
+#define HC_REG_Hpara0 0x0040
+#define HC_REG_HpataAF 0x02fc
+
+/* Read
+ */
+#define HC_REG_HREngSt 0x0000
+#define HC_REG_HRFIFOempty 0x0004
+#define HC_REG_HRFIFOfull 0x0008
+#define HC_REG_HRErr 0x000c
+#define HC_REG_FIFOstatus 0x0010
+/* HC_REG_HREngSt 0x0000
+ */
+#define HC_HDASZC_MASK 0x00010000
+#define HC_HSGEMI_MASK 0x0000f000
+#define HC_HLGEMISt_MASK 0x00000f00
+#define HC_HCRSt_MASK 0x00000080
+#define HC_HSE0St_MASK 0x00000040
+#define HC_HSE1St_MASK 0x00000020
+#define HC_HPESt_MASK 0x00000010
+#define HC_HXESt_MASK 0x00000008
+#define HC_HBESt_MASK 0x00000004
+#define HC_HE2St_MASK 0x00000002
+#define HC_HE3St_MASK 0x00000001
+/* HC_REG_HRFIFOempty 0x0004
+ */
+#define HC_HRZDempty_MASK 0x00000010
+#define HC_HRTXAempty_MASK 0x00000008
+#define HC_HRTXDempty_MASK 0x00000004
+#define HC_HWZDempty_MASK 0x00000002
+#define HC_HWCDempty_MASK 0x00000001
+/* HC_REG_HRFIFOfull 0x0008
+ */
+#define HC_HRZDfull_MASK 0x00000010
+#define HC_HRTXAfull_MASK 0x00000008
+#define HC_HRTXDfull_MASK 0x00000004
+#define HC_HWZDfull_MASK 0x00000002
+#define HC_HWCDfull_MASK 0x00000001
+/* HC_REG_HRErr 0x000c
+ */
+#define HC_HAGPCMErr_MASK 0x80000000
+#define HC_HAGPCMErrC_MASK 0x70000000
+/* HC_REG_FIFOstatus 0x0010
+ */
+#define HC_HRFIFOATall_MASK 0x80000000
+#define HC_HRFIFOATbusy_MASK 0x40000000
+#define HC_HRATFGMDo_MASK 0x00000100
+#define HC_HRATFGMDi_MASK 0x00000080
+#define HC_HRATFRZD_MASK 0x00000040
+#define HC_HRATFRTXA_MASK 0x00000020
+#define HC_HRATFRTXD_MASK 0x00000010
+#define HC_HRATFWZD_MASK 0x00000008
+#define HC_HRATFWCD_MASK 0x00000004
+#define HC_HRATTXTAG_MASK 0x00000002
+#define HC_HRATTXCH_MASK 0x00000001
+
+/* AGP Command Setting
+ */
+#define HC_SubA_HAGPBstL 0x0060
+#define HC_SubA_HAGPBendL 0x0061
+#define HC_SubA_HAGPCMNT 0x0062
+#define HC_SubA_HAGPBpL 0x0063
+#define HC_SubA_HAGPBpH 0x0064
+/* HC_SubA_HAGPCMNT 0x0062
+ */
+#define HC_HAGPCMNT_MASK 0x00800000
+#define HC_HCmdErrClr_MASK 0x00400000
+#define HC_HAGPBendH_MASK 0x0000ff00
+#define HC_HAGPBstH_MASK 0x000000ff
+#define HC_HAGPBendH_SHIFT 8
+#define HC_HAGPBstH_SHIFT 0
+/* HC_SubA_HAGPBpL 0x0063
+ */
+#define HC_HAGPBpL_MASK 0x00fffffc
+#define HC_HAGPBpID_MASK 0x00000003
+#define HC_HAGPBpID_PAUSE 0x00000000
+#define HC_HAGPBpID_JUMP 0x00000001
+#define HC_HAGPBpID_STOP 0x00000002
+/* HC_SubA_HAGPBpH 0x0064
+ */
+#define HC_HAGPBpH_MASK 0x00ffffff
+
+/* Miscellaneous Settings
+ */
+#define HC_SubA_HClipTB 0x0070
+#define HC_SubA_HClipLR 0x0071
+#define HC_SubA_HFPClipTL 0x0072
+#define HC_SubA_HFPClipBL 0x0073
+#define HC_SubA_HFPClipLL 0x0074
+#define HC_SubA_HFPClipRL 0x0075
+#define HC_SubA_HFPClipTBH 0x0076
+#define HC_SubA_HFPClipLRH 0x0077
+#define HC_SubA_HLP 0x0078
+#define HC_SubA_HLPRF 0x0079
+#define HC_SubA_HSolidCL 0x007a
+#define HC_SubA_HPixGC 0x007b
+#define HC_SubA_HSPXYOS 0x007c
+#define HC_SubA_HVertexCNT 0x007d
+
+#define HC_HClipT_MASK 0x00fff000
+#define HC_HClipT_SHIFT 12
+#define HC_HClipB_MASK 0x00000fff
+#define HC_HClipB_SHIFT 0
+#define HC_HClipL_MASK 0x00fff000
+#define HC_HClipL_SHIFT 12
+#define HC_HClipR_MASK 0x00000fff
+#define HC_HClipR_SHIFT 0
+#define HC_HFPClipBH_MASK 0x0000ff00
+#define HC_HFPClipBH_SHIFT 8
+#define HC_HFPClipTH_MASK 0x000000ff
+#define HC_HFPClipTH_SHIFT 0
+#define HC_HFPClipRH_MASK 0x0000ff00
+#define HC_HFPClipRH_SHIFT 8
+#define HC_HFPClipLH_MASK 0x000000ff
+#define HC_HFPClipLH_SHIFT 0
+#define HC_HSolidCH_MASK 0x000000ff
+#define HC_HPixGC_MASK 0x00800000
+#define HC_HSPXOS_MASK 0x00fff000
+#define HC_HSPXOS_SHIFT 12
+#define HC_HSPYOS_MASK 0x00000fff
+
+/* Command
+ * Command A
+ */
+#define HC_HCmdHeader_MASK 0xfe000000 /*0xffe00000 */
+#define HC_HE3Fire_MASK 0x00100000
+#define HC_HPMType_MASK 0x000f0000
+#define HC_HEFlag_MASK 0x0000e000
+#define HC_HShading_MASK 0x00001c00
+#define HC_HPMValidN_MASK 0x00000200
+#define HC_HPLEND_MASK 0x00000100
+#define HC_HVCycle_MASK 0x000000ff
+#define HC_HVCycle_Style_MASK 0x000000c0
+#define HC_HVCycle_ChgA_MASK 0x00000030
+#define HC_HVCycle_ChgB_MASK 0x0000000c
+#define HC_HVCycle_ChgC_MASK 0x00000003
+#define HC_HPMType_Point 0x00000000
+#define HC_HPMType_Line 0x00010000
+#define HC_HPMType_Tri 0x00020000
+#define HC_HPMType_TriWF 0x00040000
+#define HC_HEFlag_NoAA 0x00000000
+#define HC_HEFlag_ab 0x00008000
+#define HC_HEFlag_bc 0x00004000
+#define HC_HEFlag_ca 0x00002000
+#define HC_HShading_Solid 0x00000000
+#define HC_HShading_FlatA 0x00000400
+#define HC_HShading_FlatB 0x00000800
+#define HC_HShading_FlatC 0x00000c00
+#define HC_HShading_Gouraud 0x00001000
+#define HC_HVCycle_Full 0x00000000
+#define HC_HVCycle_AFP 0x00000040
+#define HC_HVCycle_One 0x000000c0
+#define HC_HVCycle_NewA 0x00000000
+#define HC_HVCycle_AA 0x00000010
+#define HC_HVCycle_AB 0x00000020
+#define HC_HVCycle_AC 0x00000030
+#define HC_HVCycle_NewB 0x00000000
+#define HC_HVCycle_BA 0x00000004
+#define HC_HVCycle_BB 0x00000008
+#define HC_HVCycle_BC 0x0000000c
+#define HC_HVCycle_NewC 0x00000000
+#define HC_HVCycle_CA 0x00000001
+#define HC_HVCycle_CB 0x00000002
+#define HC_HVCycle_CC 0x00000003
+
+/* Command B
+ */
+#define HC_HLPrst_MASK 0x00010000
+#define HC_HLLastP_MASK 0x00008000
+#define HC_HVPMSK_MASK 0x00007f80
+#define HC_HBFace_MASK 0x00000040
+#define HC_H2nd1VT_MASK 0x0000003f
+#define HC_HVPMSK_X 0x00004000
+#define HC_HVPMSK_Y 0x00002000
+#define HC_HVPMSK_Z 0x00001000
+#define HC_HVPMSK_W 0x00000800
+#define HC_HVPMSK_Cd 0x00000400
+#define HC_HVPMSK_Cs 0x00000200
+#define HC_HVPMSK_S 0x00000100
+#define HC_HVPMSK_T 0x00000080
+
+/* Enable Setting
+ */
+#define HC_SubA_HEnable 0x0000
+#define HC_HenTXEnvMap_MASK 0x00200000
+#define HC_HenVertexCNT_MASK 0x00100000
+#define HC_HenCPUDAZ_MASK 0x00080000
+#define HC_HenDASZWC_MASK 0x00040000
+#define HC_HenFBCull_MASK 0x00020000
+#define HC_HenCW_MASK 0x00010000
+#define HC_HenAA_MASK 0x00008000
+#define HC_HenST_MASK 0x00004000
+#define HC_HenZT_MASK 0x00002000
+#define HC_HenZW_MASK 0x00001000
+#define HC_HenAT_MASK 0x00000800
+#define HC_HenAW_MASK 0x00000400
+#define HC_HenSP_MASK 0x00000200
+#define HC_HenLP_MASK 0x00000100
+#define HC_HenTXCH_MASK 0x00000080
+#define HC_HenTXMP_MASK 0x00000040
+#define HC_HenTXPP_MASK 0x00000020
+#define HC_HenTXTR_MASK 0x00000010
+#define HC_HenCS_MASK 0x00000008
+#define HC_HenFOG_MASK 0x00000004
+#define HC_HenABL_MASK 0x00000002
+#define HC_HenDT_MASK 0x00000001
+
+/* Z Setting
+ */
+#define HC_SubA_HZWBBasL 0x0010
+#define HC_SubA_HZWBBasH 0x0011
+#define HC_SubA_HZWBType 0x0012
+#define HC_SubA_HZBiasL 0x0013
+#define HC_SubA_HZWBend 0x0014
+#define HC_SubA_HZWTMD 0x0015
+#define HC_SubA_HZWCDL 0x0016
+#define HC_SubA_HZWCTAGnum 0x0017
+#define HC_SubA_HZCYNum 0x0018
+#define HC_SubA_HZWCFire 0x0019
+/* HC_SubA_HZWBType
+ */
+#define HC_HZWBType_MASK 0x00800000
+#define HC_HZBiasedWB_MASK 0x00400000
+#define HC_HZONEasFF_MASK 0x00200000
+#define HC_HZOONEasFF_MASK 0x00100000
+#define HC_HZWBFM_MASK 0x00030000
+#define HC_HZWBLoc_MASK 0x0000c000
+#define HC_HZWBPit_MASK 0x00003fff
+#define HC_HZWBFM_16 0x00000000
+#define HC_HZWBFM_32 0x00020000
+#define HC_HZWBFM_24 0x00030000
+#define HC_HZWBLoc_Local 0x00000000
+#define HC_HZWBLoc_SyS 0x00004000
+/* HC_SubA_HZWBend
+ */
+#define HC_HZWBend_MASK 0x00ffe000
+#define HC_HZBiasH_MASK 0x000000ff
+#define HC_HZWBend_SHIFT 10
+/* HC_SubA_HZWTMD
+ */
+#define HC_HZWTMD_MASK 0x00070000
+#define HC_HEBEBias_MASK 0x00007f00
+#define HC_HZNF_MASK 0x000000ff
+#define HC_HZWTMD_NeverPass 0x00000000
+#define HC_HZWTMD_LT 0x00010000
+#define HC_HZWTMD_EQ 0x00020000
+#define HC_HZWTMD_LE 0x00030000
+#define HC_HZWTMD_GT 0x00040000
+#define HC_HZWTMD_NE 0x00050000
+#define HC_HZWTMD_GE 0x00060000
+#define HC_HZWTMD_AllPass 0x00070000
+#define HC_HEBEBias_SHIFT 8
+/* HC_SubA_HZWCDL 0x0016
+ */
+#define HC_HZWCDL_MASK 0x00ffffff
+/* HC_SubA_HZWCTAGnum 0x0017
+ */
+#define HC_HZWCTAGnum_MASK 0x00ff0000
+#define HC_HZWCTAGnum_SHIFT 16
+#define HC_HZWCDH_MASK 0x000000ff
+#define HC_HZWCDH_SHIFT 0
+/* HC_SubA_HZCYNum 0x0018
+ */
+#define HC_HZCYNum_MASK 0x00030000
+#define HC_HZCYNum_SHIFT 16
+#define HC_HZWCQWnum_MASK 0x00003fff
+#define HC_HZWCQWnum_SHIFT 0
+/* HC_SubA_HZWCFire 0x0019
+ */
+#define HC_ZWCFire_MASK 0x00010000
+#define HC_HZWCQWnumLast_MASK 0x00003fff
+#define HC_HZWCQWnumLast_SHIFT 0
+
+/* Stencil Setting
+ */
+#define HC_SubA_HSTREF 0x0023
+#define HC_SubA_HSTMD 0x0024
+/* HC_SubA_HSBFM
+ */
+#define HC_HSBFM_MASK 0x00030000
+#define HC_HSBLoc_MASK 0x0000c000
+#define HC_HSBPit_MASK 0x00003fff
+/* HC_SubA_HSTREF
+ */
+#define HC_HSTREF_MASK 0x00ff0000
+#define HC_HSTOPMSK_MASK 0x0000ff00
+#define HC_HSTBMSK_MASK 0x000000ff
+#define HC_HSTREF_SHIFT 16
+#define HC_HSTOPMSK_SHIFT 8
+/* HC_SubA_HSTMD
+ */
+#define HC_HSTMD_MASK 0x00070000
+#define HC_HSTOPSF_MASK 0x000001c0
+#define HC_HSTOPSPZF_MASK 0x00000038
+#define HC_HSTOPSPZP_MASK 0x00000007
+#define HC_HSTMD_NeverPass 0x00000000
+#define HC_HSTMD_LT 0x00010000
+#define HC_HSTMD_EQ 0x00020000
+#define HC_HSTMD_LE 0x00030000
+#define HC_HSTMD_GT 0x00040000
+#define HC_HSTMD_NE 0x00050000
+#define HC_HSTMD_GE 0x00060000
+#define HC_HSTMD_AllPass 0x00070000
+#define HC_HSTOPSF_KEEP 0x00000000
+#define HC_HSTOPSF_ZERO 0x00000040
+#define HC_HSTOPSF_REPLACE 0x00000080
+#define HC_HSTOPSF_INCRSAT 0x000000c0
+#define HC_HSTOPSF_DECRSAT 0x00000100
+#define HC_HSTOPSF_INVERT 0x00000140
+#define HC_HSTOPSF_INCR 0x00000180
+#define HC_HSTOPSF_DECR 0x000001c0
+#define HC_HSTOPSPZF_KEEP 0x00000000
+#define HC_HSTOPSPZF_ZERO 0x00000008
+#define HC_HSTOPSPZF_REPLACE 0x00000010
+#define HC_HSTOPSPZF_INCRSAT 0x00000018
+#define HC_HSTOPSPZF_DECRSAT 0x00000020
+#define HC_HSTOPSPZF_INVERT 0x00000028
+#define HC_HSTOPSPZF_INCR 0x00000030
+#define HC_HSTOPSPZF_DECR 0x00000038
+#define HC_HSTOPSPZP_KEEP 0x00000000
+#define HC_HSTOPSPZP_ZERO 0x00000001
+#define HC_HSTOPSPZP_REPLACE 0x00000002
+#define HC_HSTOPSPZP_INCRSAT 0x00000003
+#define HC_HSTOPSPZP_DECRSAT 0x00000004
+#define HC_HSTOPSPZP_INVERT 0x00000005
+#define HC_HSTOPSPZP_INCR 0x00000006
+#define HC_HSTOPSPZP_DECR 0x00000007
+
+/* Alpha Setting
+ */
+#define HC_SubA_HABBasL 0x0030
+#define HC_SubA_HABBasH 0x0031
+#define HC_SubA_HABFM 0x0032
+#define HC_SubA_HATMD 0x0033
+#define HC_SubA_HABLCsat 0x0034
+#define HC_SubA_HABLCop 0x0035
+#define HC_SubA_HABLAsat 0x0036
+#define HC_SubA_HABLAop 0x0037
+#define HC_SubA_HABLRCa 0x0038
+#define HC_SubA_HABLRFCa 0x0039
+#define HC_SubA_HABLRCbias 0x003a
+#define HC_SubA_HABLRCb 0x003b
+#define HC_SubA_HABLRFCb 0x003c
+#define HC_SubA_HABLRAa 0x003d
+#define HC_SubA_HABLRAb 0x003e
+/* HC_SubA_HABFM
+ */
+#define HC_HABFM_MASK 0x00030000
+#define HC_HABLoc_MASK 0x0000c000
+#define HC_HABPit_MASK 0x000007ff
+/* HC_SubA_HATMD
+ */
+#define HC_HATMD_MASK 0x00000700
+#define HC_HATREF_MASK 0x000000ff
+#define HC_HATMD_NeverPass 0x00000000
+#define HC_HATMD_LT 0x00000100
+#define HC_HATMD_EQ 0x00000200
+#define HC_HATMD_LE 0x00000300
+#define HC_HATMD_GT 0x00000400
+#define HC_HATMD_NE 0x00000500
+#define HC_HATMD_GE 0x00000600
+#define HC_HATMD_AllPass 0x00000700
+/* HC_SubA_HABLCsat
+ */
+#define HC_HABLCsat_MASK 0x00010000
+#define HC_HABLCa_MASK 0x0000fc00
+#define HC_HABLCa_C_MASK 0x0000c000
+#define HC_HABLCa_OPC_MASK 0x00003c00
+#define HC_HABLFCa_MASK 0x000003f0
+#define HC_HABLFCa_C_MASK 0x00000300
+#define HC_HABLFCa_OPC_MASK 0x000000f0
+#define HC_HABLCbias_MASK 0x0000000f
+#define HC_HABLCbias_C_MASK 0x00000008
+#define HC_HABLCbias_OPC_MASK 0x00000007
+/*-- Define the input color.
+ */
+#define HC_XC_Csrc 0x00000000
+#define HC_XC_Cdst 0x00000001
+#define HC_XC_Asrc 0x00000002
+#define HC_XC_Adst 0x00000003
+#define HC_XC_Fog 0x00000004
+#define HC_XC_HABLRC 0x00000005
+#define HC_XC_minSrcDst 0x00000006
+#define HC_XC_maxSrcDst 0x00000007
+#define HC_XC_mimAsrcInvAdst 0x00000008
+#define HC_XC_OPC 0x00000000
+#define HC_XC_InvOPC 0x00000010
+#define HC_XC_OPCp5 0x00000020
+/*-- Define the input Alpha
+ */
+#define HC_XA_OPA 0x00000000
+#define HC_XA_InvOPA 0x00000010
+#define HC_XA_OPAp5 0x00000020
+#define HC_XA_0 0x00000000
+#define HC_XA_Asrc 0x00000001
+#define HC_XA_Adst 0x00000002
+#define HC_XA_Fog 0x00000003
+#define HC_XA_minAsrcFog 0x00000004
+#define HC_XA_minAsrcAdst 0x00000005
+#define HC_XA_maxAsrcFog 0x00000006
+#define HC_XA_maxAsrcAdst 0x00000007
+#define HC_XA_HABLRA 0x00000008
+#define HC_XA_minAsrcInvAdst 0x00000008
+#define HC_XA_HABLFRA 0x00000009
+/*--
+ */
+#define HC_HABLCa_OPC (HC_XC_OPC << 10)
+#define HC_HABLCa_InvOPC (HC_XC_InvOPC << 10)
+#define HC_HABLCa_OPCp5 (HC_XC_OPCp5 << 10)
+#define HC_HABLCa_Csrc (HC_XC_Csrc << 10)
+#define HC_HABLCa_Cdst (HC_XC_Cdst << 10)
+#define HC_HABLCa_Asrc (HC_XC_Asrc << 10)
+#define HC_HABLCa_Adst (HC_XC_Adst << 10)
+#define HC_HABLCa_Fog (HC_XC_Fog << 10)
+#define HC_HABLCa_HABLRCa (HC_XC_HABLRC << 10)
+#define HC_HABLCa_minSrcDst (HC_XC_minSrcDst << 10)
+#define HC_HABLCa_maxSrcDst (HC_XC_maxSrcDst << 10)
+#define HC_HABLFCa_OPC (HC_XC_OPC << 4)
+#define HC_HABLFCa_InvOPC (HC_XC_InvOPC << 4)
+#define HC_HABLFCa_OPCp5 (HC_XC_OPCp5 << 4)
+#define HC_HABLFCa_Csrc (HC_XC_Csrc << 4)
+#define HC_HABLFCa_Cdst (HC_XC_Cdst << 4)
+#define HC_HABLFCa_Asrc (HC_XC_Asrc << 4)
+#define HC_HABLFCa_Adst (HC_XC_Adst << 4)
+#define HC_HABLFCa_Fog (HC_XC_Fog << 4)
+#define HC_HABLFCa_HABLRCa (HC_XC_HABLRC << 4)
+#define HC_HABLFCa_minSrcDst (HC_XC_minSrcDst << 4)
+#define HC_HABLFCa_maxSrcDst (HC_XC_maxSrcDst << 4)
+#define HC_HABLFCa_mimAsrcInvAdst (HC_XC_mimAsrcInvAdst << 4)
+#define HC_HABLCbias_HABLRCbias 0x00000000
+#define HC_HABLCbias_Asrc 0x00000001
+#define HC_HABLCbias_Adst 0x00000002
+#define HC_HABLCbias_Fog 0x00000003
+#define HC_HABLCbias_Cin 0x00000004
+/* HC_SubA_HABLCop 0x0035
+ */
+#define HC_HABLdot_MASK 0x00010000
+#define HC_HABLCop_MASK 0x00004000
+#define HC_HABLCb_MASK 0x00003f00
+#define HC_HABLCb_C_MASK 0x00003000
+#define HC_HABLCb_OPC_MASK 0x00000f00
+#define HC_HABLFCb_MASK 0x000000fc
+#define HC_HABLFCb_C_MASK 0x000000c0
+#define HC_HABLFCb_OPC_MASK 0x0000003c
+#define HC_HABLCshift_MASK 0x00000003
+#define HC_HABLCb_OPC (HC_XC_OPC << 8)
+#define HC_HABLCb_InvOPC (HC_XC_InvOPC << 8)
+#define HC_HABLCb_OPCp5 (HC_XC_OPCp5 << 8)
+#define HC_HABLCb_Csrc (HC_XC_Csrc << 8)
+#define HC_HABLCb_Cdst (HC_XC_Cdst << 8)
+#define HC_HABLCb_Asrc (HC_XC_Asrc << 8)
+#define HC_HABLCb_Adst (HC_XC_Adst << 8)
+#define HC_HABLCb_Fog (HC_XC_Fog << 8)
+#define HC_HABLCb_HABLRCa (HC_XC_HABLRC << 8)
+#define HC_HABLCb_minSrcDst (HC_XC_minSrcDst << 8)
+#define HC_HABLCb_maxSrcDst (HC_XC_maxSrcDst << 8)
+#define HC_HABLFCb_OPC (HC_XC_OPC << 2)
+#define HC_HABLFCb_InvOPC (HC_XC_InvOPC << 2)
+#define HC_HABLFCb_OPCp5 (HC_XC_OPCp5 << 2)
+#define HC_HABLFCb_Csrc (HC_XC_Csrc << 2)
+#define HC_HABLFCb_Cdst (HC_XC_Cdst << 2)
+#define HC_HABLFCb_Asrc (HC_XC_Asrc << 2)
+#define HC_HABLFCb_Adst (HC_XC_Adst << 2)
+#define HC_HABLFCb_Fog (HC_XC_Fog << 2)
+#define HC_HABLFCb_HABLRCb (HC_XC_HABLRC << 2)
+#define HC_HABLFCb_minSrcDst (HC_XC_minSrcDst << 2)
+#define HC_HABLFCb_maxSrcDst (HC_XC_maxSrcDst << 2)
+#define HC_HABLFCb_mimAsrcInvAdst (HC_XC_mimAsrcInvAdst << 2)
+/* HC_SubA_HABLAsat 0x0036
+ */
+#define HC_HABLAsat_MASK 0x00010000
+#define HC_HABLAa_MASK 0x0000fc00
+#define HC_HABLAa_A_MASK 0x0000c000
+#define HC_HABLAa_OPA_MASK 0x00003c00
+#define HC_HABLFAa_MASK 0x000003f0
+#define HC_HABLFAa_A_MASK 0x00000300
+#define HC_HABLFAa_OPA_MASK 0x000000f0
+#define HC_HABLAbias_MASK 0x0000000f
+#define HC_HABLAbias_A_MASK 0x00000008
+#define HC_HABLAbias_OPA_MASK 0x00000007
+#define HC_HABLAa_OPA (HC_XA_OPA << 10)
+#define HC_HABLAa_InvOPA (HC_XA_InvOPA << 10)
+#define HC_HABLAa_OPAp5 (HC_XA_OPAp5 << 10)
+#define HC_HABLAa_0 (HC_XA_0 << 10)
+#define HC_HABLAa_Asrc (HC_XA_Asrc << 10)
+#define HC_HABLAa_Adst (HC_XA_Adst << 10)
+#define HC_HABLAa_Fog (HC_XA_Fog << 10)
+#define HC_HABLAa_minAsrcFog (HC_XA_minAsrcFog << 10)
+#define HC_HABLAa_minAsrcAdst (HC_XA_minAsrcAdst << 10)
+#define HC_HABLAa_maxAsrcFog (HC_XA_maxAsrcFog << 10)
+#define HC_HABLAa_maxAsrcAdst (HC_XA_maxAsrcAdst << 10)
+#define HC_HABLAa_HABLRA (HC_XA_HABLRA << 10)
+#define HC_HABLFAa_OPA (HC_XA_OPA << 4)
+#define HC_HABLFAa_InvOPA (HC_XA_InvOPA << 4)
+#define HC_HABLFAa_OPAp5 (HC_XA_OPAp5 << 4)
+#define HC_HABLFAa_0 (HC_XA_0 << 4)
+#define HC_HABLFAa_Asrc (HC_XA_Asrc << 4)
+#define HC_HABLFAa_Adst (HC_XA_Adst << 4)
+#define HC_HABLFAa_Fog (HC_XA_Fog << 4)
+#define HC_HABLFAa_minAsrcFog (HC_XA_minAsrcFog << 4)
+#define HC_HABLFAa_minAsrcAdst (HC_XA_minAsrcAdst << 4)
+#define HC_HABLFAa_maxAsrcFog (HC_XA_maxAsrcFog << 4)
+#define HC_HABLFAa_maxAsrcAdst (HC_XA_maxAsrcAdst << 4)
+#define HC_HABLFAa_minAsrcInvAdst (HC_XA_minAsrcInvAdst << 4)
+#define HC_HABLFAa_HABLFRA (HC_XA_HABLFRA << 4)
+#define HC_HABLAbias_HABLRAbias 0x00000000
+#define HC_HABLAbias_Asrc 0x00000001
+#define HC_HABLAbias_Adst 0x00000002
+#define HC_HABLAbias_Fog 0x00000003
+#define HC_HABLAbias_Aaa 0x00000004
+/* HC_SubA_HABLAop 0x0037
+ */
+#define HC_HABLAop_MASK 0x00004000
+#define HC_HABLAb_MASK 0x00003f00
+#define HC_HABLAb_OPA_MASK 0x00000f00
+#define HC_HABLFAb_MASK 0x000000fc
+#define HC_HABLFAb_OPA_MASK 0x0000003c
+#define HC_HABLAshift_MASK 0x00000003
+#define HC_HABLAb_OPA (HC_XA_OPA << 8)
+#define HC_HABLAb_InvOPA (HC_XA_InvOPA << 8)
+#define HC_HABLAb_OPAp5 (HC_XA_OPAp5 << 8)
+#define HC_HABLAb_0 (HC_XA_0 << 8)
+#define HC_HABLAb_Asrc (HC_XA_Asrc << 8)
+#define HC_HABLAb_Adst (HC_XA_Adst << 8)
+#define HC_HABLAb_Fog (HC_XA_Fog << 8)
+#define HC_HABLAb_minAsrcFog (HC_XA_minAsrcFog << 8)
+#define HC_HABLAb_minAsrcAdst (HC_XA_minAsrcAdst << 8)
+#define HC_HABLAb_maxAsrcFog (HC_XA_maxAsrcFog << 8)
+#define HC_HABLAb_maxAsrcAdst (HC_XA_maxAsrcAdst << 8)
+#define HC_HABLAb_HABLRA (HC_XA_HABLRA << 8)
+#define HC_HABLFAb_OPA (HC_XA_OPA << 2)
+#define HC_HABLFAb_InvOPA (HC_XA_InvOPA << 2)
+#define HC_HABLFAb_OPAp5 (HC_XA_OPAp5 << 2)
+#define HC_HABLFAb_0 (HC_XA_0 << 2)
+#define HC_HABLFAb_Asrc (HC_XA_Asrc << 2)
+#define HC_HABLFAb_Adst (HC_XA_Adst << 2)
+#define HC_HABLFAb_Fog (HC_XA_Fog << 2)
+#define HC_HABLFAb_minAsrcFog (HC_XA_minAsrcFog << 2)
+#define HC_HABLFAb_minAsrcAdst (HC_XA_minAsrcAdst << 2)
+#define HC_HABLFAb_maxAsrcFog (HC_XA_maxAsrcFog << 2)
+#define HC_HABLFAb_maxAsrcAdst (HC_XA_maxAsrcAdst << 2)
+#define HC_HABLFAb_minAsrcInvAdst (HC_XA_minAsrcInvAdst << 2)
+#define HC_HABLFAb_HABLFRA (HC_XA_HABLFRA << 2)
+/* HC_SubA_HABLRAa 0x003d
+ */
+#define HC_HABLRAa_MASK 0x00ff0000
+#define HC_HABLRFAa_MASK 0x0000ff00
+#define HC_HABLRAbias_MASK 0x000000ff
+#define HC_HABLRAa_SHIFT 16
+#define HC_HABLRFAa_SHIFT 8
+/* HC_SubA_HABLRAb 0x003e
+ */
+#define HC_HABLRAb_MASK 0x0000ff00
+#define HC_HABLRFAb_MASK 0x000000ff
+#define HC_HABLRAb_SHIFT 8
+
+/* Destination Setting
+ */
+#define HC_SubA_HDBBasL 0x0040
+#define HC_SubA_HDBBasH 0x0041
+#define HC_SubA_HDBFM 0x0042
+#define HC_SubA_HFBBMSKL 0x0043
+#define HC_SubA_HROP 0x0044
+/* HC_SubA_HDBFM 0x0042
+ */
+#define HC_HDBFM_MASK 0x001f0000
+#define HC_HDBLoc_MASK 0x0000c000
+#define HC_HDBPit_MASK 0x00003fff
+#define HC_HDBFM_RGB555 0x00000000
+#define HC_HDBFM_RGB565 0x00010000
+#define HC_HDBFM_ARGB4444 0x00020000
+#define HC_HDBFM_ARGB1555 0x00030000
+#define HC_HDBFM_BGR555 0x00040000
+#define HC_HDBFM_BGR565 0x00050000
+#define HC_HDBFM_ABGR4444 0x00060000
+#define HC_HDBFM_ABGR1555 0x00070000
+#define HC_HDBFM_ARGB0888 0x00080000
+#define HC_HDBFM_ARGB8888 0x00090000
+#define HC_HDBFM_ABGR0888 0x000a0000
+#define HC_HDBFM_ABGR8888 0x000b0000
+#define HC_HDBLoc_Local 0x00000000
+#define HC_HDBLoc_Sys 0x00004000
+/* HC_SubA_HROP 0x0044
+ */
+#define HC_HROP_MASK 0x00000f00
+#define HC_HFBBMSKH_MASK 0x000000ff
+#define HC_HROP_BLACK 0x00000000
+#define HC_HROP_DPon 0x00000100
+#define HC_HROP_DPna 0x00000200
+#define HC_HROP_Pn 0x00000300
+#define HC_HROP_PDna 0x00000400
+#define HC_HROP_Dn 0x00000500
+#define HC_HROP_DPx 0x00000600
+#define HC_HROP_DPan 0x00000700
+#define HC_HROP_DPa 0x00000800
+#define HC_HROP_DPxn 0x00000900
+#define HC_HROP_D 0x00000a00
+#define HC_HROP_DPno 0x00000b00
+#define HC_HROP_P 0x00000c00
+#define HC_HROP_PDno 0x00000d00
+#define HC_HROP_DPo 0x00000e00
+#define HC_HROP_WHITE 0x00000f00
+
+/* Fog Setting
+ */
+#define HC_SubA_HFogLF 0x0050
+#define HC_SubA_HFogCL 0x0051
+#define HC_SubA_HFogCH 0x0052
+#define HC_SubA_HFogStL 0x0053
+#define HC_SubA_HFogStH 0x0054
+#define HC_SubA_HFogOOdMF 0x0055
+#define HC_SubA_HFogOOdEF 0x0056
+#define HC_SubA_HFogEndL 0x0057
+#define HC_SubA_HFogDenst 0x0058
+/* HC_SubA_FogLF 0x0050
+ */
+#define HC_FogLF_MASK 0x00000010
+#define HC_FogEq_MASK 0x00000008
+#define HC_FogMD_MASK 0x00000007
+#define HC_FogMD_LocalFog 0x00000000
+#define HC_FogMD_LinearFog 0x00000002
+#define HC_FogMD_ExponentialFog 0x00000004
+#define HC_FogMD_Exponential2Fog 0x00000005
+/* #define HC_FogMD_FogTable 0x00000003 */
+
+/* HC_SubA_HFogDenst 0x0058
+ */
+#define HC_FogDenst_MASK 0x001fff00
+#define HC_FogEndL_MASK 0x000000ff
+
+/* Texture subtype definitions
+ */
+#define HC_SubType_Tex0 0x00000000
+#define HC_SubType_Tex1 0x00000001
+#define HC_SubType_TexGeneral 0x000000fe
+
+/* Attribute of texture n
+ */
+#define HC_SubA_HTXnL0BasL 0x0000
+#define HC_SubA_HTXnL1BasL 0x0001
+#define HC_SubA_HTXnL2BasL 0x0002
+#define HC_SubA_HTXnL3BasL 0x0003
+#define HC_SubA_HTXnL4BasL 0x0004
+#define HC_SubA_HTXnL5BasL 0x0005
+#define HC_SubA_HTXnL6BasL 0x0006
+#define HC_SubA_HTXnL7BasL 0x0007
+#define HC_SubA_HTXnL8BasL 0x0008
+#define HC_SubA_HTXnL9BasL 0x0009
+#define HC_SubA_HTXnLaBasL 0x000a
+#define HC_SubA_HTXnLbBasL 0x000b
+#define HC_SubA_HTXnLcBasL 0x000c
+#define HC_SubA_HTXnLdBasL 0x000d
+#define HC_SubA_HTXnLeBasL 0x000e
+#define HC_SubA_HTXnLfBasL 0x000f
+#define HC_SubA_HTXnL10BasL 0x0010
+#define HC_SubA_HTXnL11BasL 0x0011
+#define HC_SubA_HTXnL012BasH 0x0020
+#define HC_SubA_HTXnL345BasH 0x0021
+#define HC_SubA_HTXnL678BasH 0x0022
+#define HC_SubA_HTXnL9abBasH 0x0023
+#define HC_SubA_HTXnLcdeBasH 0x0024
+#define HC_SubA_HTXnLf1011BasH 0x0025
+#define HC_SubA_HTXnL0Pit 0x002b
+#define HC_SubA_HTXnL1Pit 0x002c
+#define HC_SubA_HTXnL2Pit 0x002d
+#define HC_SubA_HTXnL3Pit 0x002e
+#define HC_SubA_HTXnL4Pit 0x002f
+#define HC_SubA_HTXnL5Pit 0x0030
+#define HC_SubA_HTXnL6Pit 0x0031
+#define HC_SubA_HTXnL7Pit 0x0032
+#define HC_SubA_HTXnL8Pit 0x0033
+#define HC_SubA_HTXnL9Pit 0x0034
+#define HC_SubA_HTXnLaPit 0x0035
+#define HC_SubA_HTXnLbPit 0x0036
+#define HC_SubA_HTXnLcPit 0x0037
+#define HC_SubA_HTXnLdPit 0x0038
+#define HC_SubA_HTXnLePit 0x0039
+#define HC_SubA_HTXnLfPit 0x003a
+#define HC_SubA_HTXnL10Pit 0x003b
+#define HC_SubA_HTXnL11Pit 0x003c
+#define HC_SubA_HTXnL0_5WE 0x004b
+#define HC_SubA_HTXnL6_bWE 0x004c
+#define HC_SubA_HTXnLc_11WE 0x004d
+#define HC_SubA_HTXnL0_5HE 0x0051
+#define HC_SubA_HTXnL6_bHE 0x0052
+#define HC_SubA_HTXnLc_11HE 0x0053
+#define HC_SubA_HTXnL0OS 0x0077
+#define HC_SubA_HTXnTB 0x0078
+#define HC_SubA_HTXnMPMD 0x0079
+#define HC_SubA_HTXnCLODu 0x007a
+#define HC_SubA_HTXnFM 0x007b
+#define HC_SubA_HTXnTRCH 0x007c
+#define HC_SubA_HTXnTRCL 0x007d
+#define HC_SubA_HTXnTBC 0x007e
+#define HC_SubA_HTXnTRAH 0x007f
+#define HC_SubA_HTXnTBLCsat 0x0080
+#define HC_SubA_HTXnTBLCop 0x0081
+#define HC_SubA_HTXnTBLMPfog 0x0082
+#define HC_SubA_HTXnTBLAsat 0x0083
+#define HC_SubA_HTXnTBLRCa 0x0085
+#define HC_SubA_HTXnTBLRCb 0x0086
+#define HC_SubA_HTXnTBLRCc 0x0087
+#define HC_SubA_HTXnTBLRCbias 0x0088
+#define HC_SubA_HTXnTBLRAa 0x0089
+#define HC_SubA_HTXnTBLRFog 0x008a
+#define HC_SubA_HTXnBumpM00 0x0090
+#define HC_SubA_HTXnBumpM01 0x0091
+#define HC_SubA_HTXnBumpM10 0x0092
+#define HC_SubA_HTXnBumpM11 0x0093
+#define HC_SubA_HTXnLScale 0x0094
+#define HC_SubA_HTXSMD 0x0000
+/* HC_SubA_HTXnL012BasH 0x0020
+ */
+#define HC_HTXnL0BasH_MASK 0x000000ff
+#define HC_HTXnL1BasH_MASK 0x0000ff00
+#define HC_HTXnL2BasH_MASK 0x00ff0000
+#define HC_HTXnL1BasH_SHIFT 8
+#define HC_HTXnL2BasH_SHIFT 16
+/* HC_SubA_HTXnL345BasH 0x0021
+ */
+#define HC_HTXnL3BasH_MASK 0x000000ff
+#define HC_HTXnL4BasH_MASK 0x0000ff00
+#define HC_HTXnL5BasH_MASK 0x00ff0000
+#define HC_HTXnL4BasH_SHIFT 8
+#define HC_HTXnL5BasH_SHIFT 16
+/* HC_SubA_HTXnL678BasH 0x0022
+ */
+#define HC_HTXnL6BasH_MASK 0x000000ff
+#define HC_HTXnL7BasH_MASK 0x0000ff00
+#define HC_HTXnL8BasH_MASK 0x00ff0000
+#define HC_HTXnL7BasH_SHIFT 8
+#define HC_HTXnL8BasH_SHIFT 16
+/* HC_SubA_HTXnL9abBasH 0x0023
+ */
+#define HC_HTXnL9BasH_MASK 0x000000ff
+#define HC_HTXnLaBasH_MASK 0x0000ff00
+#define HC_HTXnLbBasH_MASK 0x00ff0000
+#define HC_HTXnLaBasH_SHIFT 8
+#define HC_HTXnLbBasH_SHIFT 16
+/* HC_SubA_HTXnLcdeBasH 0x0024
+ */
+#define HC_HTXnLcBasH_MASK 0x000000ff
+#define HC_HTXnLdBasH_MASK 0x0000ff00
+#define HC_HTXnLeBasH_MASK 0x00ff0000
+#define HC_HTXnLdBasH_SHIFT 8
+#define HC_HTXnLeBasH_SHIFT 16
+/* HC_SubA_HTXnLcdeBasH 0x0025
+ */
+#define HC_HTXnLfBasH_MASK 0x000000ff
+#define HC_HTXnL10BasH_MASK 0x0000ff00
+#define HC_HTXnL11BasH_MASK 0x00ff0000
+#define HC_HTXnL10BasH_SHIFT 8
+#define HC_HTXnL11BasH_SHIFT 16
+/* HC_SubA_HTXnL0Pit 0x002b
+ */
+#define HC_HTXnLnPit_MASK 0x00003fff
+#define HC_HTXnEnPit_MASK 0x00080000
+#define HC_HTXnLnPitE_MASK 0x00f00000
+#define HC_HTXnLnPitE_SHIFT 20
+/* HC_SubA_HTXnL0_5WE 0x004b
+ */
+#define HC_HTXnL0WE_MASK 0x0000000f
+#define HC_HTXnL1WE_MASK 0x000000f0
+#define HC_HTXnL2WE_MASK 0x00000f00
+#define HC_HTXnL3WE_MASK 0x0000f000
+#define HC_HTXnL4WE_MASK 0x000f0000
+#define HC_HTXnL5WE_MASK 0x00f00000
+#define HC_HTXnL1WE_SHIFT 4
+#define HC_HTXnL2WE_SHIFT 8
+#define HC_HTXnL3WE_SHIFT 12
+#define HC_HTXnL4WE_SHIFT 16
+#define HC_HTXnL5WE_SHIFT 20
+/* HC_SubA_HTXnL6_bWE 0x004c
+ */
+#define HC_HTXnL6WE_MASK 0x0000000f
+#define HC_HTXnL7WE_MASK 0x000000f0
+#define HC_HTXnL8WE_MASK 0x00000f00
+#define HC_HTXnL9WE_MASK 0x0000f000
+#define HC_HTXnLaWE_MASK 0x000f0000
+#define HC_HTXnLbWE_MASK 0x00f00000
+#define HC_HTXnL7WE_SHIFT 4
+#define HC_HTXnL8WE_SHIFT 8
+#define HC_HTXnL9WE_SHIFT 12
+#define HC_HTXnLaWE_SHIFT 16
+#define HC_HTXnLbWE_SHIFT 20
+/* HC_SubA_HTXnLc_11WE 0x004d
+ */
+#define HC_HTXnLcWE_MASK 0x0000000f
+#define HC_HTXnLdWE_MASK 0x000000f0
+#define HC_HTXnLeWE_MASK 0x00000f00
+#define HC_HTXnLfWE_MASK 0x0000f000
+#define HC_HTXnL10WE_MASK 0x000f0000
+#define HC_HTXnL11WE_MASK 0x00f00000
+#define HC_HTXnLdWE_SHIFT 4
+#define HC_HTXnLeWE_SHIFT 8
+#define HC_HTXnLfWE_SHIFT 12
+#define HC_HTXnL10WE_SHIFT 16
+#define HC_HTXnL11WE_SHIFT 20
+/* HC_SubA_HTXnL0_5HE 0x0051
+ */
+#define HC_HTXnL0HE_MASK 0x0000000f
+#define HC_HTXnL1HE_MASK 0x000000f0
+#define HC_HTXnL2HE_MASK 0x00000f00
+#define HC_HTXnL3HE_MASK 0x0000f000
+#define HC_HTXnL4HE_MASK 0x000f0000
+#define HC_HTXnL5HE_MASK 0x00f00000
+#define HC_HTXnL1HE_SHIFT 4
+#define HC_HTXnL2HE_SHIFT 8
+#define HC_HTXnL3HE_SHIFT 12
+#define HC_HTXnL4HE_SHIFT 16
+#define HC_HTXnL5HE_SHIFT 20
+/* HC_SubA_HTXnL6_bHE 0x0052
+ */
+#define HC_HTXnL6HE_MASK 0x0000000f
+#define HC_HTXnL7HE_MASK 0x000000f0
+#define HC_HTXnL8HE_MASK 0x00000f00
+#define HC_HTXnL9HE_MASK 0x0000f000
+#define HC_HTXnLaHE_MASK 0x000f0000
+#define HC_HTXnLbHE_MASK 0x00f00000
+#define HC_HTXnL7HE_SHIFT 4
+#define HC_HTXnL8HE_SHIFT 8
+#define HC_HTXnL9HE_SHIFT 12
+#define HC_HTXnLaHE_SHIFT 16
+#define HC_HTXnLbHE_SHIFT 20
+/* HC_SubA_HTXnLc_11HE 0x0053
+ */
+#define HC_HTXnLcHE_MASK 0x0000000f
+#define HC_HTXnLdHE_MASK 0x000000f0
+#define HC_HTXnLeHE_MASK 0x00000f00
+#define HC_HTXnLfHE_MASK 0x0000f000
+#define HC_HTXnL10HE_MASK 0x000f0000
+#define HC_HTXnL11HE_MASK 0x00f00000
+#define HC_HTXnLdHE_SHIFT 4
+#define HC_HTXnLeHE_SHIFT 8
+#define HC_HTXnLfHE_SHIFT 12
+#define HC_HTXnL10HE_SHIFT 16
+#define HC_HTXnL11HE_SHIFT 20
+/* HC_SubA_HTXnL0OS 0x0077
+ */
+#define HC_HTXnL0OS_MASK 0x003ff000
+#define HC_HTXnLVmax_MASK 0x00000fc0
+#define HC_HTXnLVmin_MASK 0x0000003f
+#define HC_HTXnL0OS_SHIFT 12
+#define HC_HTXnLVmax_SHIFT 6
+/* HC_SubA_HTXnTB 0x0078
+ */
+#define HC_HTXnTB_MASK 0x00f00000
+#define HC_HTXnFLSe_MASK 0x0000e000
+#define HC_HTXnFLSs_MASK 0x00001c00
+#define HC_HTXnFLTe_MASK 0x00000380
+#define HC_HTXnFLTs_MASK 0x00000070
+#define HC_HTXnFLDs_MASK 0x0000000f
+#define HC_HTXnTB_NoTB 0x00000000
+#define HC_HTXnTB_TBC_S 0x00100000
+#define HC_HTXnTB_TBC_T 0x00200000
+#define HC_HTXnTB_TB_S 0x00400000
+#define HC_HTXnTB_TB_T 0x00800000
+#define HC_HTXnFLSe_Nearest 0x00000000
+#define HC_HTXnFLSe_Linear 0x00002000
+#define HC_HTXnFLSe_NonLinear 0x00004000
+#define HC_HTXnFLSe_Sharp 0x00008000
+#define HC_HTXnFLSe_Flat_Gaussian_Cubic 0x0000c000
+#define HC_HTXnFLSs_Nearest 0x00000000
+#define HC_HTXnFLSs_Linear 0x00000400
+#define HC_HTXnFLSs_NonLinear 0x00000800
+#define HC_HTXnFLSs_Flat_Gaussian_Cubic 0x00001800
+#define HC_HTXnFLTe_Nearest 0x00000000
+#define HC_HTXnFLTe_Linear 0x00000080
+#define HC_HTXnFLTe_NonLinear 0x00000100
+#define HC_HTXnFLTe_Sharp 0x00000180
+#define HC_HTXnFLTe_Flat_Gaussian_Cubic 0x00000300
+#define HC_HTXnFLTs_Nearest 0x00000000
+#define HC_HTXnFLTs_Linear 0x00000010
+#define HC_HTXnFLTs_NonLinear 0x00000020
+#define HC_HTXnFLTs_Flat_Gaussian_Cubic 0x00000060
+#define HC_HTXnFLDs_Tex0 0x00000000
+#define HC_HTXnFLDs_Nearest 0x00000001
+#define HC_HTXnFLDs_Linear 0x00000002
+#define HC_HTXnFLDs_NonLinear 0x00000003
+#define HC_HTXnFLDs_Dither 0x00000004
+#define HC_HTXnFLDs_ConstLOD 0x00000005
+#define HC_HTXnFLDs_Ani 0x00000006
+#define HC_HTXnFLDs_AniDither 0x00000007
+/* HC_SubA_HTXnMPMD 0x0079
+ */
+#define HC_HTXnMPMD_SMASK 0x00070000
+#define HC_HTXnMPMD_TMASK 0x00380000
+#define HC_HTXnLODDTf_MASK 0x00000007
+#define HC_HTXnXY2ST_MASK 0x00000008
+#define HC_HTXnMPMD_Tsingle 0x00000000
+#define HC_HTXnMPMD_Tclamp 0x00080000
+#define HC_HTXnMPMD_Trepeat 0x00100000
+#define HC_HTXnMPMD_Tmirror 0x00180000
+#define HC_HTXnMPMD_Twrap 0x00200000
+#define HC_HTXnMPMD_Ssingle 0x00000000
+#define HC_HTXnMPMD_Sclamp 0x00010000
+#define HC_HTXnMPMD_Srepeat 0x00020000
+#define HC_HTXnMPMD_Smirror 0x00030000
+#define HC_HTXnMPMD_Swrap 0x00040000
+/* HC_SubA_HTXnCLODu 0x007a
+ */
+#define HC_HTXnCLODu_MASK 0x000ffc00
+#define HC_HTXnCLODd_MASK 0x000003ff
+#define HC_HTXnCLODu_SHIFT 10
+/* HC_SubA_HTXnFM 0x007b
+ */
+#define HC_HTXnFM_MASK 0x00ff0000
+#define HC_HTXnLoc_MASK 0x00000003
+#define HC_HTXnFM_INDEX 0x00000000
+#define HC_HTXnFM_Intensity 0x00080000
+#define HC_HTXnFM_Lum 0x00100000
+#define HC_HTXnFM_Alpha 0x00180000
+#define HC_HTXnFM_DX 0x00280000
+#define HC_HTXnFM_ARGB16 0x00880000
+#define HC_HTXnFM_ARGB32 0x00980000
+#define HC_HTXnFM_ABGR16 0x00a80000
+#define HC_HTXnFM_ABGR32 0x00b80000
+#define HC_HTXnFM_RGBA16 0x00c80000
+#define HC_HTXnFM_RGBA32 0x00d80000
+#define HC_HTXnFM_BGRA16 0x00e80000
+#define HC_HTXnFM_BGRA32 0x00f80000
+#define HC_HTXnFM_BUMPMAP 0x00380000
+#define HC_HTXnFM_Index1 (HC_HTXnFM_INDEX | 0x00000000)
+#define HC_HTXnFM_Index2 (HC_HTXnFM_INDEX | 0x00010000)
+#define HC_HTXnFM_Index4 (HC_HTXnFM_INDEX | 0x00020000)
+#define HC_HTXnFM_Index8 (HC_HTXnFM_INDEX | 0x00030000)
+#define HC_HTXnFM_T1 (HC_HTXnFM_Intensity | 0x00000000)
+#define HC_HTXnFM_T2 (HC_HTXnFM_Intensity | 0x00010000)
+#define HC_HTXnFM_T4 (HC_HTXnFM_Intensity | 0x00020000)
+#define HC_HTXnFM_T8 (HC_HTXnFM_Intensity | 0x00030000)
+#define HC_HTXnFM_L1 (HC_HTXnFM_Lum | 0x00000000)
+#define HC_HTXnFM_L2 (HC_HTXnFM_Lum | 0x00010000)
+#define HC_HTXnFM_L4 (HC_HTXnFM_Lum | 0x00020000)
+#define HC_HTXnFM_L8 (HC_HTXnFM_Lum | 0x00030000)
+#define HC_HTXnFM_AL44 (HC_HTXnFM_Lum | 0x00040000)
+#define HC_HTXnFM_AL88 (HC_HTXnFM_Lum | 0x00050000)
+#define HC_HTXnFM_A1 (HC_HTXnFM_Alpha | 0x00000000)
+#define HC_HTXnFM_A2 (HC_HTXnFM_Alpha | 0x00010000)
+#define HC_HTXnFM_A4 (HC_HTXnFM_Alpha | 0x00020000)
+#define HC_HTXnFM_A8 (HC_HTXnFM_Alpha | 0x00030000)
+#define HC_HTXnFM_DX1 (HC_HTXnFM_DX | 0x00010000)
+#define HC_HTXnFM_DX23 (HC_HTXnFM_DX | 0x00020000)
+#define HC_HTXnFM_DX45 (HC_HTXnFM_DX | 0x00030000)
+#define HC_HTXnFM_RGB555 (HC_HTXnFM_ARGB16 | 0x00000000)
+#define HC_HTXnFM_RGB565 (HC_HTXnFM_ARGB16 | 0x00010000)
+#define HC_HTXnFM_ARGB1555 (HC_HTXnFM_ARGB16 | 0x00020000)
+#define HC_HTXnFM_ARGB4444 (HC_HTXnFM_ARGB16 | 0x00030000)
+#define HC_HTXnFM_ARGB0888 (HC_HTXnFM_ARGB32 | 0x00000000)
+#define HC_HTXnFM_ARGB8888 (HC_HTXnFM_ARGB32 | 0x00010000)
+#define HC_HTXnFM_BGR555 (HC_HTXnFM_ABGR16 | 0x00000000)
+#define HC_HTXnFM_BGR565 (HC_HTXnFM_ABGR16 | 0x00010000)
+#define HC_HTXnFM_ABGR1555 (HC_HTXnFM_ABGR16 | 0x00020000)
+#define HC_HTXnFM_ABGR4444 (HC_HTXnFM_ABGR16 | 0x00030000)
+#define HC_HTXnFM_ABGR0888 (HC_HTXnFM_ABGR32 | 0x00000000)
+#define HC_HTXnFM_ABGR8888 (HC_HTXnFM_ABGR32 | 0x00010000)
+#define HC_HTXnFM_RGBA5550 (HC_HTXnFM_RGBA16 | 0x00000000)
+#define HC_HTXnFM_RGBA5551 (HC_HTXnFM_RGBA16 | 0x00020000)
+#define HC_HTXnFM_RGBA4444 (HC_HTXnFM_RGBA16 | 0x00030000)
+#define HC_HTXnFM_RGBA8880 (HC_HTXnFM_RGBA32 | 0x00000000)
+#define HC_HTXnFM_RGBA8888 (HC_HTXnFM_RGBA32 | 0x00010000)
+#define HC_HTXnFM_BGRA5550 (HC_HTXnFM_BGRA16 | 0x00000000)
+#define HC_HTXnFM_BGRA5551 (HC_HTXnFM_BGRA16 | 0x00020000)
+#define HC_HTXnFM_BGRA4444 (HC_HTXnFM_BGRA16 | 0x00030000)
+#define HC_HTXnFM_BGRA8880 (HC_HTXnFM_BGRA32 | 0x00000000)
+#define HC_HTXnFM_BGRA8888 (HC_HTXnFM_BGRA32 | 0x00010000)
+#define HC_HTXnFM_VU88 (HC_HTXnFM_BUMPMAP | 0x00000000)
+#define HC_HTXnFM_LVU655 (HC_HTXnFM_BUMPMAP | 0x00010000)
+#define HC_HTXnFM_LVU888 (HC_HTXnFM_BUMPMAP | 0x00020000)
+#define HC_HTXnLoc_Local 0x00000000
+#define HC_HTXnLoc_Sys 0x00000002
+#define HC_HTXnLoc_AGP 0x00000003
+/* HC_SubA_HTXnTRAH 0x007f
+ */
+#define HC_HTXnTRAH_MASK 0x00ff0000
+#define HC_HTXnTRAL_MASK 0x0000ff00
+#define HC_HTXnTBA_MASK 0x000000ff
+#define HC_HTXnTRAH_SHIFT 16
+#define HC_HTXnTRAL_SHIFT 8
+/* HC_SubA_HTXnTBLCsat 0x0080
+ *-- Define the input texture.
+ */
+#define HC_XTC_TOPC 0x00000000
+#define HC_XTC_InvTOPC 0x00000010
+#define HC_XTC_TOPCp5 0x00000020
+#define HC_XTC_Cbias 0x00000000
+#define HC_XTC_InvCbias 0x00000010
+#define HC_XTC_0 0x00000000
+#define HC_XTC_Dif 0x00000001
+#define HC_XTC_Spec 0x00000002
+#define HC_XTC_Tex 0x00000003
+#define HC_XTC_Cur 0x00000004
+#define HC_XTC_Adif 0x00000005
+#define HC_XTC_Fog 0x00000006
+#define HC_XTC_Atex 0x00000007
+#define HC_XTC_Acur 0x00000008
+#define HC_XTC_HTXnTBLRC 0x00000009
+#define HC_XTC_Ctexnext 0x0000000a
+/*--
+ */
+#define HC_HTXnTBLCsat_MASK 0x00800000
+#define HC_HTXnTBLCa_MASK 0x000fc000
+#define HC_HTXnTBLCb_MASK 0x00001f80
+#define HC_HTXnTBLCc_MASK 0x0000003f
+#define HC_HTXnTBLCa_TOPC (HC_XTC_TOPC << 14)
+#define HC_HTXnTBLCa_InvTOPC (HC_XTC_InvTOPC << 14)
+#define HC_HTXnTBLCa_TOPCp5 (HC_XTC_TOPCp5 << 14)
+#define HC_HTXnTBLCa_0 (HC_XTC_0 << 14)
+#define HC_HTXnTBLCa_Dif (HC_XTC_Dif << 14)
+#define HC_HTXnTBLCa_Spec (HC_XTC_Spec << 14)
+#define HC_HTXnTBLCa_Tex (HC_XTC_Tex << 14)
+#define HC_HTXnTBLCa_Cur (HC_XTC_Cur << 14)
+#define HC_HTXnTBLCa_Adif (HC_XTC_Adif << 14)
+#define HC_HTXnTBLCa_Fog (HC_XTC_Fog << 14)
+#define HC_HTXnTBLCa_Atex (HC_XTC_Atex << 14)
+#define HC_HTXnTBLCa_Acur (HC_XTC_Acur << 14)
+#define HC_HTXnTBLCa_HTXnTBLRC (HC_XTC_HTXnTBLRC << 14)
+#define HC_HTXnTBLCa_Ctexnext (HC_XTC_Ctexnext << 14)
+#define HC_HTXnTBLCb_TOPC (HC_XTC_TOPC << 7)
+#define HC_HTXnTBLCb_InvTOPC (HC_XTC_InvTOPC << 7)
+#define HC_HTXnTBLCb_TOPCp5 (HC_XTC_TOPCp5 << 7)
+#define HC_HTXnTBLCb_0 (HC_XTC_0 << 7)
+#define HC_HTXnTBLCb_Dif (HC_XTC_Dif << 7)
+#define HC_HTXnTBLCb_Spec (HC_XTC_Spec << 7)
+#define HC_HTXnTBLCb_Tex (HC_XTC_Tex << 7)
+#define HC_HTXnTBLCb_Cur (HC_XTC_Cur << 7)
+#define HC_HTXnTBLCb_Adif (HC_XTC_Adif << 7)
+#define HC_HTXnTBLCb_Fog (HC_XTC_Fog << 7)
+#define HC_HTXnTBLCb_Atex (HC_XTC_Atex << 7)
+#define HC_HTXnTBLCb_Acur (HC_XTC_Acur << 7)
+#define HC_HTXnTBLCb_HTXnTBLRC (HC_XTC_HTXnTBLRC << 7)
+#define HC_HTXnTBLCb_Ctexnext (HC_XTC_Ctexnext << 7)
+#define HC_HTXnTBLCc_TOPC (HC_XTC_TOPC << 0)
+#define HC_HTXnTBLCc_InvTOPC (HC_XTC_InvTOPC << 0)
+#define HC_HTXnTBLCc_TOPCp5 (HC_XTC_TOPCp5 << 0)
+#define HC_HTXnTBLCc_0 (HC_XTC_0 << 0)
+#define HC_HTXnTBLCc_Dif (HC_XTC_Dif << 0)
+#define HC_HTXnTBLCc_Spec (HC_XTC_Spec << 0)
+#define HC_HTXnTBLCc_Tex (HC_XTC_Tex << 0)
+#define HC_HTXnTBLCc_Cur (HC_XTC_Cur << 0)
+#define HC_HTXnTBLCc_Adif (HC_XTC_Adif << 0)
+#define HC_HTXnTBLCc_Fog (HC_XTC_Fog << 0)
+#define HC_HTXnTBLCc_Atex (HC_XTC_Atex << 0)
+#define HC_HTXnTBLCc_Acur (HC_XTC_Acur << 0)
+#define HC_HTXnTBLCc_HTXnTBLRC (HC_XTC_HTXnTBLRC << 0)
+#define HC_HTXnTBLCc_Ctexnext (HC_XTC_Ctexnext << 0)
+/* HC_SubA_HTXnTBLCop 0x0081
+ */
+#define HC_HTXnTBLdot_MASK 0x00c00000
+#define HC_HTXnTBLCop_MASK 0x00380000
+#define HC_HTXnTBLCbias_MASK 0x0007c000
+#define HC_HTXnTBLCshift_MASK 0x00001800
+#define HC_HTXnTBLAop_MASK 0x00000380
+#define HC_HTXnTBLAbias_MASK 0x00000078
+#define HC_HTXnTBLAshift_MASK 0x00000003
+#define HC_HTXnTBLCop_Add 0x00000000
+#define HC_HTXnTBLCop_Sub 0x00080000
+#define HC_HTXnTBLCop_Min 0x00100000
+#define HC_HTXnTBLCop_Max 0x00180000
+#define HC_HTXnTBLCop_Mask 0x00200000
+#define HC_HTXnTBLCbias_Cbias (HC_XTC_Cbias << 14)
+#define HC_HTXnTBLCbias_InvCbias (HC_XTC_InvCbias << 14)
+#define HC_HTXnTBLCbias_0 (HC_XTC_0 << 14)
+#define HC_HTXnTBLCbias_Dif (HC_XTC_Dif << 14)
+#define HC_HTXnTBLCbias_Spec (HC_XTC_Spec << 14)
+#define HC_HTXnTBLCbias_Tex (HC_XTC_Tex << 14)
+#define HC_HTXnTBLCbias_Cur (HC_XTC_Cur << 14)
+#define HC_HTXnTBLCbias_Adif (HC_XTC_Adif << 14)
+#define HC_HTXnTBLCbias_Fog (HC_XTC_Fog << 14)
+#define HC_HTXnTBLCbias_Atex (HC_XTC_Atex << 14)
+#define HC_HTXnTBLCbias_Acur (HC_XTC_Acur << 14)
+#define HC_HTXnTBLCbias_HTXnTBLRC (HC_XTC_HTXnTBLRC << 14)
+#define HC_HTXnTBLCshift_1 0x00000000
+#define HC_HTXnTBLCshift_2 0x00000800
+#define HC_HTXnTBLCshift_No 0x00001000
+#define HC_HTXnTBLCshift_DotP 0x00001800
+/*=* John Sheng [2003.7.18] texture combine *=*/
+#define HC_HTXnTBLDOT3 0x00080000
+#define HC_HTXnTBLDOT4 0x000C0000
+
+#define HC_HTXnTBLAop_Add 0x00000000
+#define HC_HTXnTBLAop_Sub 0x00000080
+#define HC_HTXnTBLAop_Min 0x00000100
+#define HC_HTXnTBLAop_Max 0x00000180
+#define HC_HTXnTBLAop_Mask 0x00000200
+#define HC_HTXnTBLAbias_Inv 0x00000040
+#define HC_HTXnTBLAbias_Adif 0x00000000
+#define HC_HTXnTBLAbias_Fog 0x00000008
+#define HC_HTXnTBLAbias_Acur 0x00000010
+#define HC_HTXnTBLAbias_HTXnTBLRAbias 0x00000018
+#define HC_HTXnTBLAbias_Atex 0x00000020
+#define HC_HTXnTBLAshift_1 0x00000000
+#define HC_HTXnTBLAshift_2 0x00000001
+#define HC_HTXnTBLAshift_No 0x00000002
+/* #define HC_HTXnTBLAshift_DotP 0x00000003 */
+/* HC_SubA_HTXnTBLMPFog 0x0082
+ */
+#define HC_HTXnTBLMPfog_MASK 0x00e00000
+#define HC_HTXnTBLMPfog_0 0x00000000
+#define HC_HTXnTBLMPfog_Adif 0x00200000
+#define HC_HTXnTBLMPfog_Fog 0x00400000
+#define HC_HTXnTBLMPfog_Atex 0x00600000
+#define HC_HTXnTBLMPfog_Acur 0x00800000
+#define HC_HTXnTBLMPfog_GHTXnTBLRFog 0x00a00000
+/* HC_SubA_HTXnTBLAsat 0x0083
+ *-- Define the texture alpha input.
+ */
+#define HC_XTA_TOPA 0x00000000
+#define HC_XTA_InvTOPA 0x00000008
+#define HC_XTA_TOPAp5 0x00000010
+#define HC_XTA_Adif 0x00000000
+#define HC_XTA_Fog 0x00000001
+#define HC_XTA_Acur 0x00000002
+#define HC_XTA_HTXnTBLRA 0x00000003
+#define HC_XTA_Atex 0x00000004
+#define HC_XTA_Atexnext 0x00000005
+/*--
+ */
+#define HC_HTXnTBLAsat_MASK 0x00800000
+#define HC_HTXnTBLAMB_MASK 0x00700000
+#define HC_HTXnTBLAa_MASK 0x0007c000
+#define HC_HTXnTBLAb_MASK 0x00000f80
+#define HC_HTXnTBLAc_MASK 0x0000001f
+#define HC_HTXnTBLAMB_SHIFT 20
+#define HC_HTXnTBLAa_TOPA (HC_XTA_TOPA << 14)
+#define HC_HTXnTBLAa_InvTOPA (HC_XTA_InvTOPA << 14)
+#define HC_HTXnTBLAa_TOPAp5 (HC_XTA_TOPAp5 << 14)
+#define HC_HTXnTBLAa_Adif (HC_XTA_Adif << 14)
+#define HC_HTXnTBLAa_Fog (HC_XTA_Fog << 14)
+#define HC_HTXnTBLAa_Acur (HC_XTA_Acur << 14)
+#define HC_HTXnTBLAa_HTXnTBLRA (HC_XTA_HTXnTBLRA << 14)
+#define HC_HTXnTBLAa_Atex (HC_XTA_Atex << 14)
+#define HC_HTXnTBLAa_Atexnext (HC_XTA_Atexnext << 14)
+#define HC_HTXnTBLAb_TOPA (HC_XTA_TOPA << 7)
+#define HC_HTXnTBLAb_InvTOPA (HC_XTA_InvTOPA << 7)
+#define HC_HTXnTBLAb_TOPAp5 (HC_XTA_TOPAp5 << 7)
+#define HC_HTXnTBLAb_Adif (HC_XTA_Adif << 7)
+#define HC_HTXnTBLAb_Fog (HC_XTA_Fog << 7)
+#define HC_HTXnTBLAb_Acur (HC_XTA_Acur << 7)
+#define HC_HTXnTBLAb_HTXnTBLRA (HC_XTA_HTXnTBLRA << 7)
+#define HC_HTXnTBLAb_Atex (HC_XTA_Atex << 7)
+#define HC_HTXnTBLAb_Atexnext (HC_XTA_Atexnext << 7)
+#define HC_HTXnTBLAc_TOPA (HC_XTA_TOPA << 0)
+#define HC_HTXnTBLAc_InvTOPA (HC_XTA_InvTOPA << 0)
+#define HC_HTXnTBLAc_TOPAp5 (HC_XTA_TOPAp5 << 0)
+#define HC_HTXnTBLAc_Adif (HC_XTA_Adif << 0)
+#define HC_HTXnTBLAc_Fog (HC_XTA_Fog << 0)
+#define HC_HTXnTBLAc_Acur (HC_XTA_Acur << 0)
+#define HC_HTXnTBLAc_HTXnTBLRA (HC_XTA_HTXnTBLRA << 0)
+#define HC_HTXnTBLAc_Atex (HC_XTA_Atex << 0)
+#define HC_HTXnTBLAc_Atexnext (HC_XTA_Atexnext << 0)
+/* HC_SubA_HTXnTBLRAa 0x0089
+ */
+#define HC_HTXnTBLRAa_MASK 0x00ff0000
+#define HC_HTXnTBLRAb_MASK 0x0000ff00
+#define HC_HTXnTBLRAc_MASK 0x000000ff
+#define HC_HTXnTBLRAa_SHIFT 16
+#define HC_HTXnTBLRAb_SHIFT 8
+#define HC_HTXnTBLRAc_SHIFT 0
+/* HC_SubA_HTXnTBLRFog 0x008a
+ */
+#define HC_HTXnTBLRFog_MASK 0x0000ff00
+#define HC_HTXnTBLRAbias_MASK 0x000000ff
+#define HC_HTXnTBLRFog_SHIFT 8
+#define HC_HTXnTBLRAbias_SHIFT 0
+/* HC_SubA_HTXnLScale 0x0094
+ */
+#define HC_HTXnLScale_MASK 0x0007fc00
+#define HC_HTXnLOff_MASK 0x000001ff
+#define HC_HTXnLScale_SHIFT 10
+/* HC_SubA_HTXSMD 0x0000
+ */
+#define HC_HTXSMD_MASK 0x00000080
+#define HC_HTXTMD_MASK 0x00000040
+#define HC_HTXNum_MASK 0x00000038
+#define HC_HTXTRMD_MASK 0x00000006
+#define HC_HTXCHCLR_MASK 0x00000001
+#define HC_HTXNum_SHIFT 3
+
+/* Texture Palette n
+ */
+#define HC_SubType_TexPalette0 0x00000000
+#define HC_SubType_TexPalette1 0x00000001
+#define HC_SubType_FogTable 0x00000010
+#define HC_SubType_Stipple 0x00000014
+/* HC_SubA_TexPalette0 0x0000
+ */
+#define HC_HTPnA_MASK 0xff000000
+#define HC_HTPnR_MASK 0x00ff0000
+#define HC_HTPnG_MASK 0x0000ff00
+#define HC_HTPnB_MASK 0x000000ff
+/* HC_SubA_FogTable 0x0010
+ */
+#define HC_HFPn3_MASK 0xff000000
+#define HC_HFPn2_MASK 0x00ff0000
+#define HC_HFPn1_MASK 0x0000ff00
+#define HC_HFPn_MASK 0x000000ff
+#define HC_HFPn3_SHIFT 24
+#define HC_HFPn2_SHIFT 16
+#define HC_HFPn1_SHIFT 8
+
+/* Auto Testing & Security
+ */
+#define HC_SubA_HenFIFOAT 0x0000
+#define HC_SubA_HFBDrawFirst 0x0004
+#define HC_SubA_HFBBasL 0x0005
+#define HC_SubA_HFBDst 0x0006
+/* HC_SubA_HenFIFOAT 0x0000
+ */
+#define HC_HenFIFOAT_MASK 0x00000020
+#define HC_HenGEMILock_MASK 0x00000010
+#define HC_HenFBASwap_MASK 0x00000008
+#define HC_HenOT_MASK 0x00000004
+#define HC_HenCMDQ_MASK 0x00000002
+#define HC_HenTXCTSU_MASK 0x00000001
+/* HC_SubA_HFBDrawFirst 0x0004
+ */
+#define HC_HFBDrawFirst_MASK 0x00000800
+#define HC_HFBQueue_MASK 0x00000400
+#define HC_HFBLock_MASK 0x00000200
+#define HC_HEOF_MASK 0x00000100
+#define HC_HFBBasH_MASK 0x000000ff
+
+/* GEMI Setting
+ */
+#define HC_SubA_HTArbRCM 0x0008
+#define HC_SubA_HTArbRZ 0x000a
+#define HC_SubA_HTArbWZ 0x000b
+#define HC_SubA_HTArbRTX 0x000c
+#define HC_SubA_HTArbRCW 0x000d
+#define HC_SubA_HTArbE2 0x000e
+#define HC_SubA_HArbRQCM 0x0010
+#define HC_SubA_HArbWQCM 0x0011
+#define HC_SubA_HGEMITout 0x0020
+#define HC_SubA_HFthRTXD 0x0040
+#define HC_SubA_HFthRTXA 0x0044
+#define HC_SubA_HCMDQstL 0x0050
+#define HC_SubA_HCMDQendL 0x0051
+#define HC_SubA_HCMDQLen 0x0052
+/* HC_SubA_HTArbRCM 0x0008
+ */
+#define HC_HTArbRCM_MASK 0x0000ffff
+/* HC_SubA_HTArbRZ 0x000a
+ */
+#define HC_HTArbRZ_MASK 0x0000ffff
+/* HC_SubA_HTArbWZ 0x000b
+ */
+#define HC_HTArbWZ_MASK 0x0000ffff
+/* HC_SubA_HTArbRTX 0x000c
+ */
+#define HC_HTArbRTX_MASK 0x0000ffff
+/* HC_SubA_HTArbRCW 0x000d
+ */
+#define HC_HTArbRCW_MASK 0x0000ffff
+/* HC_SubA_HTArbE2 0x000e
+ */
+#define HC_HTArbE2_MASK 0x0000ffff
+/* HC_SubA_HArbRQCM 0x0010
+ */
+#define HC_HTArbRQCM_MASK 0x0000ffff
+/* HC_SubA_HArbWQCM 0x0011
+ */
+#define HC_HArbWQCM_MASK 0x0000ffff
+/* HC_SubA_HGEMITout 0x0020
+ */
+#define HC_HGEMITout_MASK 0x000f0000
+#define HC_HNPArbZC_MASK 0x0000ffff
+#define HC_HGEMITout_SHIFT 16
+/* HC_SubA_HFthRTXD 0x0040
+ */
+#define HC_HFthRTXD_MASK 0x00ff0000
+#define HC_HFthRZD_MASK 0x0000ff00
+#define HC_HFthWZD_MASK 0x000000ff
+#define HC_HFthRTXD_SHIFT 16
+#define HC_HFthRZD_SHIFT 8
+/* HC_SubA_HFthRTXA 0x0044
+ */
+#define HC_HFthRTXA_MASK 0x000000ff
+
+/******************************************************************************
+** Define the Halcyon Internal register access constants. For simulator only.
+******************************************************************************/
+#define HC_SIMA_HAGPBstL 0x0000
+#define HC_SIMA_HAGPBendL 0x0001
+#define HC_SIMA_HAGPCMNT 0x0002
+#define HC_SIMA_HAGPBpL 0x0003
+#define HC_SIMA_HAGPBpH 0x0004
+#define HC_SIMA_HClipTB 0x0005
+#define HC_SIMA_HClipLR 0x0006
+#define HC_SIMA_HFPClipTL 0x0007
+#define HC_SIMA_HFPClipBL 0x0008
+#define HC_SIMA_HFPClipLL 0x0009
+#define HC_SIMA_HFPClipRL 0x000a
+#define HC_SIMA_HFPClipTBH 0x000b
+#define HC_SIMA_HFPClipLRH 0x000c
+#define HC_SIMA_HLP 0x000d
+#define HC_SIMA_HLPRF 0x000e
+#define HC_SIMA_HSolidCL 0x000f
+#define HC_SIMA_HPixGC 0x0010
+#define HC_SIMA_HSPXYOS 0x0011
+#define HC_SIMA_HCmdA 0x0012
+#define HC_SIMA_HCmdB 0x0013
+#define HC_SIMA_HEnable 0x0014
+#define HC_SIMA_HZWBBasL 0x0015
+#define HC_SIMA_HZWBBasH 0x0016
+#define HC_SIMA_HZWBType 0x0017
+#define HC_SIMA_HZBiasL 0x0018
+#define HC_SIMA_HZWBend 0x0019
+#define HC_SIMA_HZWTMD 0x001a
+#define HC_SIMA_HZWCDL 0x001b
+#define HC_SIMA_HZWCTAGnum 0x001c
+#define HC_SIMA_HZCYNum 0x001d
+#define HC_SIMA_HZWCFire 0x001e
+/* #define HC_SIMA_HSBBasL 0x001d */
+/* #define HC_SIMA_HSBBasH 0x001e */
+/* #define HC_SIMA_HSBFM 0x001f */
+#define HC_SIMA_HSTREF 0x0020
+#define HC_SIMA_HSTMD 0x0021
+#define HC_SIMA_HABBasL 0x0022
+#define HC_SIMA_HABBasH 0x0023
+#define HC_SIMA_HABFM 0x0024
+#define HC_SIMA_HATMD 0x0025
+#define HC_SIMA_HABLCsat 0x0026
+#define HC_SIMA_HABLCop 0x0027
+#define HC_SIMA_HABLAsat 0x0028
+#define HC_SIMA_HABLAop 0x0029
+#define HC_SIMA_HABLRCa 0x002a
+#define HC_SIMA_HABLRFCa 0x002b
+#define HC_SIMA_HABLRCbias 0x002c
+#define HC_SIMA_HABLRCb 0x002d
+#define HC_SIMA_HABLRFCb 0x002e
+#define HC_SIMA_HABLRAa 0x002f
+#define HC_SIMA_HABLRAb 0x0030
+#define HC_SIMA_HDBBasL 0x0031
+#define HC_SIMA_HDBBasH 0x0032
+#define HC_SIMA_HDBFM 0x0033
+#define HC_SIMA_HFBBMSKL 0x0034
+#define HC_SIMA_HROP 0x0035
+#define HC_SIMA_HFogLF 0x0036
+#define HC_SIMA_HFogCL 0x0037
+#define HC_SIMA_HFogCH 0x0038
+#define HC_SIMA_HFogStL 0x0039
+#define HC_SIMA_HFogStH 0x003a
+#define HC_SIMA_HFogOOdMF 0x003b
+#define HC_SIMA_HFogOOdEF 0x003c
+#define HC_SIMA_HFogEndL 0x003d
+#define HC_SIMA_HFogDenst 0x003e
+/*---- start of texture 0 setting ----
+ */
+#define HC_SIMA_HTX0L0BasL 0x0040
+#define HC_SIMA_HTX0L1BasL 0x0041
+#define HC_SIMA_HTX0L2BasL 0x0042
+#define HC_SIMA_HTX0L3BasL 0x0043
+#define HC_SIMA_HTX0L4BasL 0x0044
+#define HC_SIMA_HTX0L5BasL 0x0045
+#define HC_SIMA_HTX0L6BasL 0x0046
+#define HC_SIMA_HTX0L7BasL 0x0047
+#define HC_SIMA_HTX0L8BasL 0x0048
+#define HC_SIMA_HTX0L9BasL 0x0049
+#define HC_SIMA_HTX0LaBasL 0x004a
+#define HC_SIMA_HTX0LbBasL 0x004b
+#define HC_SIMA_HTX0LcBasL 0x004c
+#define HC_SIMA_HTX0LdBasL 0x004d
+#define HC_SIMA_HTX0LeBasL 0x004e
+#define HC_SIMA_HTX0LfBasL 0x004f
+#define HC_SIMA_HTX0L10BasL 0x0050
+#define HC_SIMA_HTX0L11BasL 0x0051
+#define HC_SIMA_HTX0L012BasH 0x0052
+#define HC_SIMA_HTX0L345BasH 0x0053
+#define HC_SIMA_HTX0L678BasH 0x0054
+#define HC_SIMA_HTX0L9abBasH 0x0055
+#define HC_SIMA_HTX0LcdeBasH 0x0056
+#define HC_SIMA_HTX0Lf1011BasH 0x0057
+#define HC_SIMA_HTX0L0Pit 0x0058
+#define HC_SIMA_HTX0L1Pit 0x0059
+#define HC_SIMA_HTX0L2Pit 0x005a
+#define HC_SIMA_HTX0L3Pit 0x005b
+#define HC_SIMA_HTX0L4Pit 0x005c
+#define HC_SIMA_HTX0L5Pit 0x005d
+#define HC_SIMA_HTX0L6Pit 0x005e
+#define HC_SIMA_HTX0L7Pit 0x005f
+#define HC_SIMA_HTX0L8Pit 0x0060
+#define HC_SIMA_HTX0L9Pit 0x0061
+#define HC_SIMA_HTX0LaPit 0x0062
+#define HC_SIMA_HTX0LbPit 0x0063
+#define HC_SIMA_HTX0LcPit 0x0064
+#define HC_SIMA_HTX0LdPit 0x0065
+#define HC_SIMA_HTX0LePit 0x0066
+#define HC_SIMA_HTX0LfPit 0x0067
+#define HC_SIMA_HTX0L10Pit 0x0068
+#define HC_SIMA_HTX0L11Pit 0x0069
+#define HC_SIMA_HTX0L0_5WE 0x006a
+#define HC_SIMA_HTX0L6_bWE 0x006b
+#define HC_SIMA_HTX0Lc_11WE 0x006c
+#define HC_SIMA_HTX0L0_5HE 0x006d
+#define HC_SIMA_HTX0L6_bHE 0x006e
+#define HC_SIMA_HTX0Lc_11HE 0x006f
+#define HC_SIMA_HTX0L0OS 0x0070
+#define HC_SIMA_HTX0TB 0x0071
+#define HC_SIMA_HTX0MPMD 0x0072
+#define HC_SIMA_HTX0CLODu 0x0073
+#define HC_SIMA_HTX0FM 0x0074
+#define HC_SIMA_HTX0TRCH 0x0075
+#define HC_SIMA_HTX0TRCL 0x0076
+#define HC_SIMA_HTX0TBC 0x0077
+#define HC_SIMA_HTX0TRAH 0x0078
+#define HC_SIMA_HTX0TBLCsat 0x0079
+#define HC_SIMA_HTX0TBLCop 0x007a
+#define HC_SIMA_HTX0TBLMPfog 0x007b
+#define HC_SIMA_HTX0TBLAsat 0x007c
+#define HC_SIMA_HTX0TBLRCa 0x007d
+#define HC_SIMA_HTX0TBLRCb 0x007e
+#define HC_SIMA_HTX0TBLRCc 0x007f
+#define HC_SIMA_HTX0TBLRCbias 0x0080
+#define HC_SIMA_HTX0TBLRAa 0x0081
+#define HC_SIMA_HTX0TBLRFog 0x0082
+#define HC_SIMA_HTX0BumpM00 0x0083
+#define HC_SIMA_HTX0BumpM01 0x0084
+#define HC_SIMA_HTX0BumpM10 0x0085
+#define HC_SIMA_HTX0BumpM11 0x0086
+#define HC_SIMA_HTX0LScale 0x0087
+/*---- end of texture 0 setting ---- 0x008f
+ */
+#define HC_SIMA_TX0TX1_OFF 0x0050
+/*---- start of texture 1 setting ----
+ */
+#define HC_SIMA_HTX1L0BasL (HC_SIMA_HTX0L0BasL + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L1BasL (HC_SIMA_HTX0L1BasL + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L2BasL (HC_SIMA_HTX0L2BasL + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L3BasL (HC_SIMA_HTX0L3BasL + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L4BasL (HC_SIMA_HTX0L4BasL + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L5BasL (HC_SIMA_HTX0L5BasL + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L6BasL (HC_SIMA_HTX0L6BasL + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L7BasL (HC_SIMA_HTX0L7BasL + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L8BasL (HC_SIMA_HTX0L8BasL + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L9BasL (HC_SIMA_HTX0L9BasL + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1LaBasL (HC_SIMA_HTX0LaBasL + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1LbBasL (HC_SIMA_HTX0LbBasL + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1LcBasL (HC_SIMA_HTX0LcBasL + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1LdBasL (HC_SIMA_HTX0LdBasL + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1LeBasL (HC_SIMA_HTX0LeBasL + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1LfBasL (HC_SIMA_HTX0LfBasL + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L10BasL (HC_SIMA_HTX0L10BasL + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L11BasL (HC_SIMA_HTX0L11BasL + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L012BasH (HC_SIMA_HTX0L012BasH + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L345BasH (HC_SIMA_HTX0L345BasH + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L678BasH (HC_SIMA_HTX0L678BasH + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L9abBasH (HC_SIMA_HTX0L9abBasH + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1LcdeBasH (HC_SIMA_HTX0LcdeBasH + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1Lf1011BasH (HC_SIMA_HTX0Lf1011BasH + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L0Pit (HC_SIMA_HTX0L0Pit + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L1Pit (HC_SIMA_HTX0L1Pit + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L2Pit (HC_SIMA_HTX0L2Pit + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L3Pit (HC_SIMA_HTX0L3Pit + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L4Pit (HC_SIMA_HTX0L4Pit + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L5Pit (HC_SIMA_HTX0L5Pit + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L6Pit (HC_SIMA_HTX0L6Pit + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L7Pit (HC_SIMA_HTX0L7Pit + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L8Pit (HC_SIMA_HTX0L8Pit + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L9Pit (HC_SIMA_HTX0L9Pit + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1LaPit (HC_SIMA_HTX0LaPit + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1LbPit (HC_SIMA_HTX0LbPit + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1LcPit (HC_SIMA_HTX0LcPit + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1LdPit (HC_SIMA_HTX0LdPit + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1LePit (HC_SIMA_HTX0LePit + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1LfPit (HC_SIMA_HTX0LfPit + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L10Pit (HC_SIMA_HTX0L10Pit + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L11Pit (HC_SIMA_HTX0L11Pit + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L0_5WE (HC_SIMA_HTX0L0_5WE + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L6_bWE (HC_SIMA_HTX0L6_bWE + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1Lc_11WE (HC_SIMA_HTX0Lc_11WE + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L0_5HE (HC_SIMA_HTX0L0_5HE + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L6_bHE (HC_SIMA_HTX0L6_bHE + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1Lc_11HE (HC_SIMA_HTX0Lc_11HE + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L0OS (HC_SIMA_HTX0L0OS + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1TB (HC_SIMA_HTX0TB + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1MPMD (HC_SIMA_HTX0MPMD + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1CLODu (HC_SIMA_HTX0CLODu + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1FM (HC_SIMA_HTX0FM + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1TRCH (HC_SIMA_HTX0TRCH + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1TRCL (HC_SIMA_HTX0TRCL + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1TBC (HC_SIMA_HTX0TBC + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1TRAH (HC_SIMA_HTX0TRAH + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1LTC (HC_SIMA_HTX0LTC + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1LTA (HC_SIMA_HTX0LTA + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1TBLCsat (HC_SIMA_HTX0TBLCsat + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1TBLCop (HC_SIMA_HTX0TBLCop + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1TBLMPfog (HC_SIMA_HTX0TBLMPfog + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1TBLAsat (HC_SIMA_HTX0TBLAsat + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1TBLRCa (HC_SIMA_HTX0TBLRCa + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1TBLRCb (HC_SIMA_HTX0TBLRCb + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1TBLRCc (HC_SIMA_HTX0TBLRCc + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1TBLRCbias (HC_SIMA_HTX0TBLRCbias + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1TBLRAa (HC_SIMA_HTX0TBLRAa + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1TBLRFog (HC_SIMA_HTX0TBLRFog + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1BumpM00 (HC_SIMA_HTX0BumpM00 + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1BumpM01 (HC_SIMA_HTX0BumpM01 + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1BumpM10 (HC_SIMA_HTX0BumpM10 + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1BumpM11 (HC_SIMA_HTX0BumpM11 + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1LScale (HC_SIMA_HTX0LScale + HC_SIMA_TX0TX1_OFF)
+/*---- end of texture 1 setting ---- 0xaf
+ */
+#define HC_SIMA_HTXSMD 0x00b0
+#define HC_SIMA_HenFIFOAT 0x00b1
+#define HC_SIMA_HFBDrawFirst 0x00b2
+#define HC_SIMA_HFBBasL 0x00b3
+#define HC_SIMA_HTArbRCM 0x00b4
+#define HC_SIMA_HTArbRZ 0x00b5
+#define HC_SIMA_HTArbWZ 0x00b6
+#define HC_SIMA_HTArbRTX 0x00b7
+#define HC_SIMA_HTArbRCW 0x00b8
+#define HC_SIMA_HTArbE2 0x00b9
+#define HC_SIMA_HGEMITout 0x00ba
+#define HC_SIMA_HFthRTXD 0x00bb
+#define HC_SIMA_HFthRTXA 0x00bc
+/* Define the texture palette 0
+ */
+#define HC_SIMA_HTP0 0x0100
+#define HC_SIMA_HTP1 0x0200
+#define HC_SIMA_FOGTABLE 0x0300
+#define HC_SIMA_STIPPLE 0x0400
+#define HC_SIMA_HE3Fire 0x0440
+#define HC_SIMA_TRANS_SET 0x0441
+#define HC_SIMA_HREngSt 0x0442
+#define HC_SIMA_HRFIFOempty 0x0443
+#define HC_SIMA_HRFIFOfull 0x0444
+#define HC_SIMA_HRErr 0x0445
+#define HC_SIMA_FIFOstatus 0x0446
+
+/******************************************************************************
+** Define the AGP command header.
+******************************************************************************/
+#define HC_ACMD_MASK 0xfe000000
+#define HC_ACMD_SUB_MASK 0x0c000000
+#define HC_ACMD_HCmdA 0xee000000
+#define HC_ACMD_HCmdB 0xec000000
+#define HC_ACMD_HCmdC 0xea000000
+#define HC_ACMD_H1 0xf0000000
+#define HC_ACMD_H2 0xf2000000
+#define HC_ACMD_H3 0xf4000000
+#define HC_ACMD_H4 0xf6000000
+
+#define HC_ACMD_H1IO_MASK 0x000001ff
+#define HC_ACMD_H2IO1_MASK 0x001ff000
+#define HC_ACMD_H2IO2_MASK 0x000001ff
+#define HC_ACMD_H2IO1_SHIFT 12
+#define HC_ACMD_H2IO2_SHIFT 0
+#define HC_ACMD_H3IO_MASK 0x000001ff
+#define HC_ACMD_H3COUNT_MASK 0x01fff000
+#define HC_ACMD_H3COUNT_SHIFT 12
+#define HC_ACMD_H4ID_MASK 0x000001ff
+#define HC_ACMD_H4COUNT_MASK 0x01fffe00
+#define HC_ACMD_H4COUNT_SHIFT 9
+
+/********************************************************************************
+** Define Header
+********************************************************************************/
+#define HC_HEADER2 0xF210F110
+
+/********************************************************************************
+** Define Dummy Value
+********************************************************************************/
+#define HC_DUMMY 0xCCCCCCCC
+/********************************************************************************
+** Define for DMA use
+********************************************************************************/
+#define HALCYON_HEADER2 0XF210F110
+#define HALCYON_FIRECMD 0XEE100000
+#define HALCYON_FIREMASK 0XFFF00000
+#define HALCYON_CMDB 0XEC000000
+#define HALCYON_CMDBMASK 0XFFFE0000
+#define HALCYON_SUB_ADDR0 0X00000000
+#define HALCYON_HEADER1MASK 0XFFFFFC00
+#define HALCYON_HEADER1 0XF0000000
+#define HC_SubA_HAGPBstL 0x0060
+#define HC_SubA_HAGPBendL 0x0061
+#define HC_SubA_HAGPCMNT 0x0062
+#define HC_SubA_HAGPBpL 0x0063
+#define HC_SubA_HAGPBpH 0x0064
+#define HC_HAGPCMNT_MASK 0x00800000
+#define HC_HCmdErrClr_MASK 0x00400000
+#define HC_HAGPBendH_MASK 0x0000ff00
+#define HC_HAGPBstH_MASK 0x000000ff
+#define HC_HAGPBendH_SHIFT 8
+#define HC_HAGPBstH_SHIFT 0
+#define HC_HAGPBpL_MASK 0x00fffffc
+#define HC_HAGPBpID_MASK 0x00000003
+#define HC_HAGPBpID_PAUSE 0x00000000
+#define HC_HAGPBpID_JUMP 0x00000001
+#define HC_HAGPBpID_STOP 0x00000002
+#define HC_HAGPBpH_MASK 0x00ffffff
+
+
+#define VIA_VIDEO_HEADER5 0xFE040000
+#define VIA_VIDEO_HEADER6 0xFE050000
+#define VIA_VIDEO_HEADER7 0xFE060000
+#define VIA_VIDEOMASK 0xFFFF0000
+#endif
diff --git a/drivers/char/drm/via_dma.c b/drivers/char/drm/via_dma.c
new file mode 100644
index 000000000000..82f839451622
--- /dev/null
+++ b/drivers/char/drm/via_dma.c
@@ -0,0 +1,741 @@
+/* via_dma.c -- DMA support for the VIA Unichrome/Pro
+ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Copyright 2004 Digeo, Inc., Palo Alto, CA, U.S.A.
+ * All Rights Reserved.
+ *
+ * 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 COPYRIGHT HOLDERS, AUTHORS 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.
+ *
+ * Authors:
+ * Tungsten Graphics,
+ * Erdi Chen,
+ * Thomas Hellstrom.
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "via_drm.h"
+#include "via_drv.h"
+#include "via_3d_reg.h"
+
+#define CMDBUF_ALIGNMENT_SIZE (0x100)
+#define CMDBUF_ALIGNMENT_MASK (0x0ff)
+
+/* defines for VIA 3D registers */
+#define VIA_REG_STATUS 0x400
+#define VIA_REG_TRANSET 0x43C
+#define VIA_REG_TRANSPACE 0x440
+
+/* VIA_REG_STATUS(0x400): Engine Status */
+#define VIA_CMD_RGTR_BUSY 0x00000080 /* Command Regulator is busy */
+#define VIA_2D_ENG_BUSY 0x00000001 /* 2D Engine is busy */
+#define VIA_3D_ENG_BUSY 0x00000002 /* 3D Engine is busy */
+#define VIA_VR_QUEUE_BUSY 0x00020000 /* Virtual Queue is busy */
+
+#define SetReg2DAGP(nReg, nData) { \
+ *((uint32_t *)(vb)) = ((nReg) >> 2) | HALCYON_HEADER1; \
+ *((uint32_t *)(vb) + 1) = (nData); \
+ vb = ((uint32_t *)vb) + 2; \
+ dev_priv->dma_low +=8; \
+}
+
+#define via_flush_write_combine() DRM_MEMORYBARRIER()
+
+#define VIA_OUT_RING_QW(w1,w2) \
+ *vb++ = (w1); \
+ *vb++ = (w2); \
+ dev_priv->dma_low += 8;
+
+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);
+static void via_cmdbuf_rewind(drm_via_private_t * dev_priv);
+static int via_wait_idle(drm_via_private_t * dev_priv);
+static void via_pad_cache(drm_via_private_t *dev_priv, int qwords);
+
+
+/*
+ * Free space in command buffer.
+ */
+
+static uint32_t
+via_cmdbuf_space(drm_via_private_t *dev_priv)
+{
+ uint32_t agp_base = dev_priv->dma_offset +
+ (uint32_t) dev_priv->agpAddr;
+ uint32_t hw_addr = *(dev_priv->hw_addr_ptr) - agp_base;
+
+ return ((hw_addr <= dev_priv->dma_low) ?
+ (dev_priv->dma_high + hw_addr - dev_priv->dma_low) :
+ (hw_addr - dev_priv->dma_low));
+}
+
+/*
+ * How much does the command regulator lag behind?
+ */
+
+static uint32_t
+via_cmdbuf_lag(drm_via_private_t *dev_priv)
+{
+ uint32_t agp_base = dev_priv->dma_offset +
+ (uint32_t) dev_priv->agpAddr;
+ uint32_t hw_addr = *(dev_priv->hw_addr_ptr) - agp_base;
+
+ return ((hw_addr <= dev_priv->dma_low) ?
+ (dev_priv->dma_low - hw_addr) :
+ (dev_priv->dma_wrap + dev_priv->dma_low - hw_addr));
+}
+
+/*
+ * Check that the given size fits in the buffer, otherwise wait.
+ */
+
+static inline int
+via_cmdbuf_wait(drm_via_private_t * dev_priv, unsigned int size)
+{
+ uint32_t agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
+ uint32_t cur_addr, hw_addr, next_addr;
+ volatile uint32_t *hw_addr_ptr;
+ uint32_t count;
+ hw_addr_ptr = dev_priv->hw_addr_ptr;
+ cur_addr = dev_priv->dma_low;
+ next_addr = cur_addr + size + 512*1024;
+ count = 1000000;
+ do {
+ hw_addr = *hw_addr_ptr - agp_base;
+ if (count-- == 0) {
+ DRM_ERROR("via_cmdbuf_wait timed out hw %x cur_addr %x next_addr %x\n",
+ hw_addr, cur_addr, next_addr);
+ return -1;
+ }
+ } while ((cur_addr < hw_addr) && (next_addr >= hw_addr));
+ return 0;
+}
+
+
+/*
+ * Checks whether buffer head has reach the end. Rewind the ring buffer
+ * when necessary.
+ *
+ * Returns virtual pointer to ring buffer.
+ */
+
+static inline uint32_t *via_check_dma(drm_via_private_t * dev_priv,
+ unsigned int size)
+{
+ if ((dev_priv->dma_low + size + 4*CMDBUF_ALIGNMENT_SIZE) > dev_priv->dma_high) {
+ via_cmdbuf_rewind(dev_priv);
+ }
+ if (via_cmdbuf_wait(dev_priv, size) != 0) {
+ return NULL;
+ }
+
+ return (uint32_t *) (dev_priv->dma_ptr + dev_priv->dma_low);
+}
+
+int via_dma_cleanup(drm_device_t * dev)
+{
+ if (dev->dev_private) {
+ drm_via_private_t *dev_priv =
+ (drm_via_private_t *) dev->dev_private;
+
+ if (dev_priv->ring.virtual_start) {
+ via_cmdbuf_reset(dev_priv);
+
+ drm_core_ioremapfree(&dev_priv->ring.map, dev);
+ dev_priv->ring.virtual_start = NULL;
+ }
+
+ }
+
+ return 0;
+}
+
+static int via_initialize(drm_device_t * dev,
+ drm_via_private_t * dev_priv,
+ drm_via_dma_init_t * init)
+{
+ if (!dev_priv || !dev_priv->mmio) {
+ DRM_ERROR("via_dma_init called before via_map_init\n");
+ return DRM_ERR(EFAULT);
+ }
+
+ if (dev_priv->ring.virtual_start != NULL) {
+ DRM_ERROR("%s called again without calling cleanup\n",
+ __FUNCTION__);
+ return DRM_ERR(EFAULT);
+ }
+
+ if (!dev->agp || !dev->agp->base) {
+ DRM_ERROR("%s called with no agp memory available\n",
+ __FUNCTION__);
+ return DRM_ERR(EFAULT);
+ }
+
+ dev_priv->ring.map.offset = dev->agp->base + init->offset;
+ dev_priv->ring.map.size = init->size;
+ dev_priv->ring.map.type = 0;
+ dev_priv->ring.map.flags = 0;
+ dev_priv->ring.map.mtrr = 0;
+
+ drm_core_ioremap(&dev_priv->ring.map, dev);
+
+ if (dev_priv->ring.map.handle == NULL) {
+ via_dma_cleanup(dev);
+ DRM_ERROR("can not ioremap virtual address for"
+ " ring buffer\n");
+ return DRM_ERR(ENOMEM);
+ }
+
+ dev_priv->ring.virtual_start = dev_priv->ring.map.handle;
+
+ dev_priv->dma_ptr = dev_priv->ring.virtual_start;
+ dev_priv->dma_low = 0;
+ dev_priv->dma_high = init->size;
+ dev_priv->dma_wrap = init->size;
+ dev_priv->dma_offset = init->offset;
+ dev_priv->last_pause_ptr = NULL;
+ dev_priv->hw_addr_ptr = dev_priv->mmio->handle + init->reg_pause_addr;
+
+ via_cmdbuf_start(dev_priv);
+
+ return 0;
+}
+
+int via_dma_init(DRM_IOCTL_ARGS)
+{
+ DRM_DEVICE;
+ drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+ drm_via_dma_init_t init;
+ int retcode = 0;
+
+ DRM_COPY_FROM_USER_IOCTL(init, (drm_via_dma_init_t *) data,
+ sizeof(init));
+
+ switch (init.func) {
+ case VIA_INIT_DMA:
+ if (!capable(CAP_SYS_ADMIN))
+ retcode = DRM_ERR(EPERM);
+ else
+ retcode = via_initialize(dev, dev_priv, &init);
+ break;
+ case VIA_CLEANUP_DMA:
+ if (!capable(CAP_SYS_ADMIN))
+ retcode = DRM_ERR(EPERM);
+ else
+ 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;
+ }
+
+ return retcode;
+}
+
+
+
+static int via_dispatch_cmdbuffer(drm_device_t * dev, drm_via_cmdbuffer_t * cmd)
+{
+ drm_via_private_t *dev_priv;
+ uint32_t *vb;
+ int ret;
+
+ dev_priv = (drm_via_private_t *) dev->dev_private;
+
+ if (dev_priv->ring.virtual_start == NULL) {
+ DRM_ERROR("%s called without initializing AGP ring buffer.\n",
+ __FUNCTION__);
+ return DRM_ERR(EFAULT);
+ }
+
+ if (cmd->size > VIA_PCI_BUF_SIZE) {
+ return DRM_ERR(ENOMEM);
+ }
+
+
+ if (DRM_COPY_FROM_USER(dev_priv->pci_buf, cmd->buf, cmd->size))
+ return DRM_ERR(EFAULT);
+
+ /*
+ * Running this function on AGP memory is dead slow. Therefore
+ * we run it on a temporary cacheable system memory buffer and
+ * copy it to AGP memory when ready.
+ */
+
+
+ if ((ret = via_verify_command_stream((uint32_t *)dev_priv->pci_buf, cmd->size, dev, 1))) {
+ return ret;
+ }
+
+
+ vb = via_check_dma(dev_priv, (cmd->size < 0x100) ? 0x102 : cmd->size);
+ if (vb == NULL) {
+ return DRM_ERR(EAGAIN);
+ }
+
+ memcpy(vb, dev_priv->pci_buf, cmd->size);
+
+ dev_priv->dma_low += cmd->size;
+
+ /*
+ * Small submissions somehow stalls the CPU. (AGP cache effects?)
+ * pad to greater size.
+ */
+
+ if (cmd->size < 0x100)
+ via_pad_cache(dev_priv,(0x100 - cmd->size) >> 3);
+ via_cmdbuf_pause(dev_priv);
+
+ return 0;
+}
+
+int via_driver_dma_quiescent(drm_device_t * dev)
+{
+ drm_via_private_t *dev_priv = dev->dev_private;
+
+ if (!via_wait_idle(dev_priv)) {
+ return DRM_ERR(EBUSY);
+ }
+ return 0;
+}
+
+int via_flush_ioctl(DRM_IOCTL_ARGS)
+{
+ DRM_DEVICE;
+
+ LOCK_TEST_WITH_RETURN( dev, filp );
+
+ return via_driver_dma_quiescent(dev);
+}
+
+int via_cmdbuffer(DRM_IOCTL_ARGS)
+{
+ DRM_DEVICE;
+ drm_via_cmdbuffer_t cmdbuf;
+ int ret;
+
+ LOCK_TEST_WITH_RETURN( dev, filp );
+
+ DRM_COPY_FROM_USER_IOCTL(cmdbuf, (drm_via_cmdbuffer_t *) data,
+ sizeof(cmdbuf));
+
+ DRM_DEBUG("via cmdbuffer, buf %p size %lu\n", cmdbuf.buf, cmdbuf.size);
+
+ ret = via_dispatch_cmdbuffer(dev, &cmdbuf);
+ if (ret) {
+ return ret;
+ }
+
+ return 0;
+}
+
+extern int
+via_parse_command_stream(drm_device_t *dev, const uint32_t * buf, unsigned int size);
+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 > VIA_PCI_BUF_SIZE) {
+ return DRM_ERR(ENOMEM);
+ }
+ if (DRM_COPY_FROM_USER(dev_priv->pci_buf, cmd->buf, cmd->size))
+ return DRM_ERR(EFAULT);
+
+ if ((ret = via_verify_command_stream((uint32_t *)dev_priv->pci_buf, cmd->size, dev, 0))) {
+ return ret;
+ }
+
+ ret = via_parse_command_stream(dev, (const uint32_t *)dev_priv->pci_buf, cmd->size);
+ return ret;
+}
+
+int via_pci_cmdbuffer(DRM_IOCTL_ARGS)
+{
+ DRM_DEVICE;
+ drm_via_cmdbuffer_t cmdbuf;
+ int ret;
+
+ LOCK_TEST_WITH_RETURN( dev, filp );
+
+ DRM_COPY_FROM_USER_IOCTL(cmdbuf, (drm_via_cmdbuffer_t *) data,
+ sizeof(cmdbuf));
+
+ DRM_DEBUG("via_pci_cmdbuffer, buf %p size %lu\n", cmdbuf.buf,
+ cmdbuf.size);
+
+ ret = via_dispatch_pci_cmdbuffer(dev, &cmdbuf);
+ if (ret) {
+ return ret;
+ }
+
+ return 0;
+}
+
+
+static inline uint32_t *via_align_buffer(drm_via_private_t * dev_priv,
+ uint32_t * vb, int qw_count)
+{
+ for (; qw_count > 0; --qw_count) {
+ VIA_OUT_RING_QW(HC_DUMMY, HC_DUMMY);
+ }
+ return vb;
+}
+
+
+/*
+ * This function is used internally by ring buffer mangement code.
+ *
+ * Returns virtual pointer to ring buffer.
+ */
+static inline uint32_t *via_get_dma(drm_via_private_t * dev_priv)
+{
+ return (uint32_t *) (dev_priv->dma_ptr + dev_priv->dma_low);
+}
+
+/*
+ * Hooks a segment of data into the tail of the ring-buffer by
+ * modifying the pause address stored in the buffer itself. If
+ * the regulator has already paused, restart it.
+ */
+static int via_hook_segment(drm_via_private_t *dev_priv,
+ uint32_t pause_addr_hi, uint32_t pause_addr_lo,
+ int no_pci_fire)
+{
+ int paused, count;
+ volatile uint32_t *paused_at = dev_priv->last_pause_ptr;
+
+ via_flush_write_combine();
+ while(! *(via_get_dma(dev_priv)-1));
+ *dev_priv->last_pause_ptr = pause_addr_lo;
+ via_flush_write_combine();
+
+ /*
+ * The below statement is inserted to really force the flush.
+ * Not sure it is needed.
+ */
+
+ while(! *dev_priv->last_pause_ptr);
+ dev_priv->last_pause_ptr = via_get_dma(dev_priv) - 1;
+ while(! *dev_priv->last_pause_ptr);
+
+
+ paused = 0;
+ count = 20;
+
+ while (!(paused = (VIA_READ(0x41c) & 0x80000000)) && count--);
+ if ((count <= 8) && (count >= 0)) {
+ uint32_t rgtr, ptr;
+ rgtr = *(dev_priv->hw_addr_ptr);
+ ptr = ((char *)dev_priv->last_pause_ptr - dev_priv->dma_ptr) +
+ dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4 -
+ CMDBUF_ALIGNMENT_SIZE;
+ if (rgtr <= ptr) {
+ DRM_ERROR("Command regulator\npaused at count %d, address %x, "
+ "while current pause address is %x.\n"
+ "Please mail this message to "
+ "<unichrome-devel@lists.sourceforge.net>\n",
+ count, rgtr, ptr);
+ }
+ }
+
+ if (paused && !no_pci_fire) {
+ uint32_t rgtr,ptr;
+ uint32_t ptr_low;
+
+ count = 1000000;
+ while ((VIA_READ(VIA_REG_STATUS) & VIA_CMD_RGTR_BUSY) && count--);
+
+ rgtr = *(dev_priv->hw_addr_ptr);
+ ptr = ((char *)paused_at - dev_priv->dma_ptr) +
+ dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4;
+
+
+ ptr_low = (ptr > 3*CMDBUF_ALIGNMENT_SIZE) ?
+ ptr - 3*CMDBUF_ALIGNMENT_SIZE : 0;
+ if (rgtr <= ptr && rgtr >= ptr_low) {
+ VIA_WRITE(VIA_REG_TRANSET, (HC_ParaType_PreCR << 16));
+ VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_hi);
+ VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo);
+ }
+ }
+ return paused;
+}
+
+
+
+static int via_wait_idle(drm_via_private_t * dev_priv)
+{
+ int count = 10000000;
+ while (count-- && (VIA_READ(VIA_REG_STATUS) &
+ (VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY |
+ VIA_3D_ENG_BUSY))) ;
+ return count;
+}
+
+static uint32_t *via_align_cmd(drm_via_private_t * dev_priv, uint32_t cmd_type,
+ uint32_t addr, uint32_t *cmd_addr_hi,
+ uint32_t *cmd_addr_lo,
+ int skip_wait)
+{
+ uint32_t agp_base;
+ uint32_t cmd_addr, addr_lo, addr_hi;
+ uint32_t *vb;
+ uint32_t qw_pad_count;
+
+ if (!skip_wait)
+ via_cmdbuf_wait(dev_priv, 2*CMDBUF_ALIGNMENT_SIZE);
+
+ vb = via_get_dma(dev_priv);
+ VIA_OUT_RING_QW( HC_HEADER2 | ((VIA_REG_TRANSET >> 2) << 12) |
+ (VIA_REG_TRANSPACE >> 2), HC_ParaType_PreCR << 16);
+ agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
+ qw_pad_count = (CMDBUF_ALIGNMENT_SIZE >> 3) -
+ ((dev_priv->dma_low & CMDBUF_ALIGNMENT_MASK) >> 3);
+
+
+ cmd_addr = (addr) ? addr :
+ agp_base + dev_priv->dma_low - 8 + (qw_pad_count << 3);
+ addr_lo = ((HC_SubA_HAGPBpL << 24) | (cmd_type & HC_HAGPBpID_MASK) |
+ (cmd_addr & HC_HAGPBpL_MASK));
+ addr_hi = ((HC_SubA_HAGPBpH << 24) | (cmd_addr >> 24));
+
+ vb = via_align_buffer(dev_priv, vb, qw_pad_count - 1);
+ VIA_OUT_RING_QW(*cmd_addr_hi = addr_hi,
+ *cmd_addr_lo = addr_lo);
+ return vb;
+}
+
+
+
+
+static void via_cmdbuf_start(drm_via_private_t * dev_priv)
+{
+ uint32_t pause_addr_lo, pause_addr_hi;
+ uint32_t start_addr, start_addr_lo;
+ uint32_t end_addr, end_addr_lo;
+ uint32_t command;
+ uint32_t agp_base;
+
+
+ dev_priv->dma_low = 0;
+
+ agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
+ start_addr = agp_base;
+ end_addr = agp_base + dev_priv->dma_high;
+
+ start_addr_lo = ((HC_SubA_HAGPBstL << 24) | (start_addr & 0xFFFFFF));
+ end_addr_lo = ((HC_SubA_HAGPBendL << 24) | (end_addr & 0xFFFFFF));
+ command = ((HC_SubA_HAGPCMNT << 24) | (start_addr >> 24) |
+ ((end_addr & 0xff000000) >> 16));
+
+ dev_priv->last_pause_ptr =
+ via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0,
+ &pause_addr_hi, & pause_addr_lo, 1) - 1;
+
+ via_flush_write_combine();
+ while(! *dev_priv->last_pause_ptr);
+
+ VIA_WRITE(VIA_REG_TRANSET, (HC_ParaType_PreCR << 16));
+ VIA_WRITE(VIA_REG_TRANSPACE, command);
+ VIA_WRITE(VIA_REG_TRANSPACE, start_addr_lo);
+ VIA_WRITE(VIA_REG_TRANSPACE, end_addr_lo);
+
+ VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_hi);
+ VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo);
+
+ VIA_WRITE(VIA_REG_TRANSPACE, command | HC_HAGPCMNT_MASK);
+}
+
+static void via_pad_cache(drm_via_private_t *dev_priv, int qwords)
+{
+ uint32_t *vb;
+
+ via_cmdbuf_wait(dev_priv, qwords + 2);
+ vb = via_get_dma(dev_priv);
+ VIA_OUT_RING_QW( HC_HEADER2, HC_ParaType_NotTex << 16);
+ via_align_buffer(dev_priv,vb,qwords);
+}
+
+static inline void via_dummy_bitblt(drm_via_private_t * dev_priv)
+{
+ uint32_t *vb = via_get_dma(dev_priv);
+ SetReg2DAGP(0x0C, (0 | (0 << 16)));
+ SetReg2DAGP(0x10, 0 | (0 << 16));
+ SetReg2DAGP(0x0, 0x1 | 0x2000 | 0xAA000000);
+}
+
+
+static void via_cmdbuf_jump(drm_via_private_t * dev_priv)
+{
+ uint32_t agp_base;
+ uint32_t pause_addr_lo, pause_addr_hi;
+ uint32_t jump_addr_lo, jump_addr_hi;
+ volatile uint32_t *last_pause_ptr;
+ uint32_t dma_low_save1, dma_low_save2;
+
+ agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
+ via_align_cmd(dev_priv, HC_HAGPBpID_JUMP, 0, &jump_addr_hi,
+ &jump_addr_lo, 0);
+
+ dev_priv->dma_wrap = dev_priv->dma_low;
+
+
+ /*
+ * Wrap command buffer to the beginning.
+ */
+
+ dev_priv->dma_low = 0;
+ if (via_cmdbuf_wait(dev_priv, CMDBUF_ALIGNMENT_SIZE) != 0) {
+ DRM_ERROR("via_cmdbuf_jump failed\n");
+ }
+
+ via_dummy_bitblt(dev_priv);
+ via_dummy_bitblt(dev_priv);
+
+ last_pause_ptr = via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
+ &pause_addr_lo, 0) -1;
+ via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
+ &pause_addr_lo, 0);
+
+ *last_pause_ptr = pause_addr_lo;
+ dma_low_save1 = dev_priv->dma_low;
+
+ /*
+ * Now, set a trap that will pause the regulator if it tries to rerun the old
+ * command buffer. (Which may happen if via_hook_segment detecs a command regulator pause
+ * and reissues the jump command over PCI, while the regulator has already taken the jump
+ * and actually paused at the current buffer end).
+ * There appears to be no other way to detect this condition, since the hw_addr_pointer
+ * does not seem to get updated immediately when a jump occurs.
+ */
+
+ last_pause_ptr = via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
+ &pause_addr_lo, 0) -1;
+ via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
+ &pause_addr_lo, 0);
+ *last_pause_ptr = pause_addr_lo;
+
+ dma_low_save2 = dev_priv->dma_low;
+ dev_priv->dma_low = dma_low_save1;
+ via_hook_segment( dev_priv, jump_addr_hi, jump_addr_lo, 0);
+ dev_priv->dma_low = dma_low_save2;
+ via_hook_segment( dev_priv, pause_addr_hi, pause_addr_lo, 0);
+}
+
+
+static void via_cmdbuf_rewind(drm_via_private_t * dev_priv)
+{
+ via_cmdbuf_jump(dev_priv);
+}
+
+static void via_cmdbuf_flush(drm_via_private_t * dev_priv, uint32_t cmd_type)
+{
+ uint32_t pause_addr_lo, pause_addr_hi;
+
+ via_align_cmd(dev_priv, cmd_type, 0, &pause_addr_hi, &pause_addr_lo, 0);
+ via_hook_segment( dev_priv, pause_addr_hi, pause_addr_lo, 0);
+}
+
+
+static void via_cmdbuf_pause(drm_via_private_t * dev_priv)
+{
+ via_cmdbuf_flush(dev_priv, HC_HAGPBpID_PAUSE);
+}
+
+static void via_cmdbuf_reset(drm_via_private_t * dev_priv)
+{
+ via_cmdbuf_flush(dev_priv, HC_HAGPBpID_STOP);
+ via_wait_idle(dev_priv);
+}
+
+/*
+ * User interface to the space and lag functions.
+ */
+
+int
+via_cmdbuf_size(DRM_IOCTL_ARGS)
+{
+ DRM_DEVICE;
+ drm_via_cmdbuf_size_t d_siz;
+ int ret = 0;
+ uint32_t tmp_size, count;
+ drm_via_private_t *dev_priv;
+
+ DRM_DEBUG("via cmdbuf_size\n");
+ LOCK_TEST_WITH_RETURN( dev, filp );
+
+ dev_priv = (drm_via_private_t *) dev->dev_private;
+
+ if (dev_priv->ring.virtual_start == NULL) {
+ DRM_ERROR("%s called without initializing AGP ring buffer.\n",
+ __FUNCTION__);
+ return DRM_ERR(EFAULT);
+ }
+
+ DRM_COPY_FROM_USER_IOCTL(d_siz, (drm_via_cmdbuf_size_t *) data,
+ sizeof(d_siz));
+
+
+ count = 1000000;
+ tmp_size = d_siz.size;
+ switch(d_siz.func) {
+ case VIA_CMDBUF_SPACE:
+ while (((tmp_size = via_cmdbuf_space(dev_priv)) < d_siz.size) && count--) {
+ if (!d_siz.wait) {
+ break;
+ }
+ }
+ if (!count) {
+ DRM_ERROR("VIA_CMDBUF_SPACE timed out.\n");
+ ret = DRM_ERR(EAGAIN);
+ }
+ break;
+ case VIA_CMDBUF_LAG:
+ while (((tmp_size = via_cmdbuf_lag(dev_priv)) > d_siz.size) && count--) {
+ if (!d_siz.wait) {
+ break;
+ }
+ }
+ if (!count) {
+ DRM_ERROR("VIA_CMDBUF_LAG timed out.\n");
+ ret = DRM_ERR(EAGAIN);
+ }
+ break;
+ default:
+ ret = DRM_ERR(EFAULT);
+ }
+ d_siz.size = tmp_size;
+
+ DRM_COPY_TO_USER_IOCTL((drm_via_cmdbuf_size_t *) data, d_siz,
+ sizeof(d_siz));
+ return ret;
+}
diff --git a/drivers/char/drm/via_drm.h b/drivers/char/drm/via_drm.h
new file mode 100644
index 000000000000..4588c9bd1816
--- /dev/null
+++ b/drivers/char/drm/via_drm.h
@@ -0,0 +1,243 @@
+/*
+ * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2003 S3 Graphics, Inc. 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
+ * VIA, S3 GRAPHICS, 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.
+ */
+#ifndef _VIA_DRM_H_
+#define _VIA_DRM_H_
+
+/* WARNING: These defines must be the same as what the Xserver uses.
+ * if you change them, you must change the defines in the Xserver.
+ */
+
+#ifndef _VIA_DEFINES_
+#define _VIA_DEFINES_
+
+#ifndef __KERNEL__
+#include "via_drmclient.h"
+#endif
+
+#define VIA_NR_SAREA_CLIPRECTS 8
+#define VIA_NR_XVMC_PORTS 10
+#define VIA_NR_XVMC_LOCKS 5
+#define VIA_MAX_CACHELINE_SIZE 64
+#define XVMCLOCKPTR(saPriv,lockNo) \
+ ((volatile drm_hw_lock_t *)(((((unsigned long) (saPriv)->XvMCLockArea) + \
+ (VIA_MAX_CACHELINE_SIZE - 1)) & \
+ ~(VIA_MAX_CACHELINE_SIZE - 1)) + \
+ VIA_MAX_CACHELINE_SIZE*(lockNo)))
+
+/* Each region is a minimum of 64k, and there are at most 64 of them.
+ */
+#define VIA_NR_TEX_REGIONS 64
+#define VIA_LOG_MIN_TEX_REGION_SIZE 16
+#endif
+
+#define VIA_UPLOAD_TEX0IMAGE 0x1 /* handled clientside */
+#define VIA_UPLOAD_TEX1IMAGE 0x2 /* handled clientside */
+#define VIA_UPLOAD_CTX 0x4
+#define VIA_UPLOAD_BUFFERS 0x8
+#define VIA_UPLOAD_TEX0 0x10
+#define VIA_UPLOAD_TEX1 0x20
+#define VIA_UPLOAD_CLIPRECTS 0x40
+#define VIA_UPLOAD_ALL 0xff
+
+/* VIA specific ioctls */
+#define DRM_VIA_ALLOCMEM 0x00
+#define DRM_VIA_FREEMEM 0x01
+#define DRM_VIA_AGP_INIT 0x02
+#define DRM_VIA_FB_INIT 0x03
+#define DRM_VIA_MAP_INIT 0x04
+#define DRM_VIA_DEC_FUTEX 0x05
+#define NOT_USED
+#define DRM_VIA_DMA_INIT 0x07
+#define DRM_VIA_CMDBUFFER 0x08
+#define DRM_VIA_FLUSH 0x09
+#define DRM_VIA_PCICMD 0x0a
+#define DRM_VIA_CMDBUF_SIZE 0x0b
+#define NOT_USED
+#define DRM_VIA_WAIT_IRQ 0x0d
+
+#define DRM_IOCTL_VIA_ALLOCMEM DRM_IOWR(DRM_COMMAND_BASE + DRM_VIA_ALLOCMEM, drm_via_mem_t)
+#define DRM_IOCTL_VIA_FREEMEM DRM_IOW( DRM_COMMAND_BASE + DRM_VIA_FREEMEM, drm_via_mem_t)
+#define DRM_IOCTL_VIA_AGP_INIT DRM_IOWR(DRM_COMMAND_BASE + DRM_VIA_AGP_INIT, drm_via_agp_t)
+#define DRM_IOCTL_VIA_FB_INIT DRM_IOWR(DRM_COMMAND_BASE + DRM_VIA_FB_INIT, drm_via_fb_t)
+#define DRM_IOCTL_VIA_MAP_INIT DRM_IOWR(DRM_COMMAND_BASE + DRM_VIA_MAP_INIT, drm_via_init_t)
+#define DRM_IOCTL_VIA_DEC_FUTEX DRM_IOW( DRM_COMMAND_BASE + DRM_VIA_DEC_FUTEX, drm_via_futex_t)
+#define DRM_IOCTL_VIA_DMA_INIT DRM_IOWR(DRM_COMMAND_BASE + DRM_VIA_DMA_INIT, drm_via_dma_init_t)
+#define DRM_IOCTL_VIA_CMDBUFFER DRM_IOW( DRM_COMMAND_BASE + DRM_VIA_CMDBUFFER, drm_via_cmdbuffer_t)
+#define DRM_IOCTL_VIA_FLUSH DRM_IO( DRM_COMMAND_BASE + DRM_VIA_FLUSH)
+#define DRM_IOCTL_VIA_PCICMD DRM_IOW( DRM_COMMAND_BASE + DRM_VIA_PCICMD, drm_via_cmdbuffer_t)
+#define DRM_IOCTL_VIA_CMDBUF_SIZE DRM_IOWR( DRM_COMMAND_BASE + DRM_VIA_CMDBUF_SIZE, \
+ drm_via_cmdbuf_size_t)
+#define DRM_IOCTL_VIA_WAIT_IRQ DRM_IOWR( DRM_COMMAND_BASE + DRM_VIA_WAIT_IRQ, drm_via_irqwait_t)
+
+/* Indices into buf.Setup where various bits of state are mirrored per
+ * context and per buffer. These can be fired at the card as a unit,
+ * or in a piecewise fashion as required.
+ */
+
+#define VIA_TEX_SETUP_SIZE 8
+
+/* Flags for clear ioctl
+ */
+#define VIA_FRONT 0x1
+#define VIA_BACK 0x2
+#define VIA_DEPTH 0x4
+#define VIA_STENCIL 0x8
+#define VIDEO 0
+#define AGP 1
+typedef struct {
+ uint32_t offset;
+ uint32_t size;
+} drm_via_agp_t;
+
+typedef struct {
+ uint32_t offset;
+ uint32_t size;
+} drm_via_fb_t;
+
+typedef struct {
+ uint32_t context;
+ uint32_t type;
+ uint32_t size;
+ unsigned long index;
+ unsigned long offset;
+} drm_via_mem_t;
+
+typedef struct _drm_via_init {
+ enum {
+ VIA_INIT_MAP = 0x01,
+ VIA_CLEANUP_MAP = 0x02
+ } func;
+
+ unsigned long sarea_priv_offset;
+ unsigned long fb_offset;
+ unsigned long mmio_offset;
+ unsigned long agpAddr;
+} drm_via_init_t;
+
+typedef struct _drm_via_futex {
+ enum {
+ VIA_FUTEX_WAIT = 0x00,
+ VIA_FUTEX_WAKE = 0X01
+ } func;
+ uint32_t ms;
+ uint32_t lock;
+ uint32_t val;
+} drm_via_futex_t;
+
+typedef struct _drm_via_dma_init {
+ enum {
+ VIA_INIT_DMA = 0x01,
+ VIA_CLEANUP_DMA = 0x02,
+ VIA_DMA_INITIALIZED = 0x03
+ } func;
+
+ unsigned long offset;
+ unsigned long size;
+ unsigned long reg_pause_addr;
+} drm_via_dma_init_t;
+
+typedef struct _drm_via_cmdbuffer {
+ char *buf;
+ unsigned long size;
+} drm_via_cmdbuffer_t;
+
+/* Warning: If you change the SAREA structure you must change the Xserver
+ * structure as well */
+
+typedef struct _drm_via_tex_region {
+ unsigned char next, prev; /* indices to form a circular LRU */
+ unsigned char inUse; /* owned by a client, or free? */
+ int age; /* tracked by clients to update local LRU's */
+} drm_via_tex_region_t;
+
+typedef struct _drm_via_sarea {
+ unsigned int dirty;
+ unsigned int nbox;
+ drm_clip_rect_t boxes[VIA_NR_SAREA_CLIPRECTS];
+ drm_via_tex_region_t texList[VIA_NR_TEX_REGIONS + 1];
+ int texAge; /* last time texture was uploaded */
+ int ctxOwner; /* last context to upload state */
+ int vertexPrim;
+
+ /*
+ * Below is for XvMC.
+ * We want the lock integers alone on, and aligned to, a cache line.
+ * Therefore this somewhat strange construct.
+ */
+
+ char XvMCLockArea[VIA_MAX_CACHELINE_SIZE * (VIA_NR_XVMC_LOCKS + 1)];
+
+ unsigned int XvMCDisplaying[VIA_NR_XVMC_PORTS];
+ unsigned int XvMCSubPicOn[VIA_NR_XVMC_PORTS];
+ unsigned int XvMCCtxNoGrabbed; /* Last context to hold decoder */
+
+} drm_via_sarea_t;
+
+typedef struct _drm_via_cmdbuf_size {
+ enum {
+ VIA_CMDBUF_SPACE = 0x01,
+ VIA_CMDBUF_LAG = 0x02
+ } func;
+ int wait;
+ uint32_t size;
+} drm_via_cmdbuf_size_t;
+
+typedef enum {
+ VIA_IRQ_ABSOLUTE = 0x0,
+ VIA_IRQ_RELATIVE = 0x1,
+ VIA_IRQ_SIGNAL = 0x10000000,
+ VIA_IRQ_FORCE_SEQUENCE = 0x20000000
+} via_irq_seq_type_t;
+
+#define VIA_IRQ_FLAGS_MASK 0xF0000000
+
+struct drm_via_wait_irq_request{
+ unsigned irq;
+ via_irq_seq_type_t type;
+ uint32_t sequence;
+ uint32_t signal;
+};
+
+typedef union drm_via_irqwait {
+ struct drm_via_wait_irq_request request;
+ struct drm_wait_vblank_reply reply;
+} drm_via_irqwait_t;
+
+#ifdef __KERNEL__
+
+int via_fb_init(DRM_IOCTL_ARGS);
+int via_mem_alloc(DRM_IOCTL_ARGS);
+int via_mem_free(DRM_IOCTL_ARGS);
+int via_agp_init(DRM_IOCTL_ARGS);
+int via_map_init(DRM_IOCTL_ARGS);
+int via_decoder_futex(DRM_IOCTL_ARGS);
+int via_dma_init(DRM_IOCTL_ARGS);
+int via_cmdbuffer(DRM_IOCTL_ARGS);
+int via_flush_ioctl(DRM_IOCTL_ARGS);
+int via_pci_cmdbuffer(DRM_IOCTL_ARGS);
+int via_cmdbuf_size(DRM_IOCTL_ARGS);
+int via_wait_irq(DRM_IOCTL_ARGS);
+
+#endif
+#endif /* _VIA_DRM_H_ */
diff --git a/drivers/char/drm/via_drv.c b/drivers/char/drm/via_drv.c
new file mode 100644
index 000000000000..275eefc79221
--- /dev/null
+++ b/drivers/char/drm/via_drv.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2003 S3 Graphics, Inc. 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
+ * VIA, S3 GRAPHICS, 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.
+ */
+
+#include <linux/config.h>
+#include "drmP.h"
+#include "via_drm.h"
+#include "via_drv.h"
+
+#include "drm_pciids.h"
+
+static int postinit(struct drm_device *dev, unsigned long flags)
+{
+ DRM_INFO("Initialized %s %d.%d.%d %s on minor %d: %s\n",
+ DRIVER_NAME,
+ DRIVER_MAJOR,
+ DRIVER_MINOR,
+ DRIVER_PATCHLEVEL,
+ DRIVER_DATE, dev->primary.minor, pci_pretty_name(dev->pdev)
+ );
+ return 0;
+}
+
+static int version(drm_version_t * version)
+{
+ int len;
+
+ version->version_major = DRIVER_MAJOR;
+ version->version_minor = DRIVER_MINOR;
+ version->version_patchlevel = DRIVER_PATCHLEVEL;
+ DRM_COPY(version->name, DRIVER_NAME);
+ DRM_COPY(version->date, DRIVER_DATE);
+ DRM_COPY(version->desc, DRIVER_DESC);
+ return 0;
+}
+
+static struct pci_device_id pciidlist[] = {
+ viadrv_PCI_IDS
+};
+
+static drm_ioctl_desc_t ioctls[] = {
+ [DRM_IOCTL_NR(DRM_VIA_ALLOCMEM)] = {via_mem_alloc, 1, 0},
+ [DRM_IOCTL_NR(DRM_VIA_FREEMEM)] = {via_mem_free, 1, 0},
+ [DRM_IOCTL_NR(DRM_VIA_AGP_INIT)] = {via_agp_init, 1, 0},
+ [DRM_IOCTL_NR(DRM_VIA_FB_INIT)] = {via_fb_init, 1, 0},
+ [DRM_IOCTL_NR(DRM_VIA_MAP_INIT)] = {via_map_init, 1, 0},
+ [DRM_IOCTL_NR(DRM_VIA_DEC_FUTEX)] = {via_decoder_futex, 1, 0},
+ [DRM_IOCTL_NR(DRM_VIA_DMA_INIT)] = {via_dma_init, 1, 0},
+ [DRM_IOCTL_NR(DRM_VIA_CMDBUFFER)] = {via_cmdbuffer, 1, 0},
+ [DRM_IOCTL_NR(DRM_VIA_FLUSH)] = {via_flush_ioctl, 1, 0},
+ [DRM_IOCTL_NR(DRM_VIA_PCICMD)] = {via_pci_cmdbuffer, 1, 0},
+ [DRM_IOCTL_NR(DRM_VIA_CMDBUF_SIZE)] = {via_cmdbuf_size, 1, 0},
+ [DRM_IOCTL_NR(DRM_VIA_WAIT_IRQ)] = {via_wait_irq, 1, 0}
+};
+
+static struct drm_driver driver = {
+ .driver_features =
+ DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_IRQ |
+ DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL,
+ .context_ctor = via_init_context,
+ .context_dtor = via_final_context,
+ .vblank_wait = via_driver_vblank_wait,
+ .irq_preinstall = via_driver_irq_preinstall,
+ .irq_postinstall = via_driver_irq_postinstall,
+ .irq_uninstall = via_driver_irq_uninstall,
+ .irq_handler = via_driver_irq_handler,
+ .dma_quiescent = via_driver_dma_quiescent,
+ .reclaim_buffers = drm_core_reclaim_buffers,
+ .get_map_ofs = drm_core_get_map_ofs,
+ .get_reg_ofs = drm_core_get_reg_ofs,
+ .postinit = postinit,
+ .version = version,
+ .ioctls = ioctls,
+ .num_ioctls = DRM_ARRAY_SIZE(ioctls),
+ .fops = {
+ .owner = THIS_MODULE,
+ .open = drm_open,
+ .release = drm_release,
+ .ioctl = drm_ioctl,
+ .mmap = drm_mmap,
+ .poll = drm_poll,
+ .fasync = drm_fasync,
+ },
+ .pci_driver = {
+ .name = DRIVER_NAME,
+ .id_table = pciidlist,
+ }
+};
+
+static int __init via_init(void)
+{
+ via_init_command_verifier();
+ return drm_init(&driver);
+}
+
+static void __exit via_exit(void)
+{
+ drm_exit(&driver);
+}
+
+module_init(via_init);
+module_exit(via_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/char/drm/via_drv.h b/drivers/char/drm/via_drv.h
new file mode 100644
index 000000000000..4eaa8b7c4c96
--- /dev/null
+++ b/drivers/char/drm/via_drv.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2003 S3 Graphics, Inc. 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
+ * VIA, S3 GRAPHICS, 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.
+ */
+#ifndef _VIA_DRV_H_
+#define _VIA_DRV_H_
+
+#define DRIVER_AUTHOR "VIA"
+
+#define DRIVER_NAME "via"
+#define DRIVER_DESC "VIA Unichrome / Pro"
+#define DRIVER_DATE "20050523"
+
+#define DRIVER_MAJOR 2
+#define DRIVER_MINOR 6
+#define DRIVER_PATCHLEVEL 3
+
+#include "via_verifier.h"
+
+#define VIA_PCI_BUF_SIZE 60000
+#define VIA_FIRE_BUF_SIZE 1024
+#define VIA_NUM_IRQS 2
+
+
+
+typedef struct drm_via_ring_buffer {
+ drm_map_t map;
+ char *virtual_start;
+} drm_via_ring_buffer_t;
+
+typedef uint32_t maskarray_t[5];
+
+typedef struct drm_via_irq {
+ atomic_t irq_received;
+ uint32_t pending_mask;
+ uint32_t enable_mask;
+ wait_queue_head_t irq_queue;
+} drm_via_irq_t;
+
+typedef struct drm_via_private {
+ drm_via_sarea_t *sarea_priv;
+ drm_map_t *sarea;
+ drm_map_t *fb;
+ drm_map_t *mmio;
+ unsigned long agpAddr;
+ wait_queue_head_t decoder_queue[VIA_NR_XVMC_LOCKS];
+ char *dma_ptr;
+ unsigned int dma_low;
+ unsigned int dma_high;
+ unsigned int dma_offset;
+ uint32_t dma_wrap;
+ volatile uint32_t *last_pause_ptr;
+ volatile uint32_t *hw_addr_ptr;
+ drm_via_ring_buffer_t ring;
+ struct timeval last_vblank;
+ 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;
+ int pro_group_a;
+ drm_via_irq_t via_irqs[VIA_NUM_IRQS];
+ unsigned num_irqs;
+ maskarray_t *irq_masks;
+ uint32_t irq_enable_mask;
+ uint32_t irq_pending_mask;
+} drm_via_private_t;
+
+/* VIA MMIO register access */
+#define VIA_BASE ((dev_priv->mmio))
+
+#define VIA_READ(reg) DRM_READ32(VIA_BASE, reg)
+#define VIA_WRITE(reg,val) DRM_WRITE32(VIA_BASE, reg, val)
+#define VIA_READ8(reg) DRM_READ8(VIA_BASE, reg)
+#define VIA_WRITE8(reg,val) DRM_WRITE8(VIA_BASE, reg, val)
+
+extern int via_init_context(drm_device_t * dev, int context);
+extern int via_final_context(drm_device_t * dev, int context);
+
+extern int via_do_cleanup_map(drm_device_t * dev);
+extern int via_map_init(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int via_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence);
+
+extern irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS);
+extern void via_driver_irq_preinstall(drm_device_t * dev);
+extern void via_driver_irq_postinstall(drm_device_t * dev);
+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_driver_dma_quiescent(drm_device_t * dev);
+extern void via_init_futex(drm_via_private_t *dev_priv);
+extern void via_cleanup_futex(drm_via_private_t *dev_priv);
+extern void via_release_futex(drm_via_private_t *dev_priv, int context);
+
+
+#endif
diff --git a/drivers/char/drm/via_ds.c b/drivers/char/drm/via_ds.c
new file mode 100644
index 000000000000..daf3df75a20e
--- /dev/null
+++ b/drivers/char/drm/via_ds.c
@@ -0,0 +1,280 @@
+/*
+ * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
+ * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan.
+ *
+ * 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
+ * VIA, S3 GRAPHICS, 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.
+ */
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/poll.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+
+#include "via_ds.h"
+extern unsigned int VIA_DEBUG;
+
+set_t *via_setInit(void)
+{
+ int i;
+ set_t *set;
+ set = (set_t *) drm_alloc(sizeof(set_t), DRM_MEM_DRIVER);
+ for (i = 0; i < SET_SIZE; i++) {
+ set->list[i].free_next = i + 1;
+ set->list[i].alloc_next = -1;
+ }
+ set->list[SET_SIZE - 1].free_next = -1;
+ set->free = 0;
+ set->alloc = -1;
+ set->trace = -1;
+ return set;
+}
+
+int via_setAdd(set_t * set, ITEM_TYPE item)
+{
+ int free = set->free;
+ if (free != -1) {
+ set->list[free].val = item;
+ set->free = set->list[free].free_next;
+ } else {
+ return 0;
+ }
+ set->list[free].alloc_next = set->alloc;
+ set->alloc = free;
+ set->list[free].free_next = -1;
+ return 1;
+}
+
+int via_setDel(set_t * set, ITEM_TYPE item)
+{
+ int alloc = set->alloc;
+ int prev = -1;
+
+ while (alloc != -1) {
+ if (set->list[alloc].val == item) {
+ if (prev != -1)
+ set->list[prev].alloc_next =
+ set->list[alloc].alloc_next;
+ else
+ set->alloc = set->list[alloc].alloc_next;
+ break;
+ }
+ prev = alloc;
+ alloc = set->list[alloc].alloc_next;
+ }
+
+ if (alloc == -1)
+ return 0;
+
+ set->list[alloc].free_next = set->free;
+ set->free = alloc;
+ set->list[alloc].alloc_next = -1;
+
+ return 1;
+}
+
+/* setFirst -> setAdd -> setNext is wrong */
+
+int via_setFirst(set_t * set, ITEM_TYPE * item)
+{
+ if (set->alloc == -1)
+ return 0;
+
+ *item = set->list[set->alloc].val;
+ set->trace = set->list[set->alloc].alloc_next;
+
+ return 1;
+}
+
+int via_setNext(set_t * set, ITEM_TYPE * item)
+{
+ if (set->trace == -1)
+ return 0;
+
+ *item = set->list[set->trace].val;
+ set->trace = set->list[set->trace].alloc_next;
+
+ return 1;
+}
+
+int via_setDestroy(set_t * set)
+{
+ drm_free(set, sizeof(set_t), DRM_MEM_DRIVER);
+
+ return 1;
+}
+
+#define ISFREE(bptr) ((bptr)->free)
+
+#define fprintf(fmt, arg...) do{}while(0)
+
+memHeap_t *via_mmInit(int ofs, int size)
+{
+ PMemBlock blocks;
+
+ if (size <= 0)
+ return 0;
+
+ blocks = (TMemBlock *) drm_calloc(1, sizeof(TMemBlock), DRM_MEM_DRIVER);
+
+ if (blocks) {
+ blocks->ofs = ofs;
+ blocks->size = size;
+ blocks->free = 1;
+ return (memHeap_t *) blocks;
+ } else
+ return 0;
+}
+
+static TMemBlock *SliceBlock(TMemBlock * p,
+ int startofs, int size,
+ int reserved, int alignment)
+{
+ TMemBlock *newblock;
+
+ /* break left */
+ if (startofs > p->ofs) {
+ newblock =
+ (TMemBlock *) drm_calloc(1, sizeof(TMemBlock),
+ DRM_MEM_DRIVER);
+ newblock->ofs = startofs;
+ newblock->size = p->size - (startofs - p->ofs);
+ newblock->free = 1;
+ newblock->next = p->next;
+ p->size -= newblock->size;
+ p->next = newblock;
+ p = newblock;
+ }
+
+ /* break right */
+ if (size < p->size) {
+ newblock =
+ (TMemBlock *) drm_calloc(1, sizeof(TMemBlock),
+ DRM_MEM_DRIVER);
+ newblock->ofs = startofs + size;
+ newblock->size = p->size - size;
+ newblock->free = 1;
+ newblock->next = p->next;
+ p->size = size;
+ p->next = newblock;
+ }
+
+ /* p = middle block */
+ p->align = alignment;
+ p->free = 0;
+ p->reserved = reserved;
+ return p;
+}
+
+PMemBlock via_mmAllocMem(memHeap_t * heap, int size, int align2,
+ int startSearch)
+{
+ int mask, startofs, endofs;
+ TMemBlock *p;
+
+ if (!heap || align2 < 0 || size <= 0)
+ return NULL;
+
+ mask = (1 << align2) - 1;
+ startofs = 0;
+ p = (TMemBlock *) heap;
+
+ while (p) {
+ if (ISFREE(p)) {
+ startofs = (p->ofs + mask) & ~mask;
+
+ if (startofs < startSearch)
+ startofs = startSearch;
+
+ endofs = startofs + size;
+
+ if (endofs <= (p->ofs + p->size))
+ break;
+ }
+
+ p = p->next;
+ }
+
+ if (!p)
+ return NULL;
+
+ p = SliceBlock(p, startofs, size, 0, mask + 1);
+ p->heap = heap;
+
+ return p;
+}
+
+static __inline__ int Join2Blocks(TMemBlock * p)
+{
+ if (p->free && p->next && p->next->free) {
+ TMemBlock *q = p->next;
+ p->size += q->size;
+ p->next = q->next;
+ drm_free(q, sizeof(TMemBlock), DRM_MEM_DRIVER);
+
+ return 1;
+ }
+
+ return 0;
+}
+
+int via_mmFreeMem(PMemBlock b)
+{
+ TMemBlock *p, *prev;
+
+ if (!b)
+ return 0;
+
+ if (!b->heap) {
+ fprintf(stderr, "no heap\n");
+
+ return -1;
+ }
+
+ p = b->heap;
+ prev = NULL;
+
+ while (p && p != b) {
+ prev = p;
+ p = p->next;
+ }
+
+ if (!p || p->free || p->reserved) {
+ if (!p)
+ fprintf(stderr, "block not found in heap\n");
+ else if (p->free)
+ fprintf(stderr, "block already free\n");
+ else
+ fprintf(stderr, "block is reserved\n");
+
+ return -1;
+ }
+
+ p->free = 1;
+ Join2Blocks(p);
+
+ if (prev)
+ Join2Blocks(prev);
+
+ return 0;
+}
diff --git a/drivers/char/drm/via_ds.h b/drivers/char/drm/via_ds.h
new file mode 100644
index 000000000000..be9c7f9f1aee
--- /dev/null
+++ b/drivers/char/drm/via_ds.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
+ * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan.
+ * 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
+ * VIA, S3 GRAPHICS, 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.
+ */
+#ifndef _via_ds_h_
+#define _via_ds_h_
+
+#include "drmP.h"
+
+/* Set Data Structure */
+#define SET_SIZE 5000
+typedef unsigned long ITEM_TYPE;
+
+typedef struct {
+ ITEM_TYPE val;
+ int alloc_next, free_next;
+} list_item_t;
+
+typedef struct {
+ int alloc;
+ int free;
+ int trace;
+ list_item_t list[SET_SIZE];
+} set_t;
+
+set_t *via_setInit(void);
+int via_setAdd(set_t * set, ITEM_TYPE item);
+int via_setDel(set_t * set, ITEM_TYPE item);
+int via_setFirst(set_t * set, ITEM_TYPE * item);
+int via_setNext(set_t * set, ITEM_TYPE * item);
+int via_setDestroy(set_t * set);
+
+#endif
+
+#ifndef MM_INC
+#define MM_INC
+
+struct mem_block_t {
+ struct mem_block_t *next;
+ struct mem_block_t *heap;
+ int ofs, size;
+ int align;
+ int free:1;
+ int reserved:1;
+};
+typedef struct mem_block_t TMemBlock;
+typedef struct mem_block_t *PMemBlock;
+
+/* a heap is just the first block in a chain */
+typedef struct mem_block_t memHeap_t;
+
+static __inline__ int mmBlockSize(PMemBlock b)
+{
+ return b->size;
+}
+
+static __inline__ int mmOffset(PMemBlock b)
+{
+ return b->ofs;
+}
+
+static __inline__ void mmMarkReserved(PMemBlock b)
+{
+ b->reserved = 1;
+}
+
+/*
+ * input: total size in bytes
+ * return: a heap pointer if OK, NULL if error
+ */
+memHeap_t *via_mmInit(int ofs, int size);
+
+PMemBlock via_mmAllocMem(memHeap_t * heap, int size, int align2,
+ int startSearch);
+
+/*
+ * Free block starts at offset
+ * input: pointer to a block
+ * return: 0 if OK, -1 if error
+ */
+int via_mmFreeMem(PMemBlock b);
+
+#endif
diff --git a/drivers/char/drm/via_irq.c b/drivers/char/drm/via_irq.c
new file mode 100644
index 000000000000..e8027f3a93b0
--- /dev/null
+++ b/drivers/char/drm/via_irq.c
@@ -0,0 +1,339 @@
+/* via_irq.c
+ *
+ * Copyright 2004 BEAM Ltd.
+ * Copyright 2002 Tungsten Graphics, Inc.
+ * Copyright 2005 Thomas Hellstrom.
+ * 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, sublicense,
+ * 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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * BEAM LTD, TUNGSTEN GRAPHICS 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.
+ *
+ * Authors:
+ * Terry Barnaby <terry1@beam.ltd.uk>
+ * Keith Whitwell <keith@tungstengraphics.com>
+ * Thomas Hellstrom <unichrome@shipmail.org>
+ *
+ * This code provides standard DRM access to the Via Unichrome / Pro Vertical blank
+ * interrupt, as well as an infrastructure to handle other interrupts of the chip.
+ * The refresh rate is also calculated for video playback sync purposes.
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "via_drm.h"
+#include "via_drv.h"
+
+#define VIA_REG_INTERRUPT 0x200
+
+/* VIA_REG_INTERRUPT */
+#define VIA_IRQ_GLOBAL (1 << 31)
+#define VIA_IRQ_VBLANK_ENABLE (1 << 19)
+#define VIA_IRQ_VBLANK_PENDING (1 << 3)
+#define VIA_IRQ_HQV0_ENABLE (1 << 11)
+#define VIA_IRQ_HQV1_ENABLE (1 << 25)
+#define VIA_IRQ_HQV0_PENDING (1 << 9)
+#define VIA_IRQ_HQV1_PENDING (1 << 10)
+
+/*
+ * Device-specific IRQs go here. This type might need to be extended with
+ * the register if there are multiple IRQ control registers.
+ * Currently we activate the HQV interrupts of Unichrome Pro group A.
+ */
+
+static maskarray_t via_pro_group_a_irqs[] = {
+ {VIA_IRQ_HQV0_ENABLE, VIA_IRQ_HQV0_PENDING, 0x000003D0, 0x00008010, 0x00000000 },
+ {VIA_IRQ_HQV1_ENABLE, VIA_IRQ_HQV1_PENDING, 0x000013D0, 0x00008010, 0x00000000 }};
+static int via_num_pro_group_a = sizeof(via_pro_group_a_irqs)/sizeof(maskarray_t);
+
+static maskarray_t via_unichrome_irqs[] = {};
+static int via_num_unichrome = sizeof(via_unichrome_irqs)/sizeof(maskarray_t);
+
+
+static unsigned time_diff(struct timeval *now,struct timeval *then)
+{
+ return (now->tv_usec >= then->tv_usec) ?
+ now->tv_usec - then->tv_usec :
+ 1000000 - (then->tv_usec - now->tv_usec);
+}
+
+irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS)
+{
+ drm_device_t *dev = (drm_device_t *) arg;
+ drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+ u32 status;
+ int handled = 0;
+ struct timeval cur_vblank;
+ drm_via_irq_t *cur_irq = dev_priv->via_irqs;
+ int i;
+
+ status = VIA_READ(VIA_REG_INTERRUPT);
+ if (status & VIA_IRQ_VBLANK_PENDING) {
+ atomic_inc(&dev->vbl_received);
+ if (!(atomic_read(&dev->vbl_received) & 0x0F)) {
+ do_gettimeofday(&cur_vblank);
+ if (dev_priv->last_vblank_valid) {
+ dev_priv->usec_per_vblank =
+ time_diff( &cur_vblank,&dev_priv->last_vblank) >> 4;
+ }
+ dev_priv->last_vblank = cur_vblank;
+ dev_priv->last_vblank_valid = 1;
+ }
+ if (!(atomic_read(&dev->vbl_received) & 0xFF)) {
+ DRM_DEBUG("US per vblank is: %u\n",
+ dev_priv->usec_per_vblank);
+ }
+ DRM_WAKEUP(&dev->vbl_queue);
+ drm_vbl_send_signals(dev);
+ handled = 1;
+ }
+
+
+ for (i=0; i<dev_priv->num_irqs; ++i) {
+ if (status & cur_irq->pending_mask) {
+ atomic_inc( &cur_irq->irq_received );
+ DRM_WAKEUP( &cur_irq->irq_queue );
+ handled = 1;
+ }
+ cur_irq++;
+ }
+
+ /* Acknowlege interrupts */
+ VIA_WRITE(VIA_REG_INTERRUPT, status);
+
+
+ if (handled)
+ return IRQ_HANDLED;
+ else
+ return IRQ_NONE;
+}
+
+static __inline__ void viadrv_acknowledge_irqs(drm_via_private_t * dev_priv)
+{
+ u32 status;
+
+ if (dev_priv) {
+ /* Acknowlege interrupts */
+ status = VIA_READ(VIA_REG_INTERRUPT);
+ VIA_WRITE(VIA_REG_INTERRUPT, status |
+ dev_priv->irq_pending_mask);
+ }
+}
+
+int via_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
+{
+ drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+ unsigned int cur_vblank;
+ int ret = 0;
+
+ DRM_DEBUG("viadrv_vblank_wait\n");
+ if (!dev_priv) {
+ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+ return -EINVAL;
+ }
+
+ viadrv_acknowledge_irqs(dev_priv);
+
+ /* Assume that the user has missed the current sequence number
+ * by about a day rather than she wants to wait for years
+ * using vertical blanks...
+ */
+
+ DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
+ (((cur_vblank = atomic_read(&dev->vbl_received)) -
+ *sequence) <= (1 << 23)));
+
+ *sequence = cur_vblank;
+ return ret;
+}
+
+static int
+via_driver_irq_wait(drm_device_t * dev, unsigned int irq, int force_sequence,
+ unsigned int *sequence)
+{
+ drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+ unsigned int cur_irq_sequence;
+ drm_via_irq_t *cur_irq = dev_priv->via_irqs;
+ int ret = 0;
+ maskarray_t *masks = dev_priv->irq_masks;
+
+ DRM_DEBUG("%s\n", __FUNCTION__);
+
+ if (!dev_priv) {
+ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+ return DRM_ERR(EINVAL);
+ }
+
+ if (irq >= dev_priv->num_irqs ) {
+ DRM_ERROR("%s Trying to wait on unknown irq %d\n", __FUNCTION__, irq);
+ return DRM_ERR(EINVAL);
+ }
+
+ cur_irq += irq;
+
+ if (masks[irq][2] && !force_sequence) {
+ DRM_WAIT_ON(ret, cur_irq->irq_queue, 3 * DRM_HZ,
+ ((VIA_READ(masks[irq][2]) & masks[irq][3]) == masks[irq][4]));
+ cur_irq_sequence = atomic_read(&cur_irq->irq_received);
+ } else {
+ DRM_WAIT_ON(ret, cur_irq->irq_queue, 3 * DRM_HZ,
+ (((cur_irq_sequence = atomic_read(&cur_irq->irq_received)) -
+ *sequence) <= (1 << 23)));
+ }
+ *sequence = cur_irq_sequence;
+ return ret;
+}
+
+
+/*
+ * drm_dma.h hooks
+ */
+
+void via_driver_irq_preinstall(drm_device_t * dev)
+{
+ drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+ u32 status;
+ drm_via_irq_t *cur_irq = dev_priv->via_irqs;
+ int i;
+
+ DRM_DEBUG("driver_irq_preinstall: dev_priv: %p\n", dev_priv);
+ if (dev_priv) {
+
+ dev_priv->irq_enable_mask = VIA_IRQ_VBLANK_ENABLE;
+ dev_priv->irq_pending_mask = VIA_IRQ_VBLANK_PENDING;
+
+ dev_priv->irq_masks = (dev_priv->pro_group_a) ?
+ via_pro_group_a_irqs : via_unichrome_irqs;
+ dev_priv->num_irqs = (dev_priv->pro_group_a) ?
+ via_num_pro_group_a : via_num_unichrome;
+
+ for(i=0; i < dev_priv->num_irqs; ++i) {
+ atomic_set(&cur_irq->irq_received, 0);
+ cur_irq->enable_mask = dev_priv->irq_masks[i][0];
+ cur_irq->pending_mask = dev_priv->irq_masks[i][1];
+ DRM_INIT_WAITQUEUE( &cur_irq->irq_queue );
+ dev_priv->irq_enable_mask |= cur_irq->enable_mask;
+ dev_priv->irq_pending_mask |= cur_irq->pending_mask;
+ cur_irq++;
+
+ DRM_DEBUG("Initializing IRQ %d\n", i);
+ }
+
+ dev_priv->last_vblank_valid = 0;
+
+ // Clear VSync interrupt regs
+ status = VIA_READ(VIA_REG_INTERRUPT);
+ VIA_WRITE(VIA_REG_INTERRUPT, status &
+ ~(dev_priv->irq_enable_mask));
+
+ /* Clear bits if they're already high */
+ viadrv_acknowledge_irqs(dev_priv);
+ }
+}
+
+void via_driver_irq_postinstall(drm_device_t * dev)
+{
+ drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+ u32 status;
+
+ DRM_DEBUG("via_driver_irq_postinstall\n");
+ if (dev_priv) {
+ status = VIA_READ(VIA_REG_INTERRUPT);
+ VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL
+ | dev_priv->irq_enable_mask);
+
+ /* Some magic, oh for some data sheets ! */
+
+ VIA_WRITE8(0x83d4, 0x11);
+ VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30);
+
+ }
+}
+
+void via_driver_irq_uninstall(drm_device_t * dev)
+{
+ drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+ u32 status;
+
+ DRM_DEBUG("driver_irq_uninstall)\n");
+ if (dev_priv) {
+
+ /* Some more magic, oh for some data sheets ! */
+
+ VIA_WRITE8(0x83d4, 0x11);
+ VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) & ~0x30);
+
+ status = VIA_READ(VIA_REG_INTERRUPT);
+ VIA_WRITE(VIA_REG_INTERRUPT, status &
+ ~(VIA_IRQ_VBLANK_ENABLE | dev_priv->irq_enable_mask));
+ }
+}
+
+int via_wait_irq(DRM_IOCTL_ARGS)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+ drm_via_irqwait_t __user *argp = (void __user *)data;
+ drm_via_irqwait_t irqwait;
+ struct timeval now;
+ int ret = 0;
+ drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+ drm_via_irq_t *cur_irq = dev_priv->via_irqs;
+ int force_sequence;
+
+ if (!dev->irq)
+ return DRM_ERR(EINVAL);
+
+ DRM_COPY_FROM_USER_IOCTL(irqwait, argp, sizeof(irqwait));
+ if (irqwait.request.irq >= dev_priv->num_irqs) {
+ DRM_ERROR("%s Trying to wait on unknown irq %d\n", __FUNCTION__,
+ irqwait.request.irq);
+ return DRM_ERR(EINVAL);
+ }
+
+ cur_irq += irqwait.request.irq;
+
+ switch (irqwait.request.type & ~VIA_IRQ_FLAGS_MASK) {
+ case VIA_IRQ_RELATIVE:
+ irqwait.request.sequence += atomic_read(&cur_irq->irq_received);
+ irqwait.request.type &= ~_DRM_VBLANK_RELATIVE;
+ case VIA_IRQ_ABSOLUTE:
+ break;
+ default:
+ return DRM_ERR(EINVAL);
+ }
+
+ if (irqwait.request.type & VIA_IRQ_SIGNAL) {
+ DRM_ERROR("%s Signals on Via IRQs not implemented yet.\n",
+ __FUNCTION__);
+ return DRM_ERR(EINVAL);
+ }
+
+ force_sequence = (irqwait.request.type & VIA_IRQ_FORCE_SEQUENCE);
+
+ ret = via_driver_irq_wait(dev, irqwait.request.irq, force_sequence,
+ &irqwait.request.sequence);
+ do_gettimeofday(&now);
+ irqwait.reply.tval_sec = now.tv_sec;
+ irqwait.reply.tval_usec = now.tv_usec;
+
+ DRM_COPY_TO_USER_IOCTL(argp, irqwait, sizeof(irqwait));
+
+ return ret;
+}
diff --git a/drivers/char/drm/via_map.c b/drivers/char/drm/via_map.c
new file mode 100644
index 000000000000..0be829b6ec65
--- /dev/null
+++ b/drivers/char/drm/via_map.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2003 S3 Graphics, Inc. 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
+ * VIA, S3 GRAPHICS, 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.
+ */
+#include "drmP.h"
+#include "via_drm.h"
+#include "via_drv.h"
+
+static int via_do_init_map(drm_device_t * dev, drm_via_init_t * init)
+{
+ drm_via_private_t *dev_priv;
+
+ DRM_DEBUG("%s\n", __FUNCTION__);
+
+ dev_priv = drm_alloc(sizeof(drm_via_private_t), DRM_MEM_DRIVER);
+ if (dev_priv == NULL)
+ return -ENOMEM;
+
+ memset(dev_priv, 0, sizeof(drm_via_private_t));
+
+ DRM_GETSAREA();
+ if (!dev_priv->sarea) {
+ DRM_ERROR("could not find sarea!\n");
+ dev->dev_private = (void *)dev_priv;
+ via_do_cleanup_map(dev);
+ return -EINVAL;
+ }
+
+ dev_priv->fb = drm_core_findmap(dev, init->fb_offset);
+ if (!dev_priv->fb) {
+ DRM_ERROR("could not find framebuffer!\n");
+ dev->dev_private = (void *)dev_priv;
+ via_do_cleanup_map(dev);
+ return -EINVAL;
+ }
+ dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset);
+ if (!dev_priv->mmio) {
+ DRM_ERROR("could not find mmio region!\n");
+ dev->dev_private = (void *)dev_priv;
+ via_do_cleanup_map(dev);
+ return -EINVAL;
+ }
+
+ dev_priv->sarea_priv =
+ (drm_via_sarea_t *) ((u8 *) dev_priv->sarea->handle +
+ init->sarea_priv_offset);
+
+ dev_priv->agpAddr = init->agpAddr;
+
+ via_init_futex( dev_priv );
+ dev_priv->pro_group_a = (dev->pdev->device == 0x3118);
+
+ dev->dev_private = (void *)dev_priv;
+ return 0;
+}
+
+int via_do_cleanup_map(drm_device_t * dev)
+{
+ if (dev->dev_private) {
+
+ drm_via_private_t *dev_priv = dev->dev_private;
+
+ via_dma_cleanup(dev);
+
+ drm_free(dev_priv, sizeof(drm_via_private_t), DRM_MEM_DRIVER);
+ dev->dev_private = NULL;
+ }
+
+ return 0;
+}
+
+int via_map_init(DRM_IOCTL_ARGS)
+{
+ DRM_DEVICE;
+ drm_via_init_t init;
+
+ DRM_DEBUG("%s\n", __FUNCTION__);
+
+ DRM_COPY_FROM_USER_IOCTL(init, (drm_via_init_t *) data, sizeof(init));
+
+ switch (init.func) {
+ case VIA_INIT_MAP:
+ return via_do_init_map(dev, &init);
+ case VIA_CLEANUP_MAP:
+ return via_do_cleanup_map(dev);
+ }
+
+ return -EINVAL;
+}
+
+
diff --git a/drivers/char/drm/via_mm.c b/drivers/char/drm/via_mm.c
new file mode 100644
index 000000000000..c22712f44d42
--- /dev/null
+++ b/drivers/char/drm/via_mm.c
@@ -0,0 +1,358 @@
+/*
+ * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2003 S3 Graphics, Inc. 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
+ * VIA, S3 GRAPHICS, 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.
+ */
+#include "drmP.h"
+#include "via_drm.h"
+#include "via_drv.h"
+#include "via_ds.h"
+#include "via_mm.h"
+
+#define MAX_CONTEXT 100
+
+typedef struct {
+ int used;
+ int context;
+ set_t *sets[2]; /* 0 for frame buffer, 1 for AGP , 2 for System */
+} via_context_t;
+
+static via_context_t global_ppriv[MAX_CONTEXT];
+
+static int via_agp_alloc(drm_via_mem_t * mem);
+static int via_agp_free(drm_via_mem_t * mem);
+static int via_fb_alloc(drm_via_mem_t * mem);
+static int via_fb_free(drm_via_mem_t * mem);
+
+static int add_alloc_set(int context, int type, unsigned int val)
+{
+ int i, retval = 0;
+
+ for (i = 0; i < MAX_CONTEXT; i++) {
+ if (global_ppriv[i].used && global_ppriv[i].context == context) {
+ retval = via_setAdd(global_ppriv[i].sets[type], val);
+ break;
+ }
+ }
+
+ return retval;
+}
+
+static int del_alloc_set(int context, int type, unsigned int val)
+{
+ int i, retval = 0;
+
+ for (i = 0; i < MAX_CONTEXT; i++)
+ if (global_ppriv[i].used && global_ppriv[i].context == context) {
+ retval = via_setDel(global_ppriv[i].sets[type], val);
+ break;
+ }
+
+ return retval;
+}
+
+/* agp memory management */
+static memHeap_t *AgpHeap = NULL;
+
+int via_agp_init(DRM_IOCTL_ARGS)
+{
+ drm_via_agp_t agp;
+
+ DRM_COPY_FROM_USER_IOCTL(agp, (drm_via_agp_t *) data, sizeof(agp));
+
+ AgpHeap = via_mmInit(agp.offset, agp.size);
+
+ DRM_DEBUG("offset = %lu, size = %lu", (unsigned long)agp.offset, (unsigned long)agp.size);
+
+ return 0;
+}
+
+/* fb memory management */
+static memHeap_t *FBHeap = NULL;
+
+int via_fb_init(DRM_IOCTL_ARGS)
+{
+ drm_via_fb_t fb;
+
+ DRM_COPY_FROM_USER_IOCTL(fb, (drm_via_fb_t *) data, sizeof(fb));
+
+ FBHeap = via_mmInit(fb.offset, fb.size);
+
+ DRM_DEBUG("offset = %lu, size = %lu", (unsigned long)fb.offset, (unsigned long)fb.size);
+
+ return 0;
+}
+
+int via_init_context(struct drm_device *dev, int context)
+{
+ int i;
+
+ for (i = 0; i < MAX_CONTEXT; i++)
+ if (global_ppriv[i].used &&
+ (global_ppriv[i].context == context))
+ break;
+
+ if (i >= MAX_CONTEXT) {
+ for (i = 0; i < MAX_CONTEXT; i++) {
+ if (!global_ppriv[i].used) {
+ global_ppriv[i].context = context;
+ global_ppriv[i].used = 1;
+ global_ppriv[i].sets[0] = via_setInit();
+ global_ppriv[i].sets[1] = via_setInit();
+ DRM_DEBUG("init allocation set, socket=%d,"
+ " context = %d\n", i, context);
+ break;
+ }
+ }
+
+ if ((i >= MAX_CONTEXT) || (global_ppriv[i].sets[0] == NULL) ||
+ (global_ppriv[i].sets[1] == NULL)) {
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+int via_final_context(struct drm_device *dev, int context)
+{
+ int i;
+ drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+
+ for (i = 0; i < MAX_CONTEXT; i++)
+ if (global_ppriv[i].used &&
+ (global_ppriv[i].context == context))
+ break;
+
+ if (i < MAX_CONTEXT) {
+ set_t *set;
+ ITEM_TYPE item;
+ int retval;
+
+ DRM_DEBUG("find socket %d, context = %d\n", i, context);
+
+ /* Video Memory */
+ set = global_ppriv[i].sets[0];
+ retval = via_setFirst(set, &item);
+ while (retval) {
+ DRM_DEBUG("free video memory 0x%lx\n", item);
+ via_mmFreeMem((PMemBlock) item);
+ retval = via_setNext(set, &item);
+ }
+ via_setDestroy(set);
+
+ /* AGP Memory */
+ set = global_ppriv[i].sets[1];
+ retval = via_setFirst(set, &item);
+ while (retval) {
+ DRM_DEBUG("free agp memory 0x%lx\n", item);
+ via_mmFreeMem((PMemBlock) item);
+ retval = via_setNext(set, &item);
+ }
+ via_setDestroy(set);
+ global_ppriv[i].used = 0;
+ }
+ via_release_futex(dev_priv, context);
+
+
+#if defined(__linux__)
+ /* Linux specific until context tracking code gets ported to BSD */
+ /* Last context, perform cleanup */
+ if (dev->ctx_count == 1 && dev->dev_private) {
+ DRM_DEBUG("Last Context\n");
+ if (dev->irq)
+ drm_irq_uninstall(dev);
+
+ via_cleanup_futex(dev_priv);
+ via_do_cleanup_map(dev);
+ }
+#endif
+
+ return 1;
+}
+
+int via_mem_alloc(DRM_IOCTL_ARGS)
+{
+ drm_via_mem_t mem;
+
+ DRM_COPY_FROM_USER_IOCTL(mem, (drm_via_mem_t *) data, sizeof(mem));
+
+ switch (mem.type) {
+ case VIDEO:
+ if (via_fb_alloc(&mem) < 0)
+ return -EFAULT;
+ DRM_COPY_TO_USER_IOCTL((drm_via_mem_t *) data, mem,
+ sizeof(mem));
+ return 0;
+ case AGP:
+ if (via_agp_alloc(&mem) < 0)
+ return -EFAULT;
+ DRM_COPY_TO_USER_IOCTL((drm_via_mem_t *) data, mem,
+ sizeof(mem));
+ return 0;
+ }
+
+ return -EFAULT;
+}
+
+static int via_fb_alloc(drm_via_mem_t * mem)
+{
+ drm_via_mm_t fb;
+ PMemBlock block;
+ int retval = 0;
+
+ if (!FBHeap)
+ return -1;
+
+ fb.size = mem->size;
+ fb.context = mem->context;
+
+ block = via_mmAllocMem(FBHeap, fb.size, 5, 0);
+ if (block) {
+ fb.offset = block->ofs;
+ fb.free = (unsigned long)block;
+ if (!add_alloc_set(fb.context, VIDEO, fb.free)) {
+ DRM_DEBUG("adding to allocation set fails\n");
+ via_mmFreeMem((PMemBlock) fb.free);
+ retval = -1;
+ }
+ } else {
+ fb.offset = 0;
+ fb.size = 0;
+ fb.free = 0;
+ retval = -1;
+ }
+
+ mem->offset = fb.offset;
+ mem->index = fb.free;
+
+ DRM_DEBUG("alloc fb, size = %d, offset = %d\n", fb.size,
+ (int)fb.offset);
+
+ return retval;
+}
+
+static int via_agp_alloc(drm_via_mem_t * mem)
+{
+ drm_via_mm_t agp;
+ PMemBlock block;
+ int retval = 0;
+
+ if (!AgpHeap)
+ return -1;
+
+ agp.size = mem->size;
+ agp.context = mem->context;
+
+ block = via_mmAllocMem(AgpHeap, agp.size, 5, 0);
+ if (block) {
+ agp.offset = block->ofs;
+ agp.free = (unsigned long)block;
+ if (!add_alloc_set(agp.context, AGP, agp.free)) {
+ DRM_DEBUG("adding to allocation set fails\n");
+ via_mmFreeMem((PMemBlock) agp.free);
+ retval = -1;
+ }
+ } else {
+ agp.offset = 0;
+ agp.size = 0;
+ agp.free = 0;
+ }
+
+ mem->offset = agp.offset;
+ mem->index = agp.free;
+
+ DRM_DEBUG("alloc agp, size = %d, offset = %d\n", agp.size,
+ (unsigned int)agp.offset);
+ return retval;
+}
+
+int via_mem_free(DRM_IOCTL_ARGS)
+{
+ drm_via_mem_t mem;
+
+ DRM_COPY_FROM_USER_IOCTL(mem, (drm_via_mem_t *) data, sizeof(mem));
+
+ switch (mem.type) {
+
+ case VIDEO:
+ if (via_fb_free(&mem) == 0)
+ return 0;
+ break;
+ case AGP:
+ if (via_agp_free(&mem) == 0)
+ return 0;
+ break;
+ }
+
+ return -EFAULT;
+}
+
+static int via_fb_free(drm_via_mem_t * mem)
+{
+ drm_via_mm_t fb;
+ int retval = 0;
+
+ if (!FBHeap) {
+ return -1;
+ }
+
+ fb.free = mem->index;
+ fb.context = mem->context;
+
+ if (!fb.free) {
+ return -1;
+
+ }
+
+ via_mmFreeMem((PMemBlock) fb.free);
+
+ if (!del_alloc_set(fb.context, VIDEO, fb.free)) {
+ retval = -1;
+ }
+
+ DRM_DEBUG("free fb, free = %ld\n", fb.free);
+
+ return retval;
+}
+
+static int via_agp_free(drm_via_mem_t * mem)
+{
+ drm_via_mm_t agp;
+
+ int retval = 0;
+
+ agp.free = mem->index;
+ agp.context = mem->context;
+
+ if (!agp.free)
+ return -1;
+
+ via_mmFreeMem((PMemBlock) agp.free);
+
+ if (!del_alloc_set(agp.context, AGP, agp.free)) {
+ retval = -1;
+ }
+
+ DRM_DEBUG("free agp, free = %ld\n", agp.free);
+
+ return retval;
+}
diff --git a/drivers/char/drm/via_mm.h b/drivers/char/drm/via_mm.h
new file mode 100644
index 000000000000..d57efda57c76
--- /dev/null
+++ b/drivers/char/drm/via_mm.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2003 S3 Graphics, Inc. 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
+ * VIA, S3 GRAPHICS, 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.
+ */
+#ifndef _via_drm_mm_h_
+#define _via_drm_mm_h_
+
+typedef struct {
+ unsigned int context;
+ unsigned int size;
+ unsigned long offset;
+ unsigned long free;
+} drm_via_mm_t;
+
+typedef struct {
+ unsigned int size;
+ unsigned long handle;
+ void *virtual;
+} drm_via_dma_t;
+
+#endif
diff --git a/drivers/char/drm/via_verifier.c b/drivers/char/drm/via_verifier.c
new file mode 100644
index 000000000000..07923b0c7a97
--- /dev/null
+++ b/drivers/char/drm/via_verifier.c
@@ -0,0 +1,1061 @@
+/*
+ * Copyright 2004 The Unichrome Project. All Rights Reserved.
+ * Copyright 2005 Thomas Hellstrom. 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 AUTHOR(S), AND/OR THE COPYRIGHT HOLDER(S) 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 Hellstrom 2004, 2005.
+ * This code was written using docs obtained under NDA from VIA Inc.
+ *
+ * Don't run this code directly on an AGP buffer. Due to cache problems it will
+ * be very slow.
+ */
+
+
+#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,
+ state_header2,
+ state_header1,
+ state_vheader5,
+ state_vheader6,
+ state_error
+} verifier_state_t;
+
+
+typedef enum{
+ no_check = 0,
+ check_for_header2,
+ check_for_header1,
+ check_for_header2_err,
+ check_for_header1_err,
+ check_for_fire,
+ check_z_buffer_addr0,
+ check_z_buffer_addr1,
+ check_z_buffer_addr_mode,
+ check_destination_addr0,
+ check_destination_addr1,
+ check_destination_addr_mode,
+ check_for_dummy,
+ check_for_dd,
+ check_texture_addr0,
+ check_texture_addr1,
+ check_texture_addr2,
+ check_texture_addr3,
+ check_texture_addr4,
+ check_texture_addr5,
+ check_texture_addr6,
+ check_texture_addr7,
+ check_texture_addr8,
+ check_texture_addr_mode,
+ check_for_vertex_count,
+ check_number_texunits,
+ forbidden_command
+}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
+ * that does not include any part of the address.
+ */
+
+static drm_via_sequence_t seqs[] = {
+ no_sequence,
+ no_sequence,
+ no_sequence,
+ no_sequence,
+ no_sequence,
+ no_sequence,
+ z_address,
+ z_address,
+ z_address,
+ dest_address,
+ dest_address,
+ dest_address,
+ no_sequence,
+ no_sequence,
+ tex_address,
+ tex_address,
+ tex_address,
+ tex_address,
+ tex_address,
+ tex_address,
+ tex_address,
+ tex_address,
+ tex_address,
+ tex_address,
+ no_sequence
+};
+
+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},
+ {0xee, check_for_fire},
+ {0xcc, check_for_dummy},
+ {0xdd, check_for_dd},
+ {0x00, no_check},
+ {0x10, check_z_buffer_addr0},
+ {0x11, check_z_buffer_addr1},
+ {0x12, check_z_buffer_addr_mode},
+ {0x13, no_check},
+ {0x14, no_check},
+ {0x15, no_check},
+ {0x23, no_check},
+ {0x24, no_check},
+ {0x33, no_check},
+ {0x34, no_check},
+ {0x35, no_check},
+ {0x36, no_check},
+ {0x37, no_check},
+ {0x38, no_check},
+ {0x39, no_check},
+ {0x3A, no_check},
+ {0x3B, no_check},
+ {0x3C, no_check},
+ {0x3D, no_check},
+ {0x3E, no_check},
+ {0x40, check_destination_addr0},
+ {0x41, check_destination_addr1},
+ {0x42, check_destination_addr_mode},
+ {0x43, no_check},
+ {0x44, no_check},
+ {0x50, no_check},
+ {0x51, no_check},
+ {0x52, no_check},
+ {0x53, no_check},
+ {0x54, no_check},
+ {0x55, no_check},
+ {0x56, no_check},
+ {0x57, no_check},
+ {0x58, no_check},
+ {0x70, no_check},
+ {0x71, no_check},
+ {0x78, no_check},
+ {0x79, no_check},
+ {0x7A, no_check},
+ {0x7B, no_check},
+ {0x7C, no_check},
+ {0x7D, check_for_vertex_count}
+};
+
+
+
+static hz_init_t init_table2[] = {
+ {0xf2, check_for_header2_err},
+ {0xf0, check_for_header1_err},
+ {0xee, check_for_fire},
+ {0xcc, check_for_dummy},
+ {0x00, check_texture_addr0},
+ {0x01, check_texture_addr0},
+ {0x02, check_texture_addr0},
+ {0x03, check_texture_addr0},
+ {0x04, check_texture_addr0},
+ {0x05, check_texture_addr0},
+ {0x06, check_texture_addr0},
+ {0x07, check_texture_addr0},
+ {0x08, check_texture_addr0},
+ {0x09, check_texture_addr0},
+ {0x20, check_texture_addr1},
+ {0x21, check_texture_addr1},
+ {0x22, check_texture_addr1},
+ {0x23, check_texture_addr4},
+ {0x2B, check_texture_addr3},
+ {0x2C, check_texture_addr3},
+ {0x2D, check_texture_addr3},
+ {0x2E, check_texture_addr3},
+ {0x2F, check_texture_addr3},
+ {0x30, check_texture_addr3},
+ {0x31, check_texture_addr3},
+ {0x32, check_texture_addr3},
+ {0x33, check_texture_addr3},
+ {0x34, check_texture_addr3},
+ {0x4B, check_texture_addr5},
+ {0x4C, check_texture_addr6},
+ {0x51, check_texture_addr7},
+ {0x52, check_texture_addr8},
+ {0x77, check_texture_addr2},
+ {0x78, no_check},
+ {0x79, no_check},
+ {0x7A, no_check},
+ {0x7B, check_texture_addr_mode},
+ {0x7C, no_check},
+ {0x7D, no_check},
+ {0x7E, no_check},
+ {0x7F, no_check},
+ {0x80, no_check},
+ {0x81, no_check},
+ {0x82, no_check},
+ {0x83, no_check},
+ {0x85, no_check},
+ {0x86, no_check},
+ {0x87, no_check},
+ {0x88, no_check},
+ {0x89, no_check},
+ {0x8A, no_check},
+ {0x90, no_check},
+ {0x91, no_check},
+ {0x92, no_check},
+ {0x93, no_check}
+};
+
+static hz_init_t init_table3[] = {
+ {0xf2, check_for_header2_err},
+ {0xf0, check_for_header1_err},
+ {0xcc, check_for_dummy},
+ {0x00, check_number_texunits}
+};
+
+
+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)
+{
+ if ((*buf - buf_end) >= 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)
+{
+ struct list_head *list;
+ drm_map_list_t *r_list;
+ drm_map_t *map = seq->map_cache;
+
+ 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)) {
+ seq->map_cache = map;
+ return map;
+ }
+ }
+ return NULL;
+}
+
+
+/*
+ * 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.
+ * 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)
+{
+ 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);
+ break;
+ case tex_address:
+ 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;
+ uint32_t *addr, *pitch, *height, tex;
+ unsigned i;
+
+ if (end > 9) end = 9;
+ if (start > 9) start = 9;
+
+ 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) {
+ tmp = *addr++;
+ if (tmp < lo) lo = tmp;
+ 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");
+ return 2;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ cur_seq->unfinished = no_sequence;
+ return 0;
+}
+
+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;
+ }
+
+ switch(hz) {
+ case check_for_header2:
+ if (cmd == HALCYON_HEADER2) return 1;
+ return 0;
+ case check_for_header1:
+ if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1) return 1;
+ return 0;
+ case check_for_header2_err:
+ 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;
+ DRM_ERROR("Illegal DMA HALCYON_HEADER1 command\n");
+ break;
+ case check_for_fire:
+ 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;
+ DRM_ERROR("Illegal DMA HC_DUMMY command\n");
+ break;
+ case check_for_dd:
+ 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);
+ return 0;
+ case check_z_buffer_addr1:
+ cur_seq->unfinished = z_address;
+ cur_seq->z_addr = (cur_seq->z_addr & 0x00FFFFFF) |
+ ((cmd & 0xFF) << 24);
+ return 0;
+ case check_z_buffer_addr_mode:
+ cur_seq->unfinished = z_address;
+ 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);
+ return 0;
+ case check_destination_addr1:
+ cur_seq->unfinished = dest_address;
+ cur_seq->d_addr = (cur_seq->d_addr & 0x00FFFFFF) |
+ ((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;
+ case check_texture_addr0:
+ cur_seq->unfinished = tex_address;
+ tmp = (cmd >> 24);
+ tmp_addr = &cur_seq->t_addr[cur_seq->texture][tmp];
+ *tmp_addr = (*tmp_addr & 0xFF000000) | (cmd & 0x00FFFFFF);
+ return 0;
+ case check_texture_addr1:
+ cur_seq->unfinished = tex_address;
+ tmp = ((cmd >> 24) - 0x20);
+ tmp += tmp << 1;
+ tmp_addr = &cur_seq->t_addr[cur_seq->texture][tmp];
+ *tmp_addr = (*tmp_addr & 0x00FFFFFF) | ((cmd & 0xFF) << 24);
+ tmp_addr++;
+ *tmp_addr = (*tmp_addr & 0x00FFFFFF) | ((cmd & 0xFF00) << 16);
+ tmp_addr++;
+ *tmp_addr = (*tmp_addr & 0x00FFFFFF) | ((cmd & 0xFF0000) << 8);
+ return 0;
+ case check_texture_addr2:
+ cur_seq->unfinished = tex_address;
+ cur_seq->tex_level_lo[tmp = cur_seq->texture] = cmd & 0x3F;
+ cur_seq->tex_level_hi[tmp] = (cmd & 0xFC0) >> 6;
+ 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;
+ }
+ return 0;
+ case check_texture_addr4:
+ cur_seq->unfinished = tex_address;
+ tmp_addr = &cur_seq->t_addr[cur_seq->texture][9];
+ *tmp_addr = (*tmp_addr & 0x00FFFFFF) | ((cmd & 0xFF) << 24);
+ return 0;
+ case check_texture_addr5:
+ case check_texture_addr6:
+ 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;
+ tmp_addr = &(cur_seq->height[cur_seq->texture][0]);
+ tmp_addr[5] = 1 << ((cmd & 0x00F00000) >> 20);
+ tmp_addr[4] = 1 << ((cmd & 0x000F0000) >> 16);
+ tmp_addr[3] = 1 << ((cmd & 0x0000F000) >> 12);
+ tmp_addr[2] = 1 << ((cmd & 0x00000F00) >> 8);
+ tmp_addr[1] = 1 << ((cmd & 0x000000F0) >> 4);
+ tmp_addr[0] = 1 << (cmd & 0x0000000F);
+ return 0;
+ case check_texture_addr8:
+ 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[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");
+ return 2;
+ }
+ cur_seq->agp_texture = (tmp == 3);
+ 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;
+ return 0;
+ default:
+ DRM_ERROR("Illegal DMA data: 0x%x\n", cmd);
+ return 2;
+ }
+ return 2;
+}
+
+
+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;
+ const uint32_t *buf = *buffer;
+
+ while(buf < buf_end) {
+ have_fire = 0;
+ if ((buf_end - buf) < 2) {
+ DRM_ERROR("Unexpected termination of primitive list.\n");
+ ret = 1;
+ 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",
+ *buf);
+ ret = 1;
+ break;
+ }
+ 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 (*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)
+ buf++;
+ break;
+ }
+ 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;
+ }
+ if ((ret = eat_words(&buf, buf_end, dw_count)))
+ break;
+ }
+ if (buf >= buf_end && !have_fire) {
+ DRM_ERROR("Missing Vertex Fire command or verifier "
+ "lost sync.\n");
+ 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;
+}
+
+
+
+
+
+static __inline__ verifier_state_t
+via_check_header2( uint32_t const **buffer, const uint32_t *buf_end,
+ drm_via_state_t *hc_state)
+{
+ uint32_t cmd;
+ int hz_mode;
+ hazard_t hz;
+ 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");
+ return state_error;
+ }
+ buf++;
+ cmd = (*buf++ & 0xFFFF0000) >> 16;
+
+ switch(cmd) {
+ case HC_ParaType_CmdVdata:
+ if (via_check_prim_list(&buf, buf_end, hc_state ))
+ return state_error;
+ *buffer = buf;
+ return state_command;
+ case HC_ParaType_NotTex:
+ hz_table = table1;
+ break;
+ case HC_ParaType_Tex:
+ hc_state->texture = 0;
+ hz_table = table2;
+ break;
+ case (HC_ParaType_Tex | (HC_SubType_Tex1 << 8)):
+ hc_state->texture = 1;
+ hz_table = table2;
+ break;
+ case (HC_ParaType_Tex | (HC_SubType_TexGeneral << 8)):
+ hz_table = table3;
+ break;
+ case HC_ParaType_Auto:
+ if (eat_words(&buf, buf_end, 2))
+ return state_error;
+ *buffer = buf;
+ return state_command;
+ case (HC_ParaType_Palette | (HC_SubType_Stipple << 8)):
+ if (eat_words(&buf, buf_end, 32))
+ return state_error;
+ *buffer = buf;
+ return state_command;
+ case (HC_ParaType_Palette | (HC_SubType_TexPalette0 << 8)):
+ case (HC_ParaType_Palette | (HC_SubType_TexPalette1 << 8)):
+ DRM_ERROR("Texture palettes are rejected because of "
+ "lack of info how to determine their size.\n");
+ return state_error;
+ case (HC_ParaType_Palette | (HC_SubType_FogTable << 8)):
+ DRM_ERROR("Fog factor palettes are rejected because of "
+ "lack of info how to determine their size.\n");
+ return state_error;
+ default:
+
+ /*
+ * There are some unimplemented HC_ParaTypes here, that
+ * need to be implemented if the Mesa driver is extended.
+ */
+
+ DRM_ERROR("Invalid or unimplemented HALCYON_HEADER2 "
+ "DMA subcommand: 0x%x. Previous dword: 0x%x\n",
+ cmd, *(buf -2));
+ *buffer = buf;
+ return state_error;
+ }
+
+ while(buf < buf_end) {
+ cmd = *buf++;
+ if ((hz = hz_table[cmd >> 24])) {
+ if ((hz_mode = investigate_hazard(cmd, hz, hc_state))) {
+ if (hz_mode == 1) {
+ buf--;
+ break;
+ }
+ return state_error;
+ }
+ } else if (hc_state->unfinished &&
+ finish_current_sequence(hc_state)) {
+ return state_error;
+ }
+ }
+ if (hc_state->unfinished && finish_current_sequence(hc_state)) {
+ return state_error;
+ }
+ *buffer = buf;
+ return state_command;
+}
+
+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)
+{
+ uint32_t cmd;
+ const uint32_t *buf = *buffer;
+ 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) {
+ 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++);
+ burst += 4;
+ }
+ if ( ( buf < buf_end ) && ((*buf & HALCYON_FIREMASK) == HALCYON_FIRECMD))
+ buf++;
+
+ 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;
+ }
+ }
+ *buffer = buf;
+ return state_command;
+}
+
+
+
+static __inline__ int
+verify_mmio_address( uint32_t address)
+{
+ 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 ) {
+ DRM_ERROR("Invalid VIDEO DMA command. "
+ "Attempt to access VGA registers.\n");
+ return 1;
+ }
+ return 0;
+}
+
+static __inline__ int
+verify_video_tail( uint32_t const **buffer, const uint32_t *buf_end, uint32_t dwords)
+{
+ const uint32_t *buf = *buffer;
+
+ if (buf_end - buf < dwords) {
+ DRM_ERROR("Illegal termination of video command.\n");
+ return 1;
+ }
+ while (dwords--) {
+ if (*buf++) {
+ DRM_ERROR("Illegal video command tail.\n");
+ return 1;
+ }
+ }
+ *buffer = buf;
+ return 0;
+}
+
+
+static __inline__ verifier_state_t
+via_check_header1( uint32_t const **buffer, const uint32_t *buf_end )
+{
+ uint32_t cmd;
+ const uint32_t *buf = *buffer;
+ verifier_state_t ret = state_command;
+
+ while (buf < buf_end) {
+ cmd = *buf;
+ if ((cmd > ((0x3FF >> 2) | 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)
+ break;
+ DRM_ERROR("Invalid HALCYON_HEADER1 command. "
+ "Attempt to access VGA registers.\n");
+ ret = state_error;
+ break;
+ } else {
+ buf += 2;
+ }
+ }
+ *buffer = buf;
+ return ret;
+}
+
+static __inline__ verifier_state_t
+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);
+ buf++;
+ }
+ *buffer = buf;
+ return state_command;
+}
+
+static __inline__ verifier_state_t
+via_check_vheader5( uint32_t const **buffer, const uint32_t *buf_end )
+{
+ uint32_t data;
+ const uint32_t *buf = *buffer;
+
+ if (buf_end - buf < 4) {
+ DRM_ERROR("Illegal termination of video header5 command\n");
+ return state_error;
+ }
+
+ data = *buf++ & ~VIA_VIDEOMASK;
+ if (verify_mmio_address(data))
+ return state_error;
+
+ data = *buf++;
+ if (*buf++ != 0x00F50000) {
+ DRM_ERROR("Illegal header5 header data\n");
+ return state_error;
+ }
+ if (*buf++ != 0x00000000) {
+ DRM_ERROR("Illegal header5 header data\n");
+ return state_error;
+ }
+ if (eat_words(&buf, buf_end, data))
+ return state_error;
+ 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 )
+{
+ uint32_t addr, count, i;
+ const uint32_t *buf = *buffer;
+
+ addr = *buf++ & ~VIA_VIDEOMASK;
+ i = count = *buf;
+ buf += 3;
+ while(i--) {
+ VIA_WRITE(addr, *buf++);
+ }
+ if (count & 3) buf += 4 - (count & 3);
+ *buffer = buf;
+ return state_command;
+}
+
+
+static __inline__ verifier_state_t
+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;
+ }
+ buf++;
+ data = *buf++;
+ if (*buf++ != 0x00F60000) {
+ DRM_ERROR("Illegal header6 header data\n");
+ return state_error;
+ }
+ if (*buf++ != 0x00000000) {
+ DRM_ERROR("Illegal header6 header data\n");
+ return state_error;
+ }
+ if ((buf_end - buf) < (data << 1)) {
+ DRM_ERROR("Illegal termination of video header6 command\n");
+ return state_error;
+ }
+ for (i=0; i<data; ++i) {
+ if (verify_mmio_address(*buf++))
+ return state_error;
+ buf++;
+ }
+ data <<= 1;
+ 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_vheader6( drm_via_private_t *dev_priv, uint32_t const **buffer, const uint32_t *buf_end )
+{
+
+ uint32_t addr, count, i;
+ const uint32_t *buf = *buffer;
+
+ i = count = *++buf;
+ buf += 3;
+ while(i--) {
+ addr = *buf++;
+ VIA_WRITE(addr, *buf++);
+ }
+ count <<= 1;
+ 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)
+{
+
+ 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;
+ int pro_group_a = dev_priv->pro_group_a;
+
+ hc_state->dev = dev;
+ hc_state->unfinished = no_sequence;
+ hc_state->map_cache = NULL;
+ hc_state->agp = agp;
+ hc_state->buf_start = buf;
+ dev_priv->num_fire_offsets = 0;
+
+ while (buf < buf_end) {
+
+ switch (state) {
+ case state_header2:
+ state = via_check_header2( &buf, buf_end, hc_state );
+ break;
+ case state_header1:
+ state = via_check_header1( &buf, buf_end );
+ break;
+ case state_vheader5:
+ state = via_check_vheader5( &buf, buf_end );
+ break;
+ case state_vheader6:
+ state = via_check_vheader6( &buf, buf_end );
+ break;
+ case state_command:
+ if (HALCYON_HEADER2 == (cmd = *buf))
+ state = state_header2;
+ else if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1)
+ state = state_header1;
+ else if (pro_group_a && (cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5)
+ state = state_vheader5;
+ else if (pro_group_a && (cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6)
+ state = state_vheader6;
+ 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);
+ }
+ }
+ if (state == state_error) {
+ *hc_state = saved_state;
+ return DRM_ERR(EINVAL);
+ }
+ return 0;
+}
+
+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 );
+ 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 );
+ break;
+ case state_header1:
+ state = via_parse_header1( dev_priv, &buf, buf_end );
+ break;
+ case state_vheader5:
+ state = via_parse_vheader5( dev_priv, &buf, buf_end );
+ break;
+ case state_vheader6:
+ state = via_parse_vheader6( dev_priv, &buf, buf_end );
+ break;
+ case state_command:
+ if (HALCYON_HEADER2 == (cmd = *buf))
+ state = state_header2;
+ 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);
+ state = state_error;
+ }
+ break;
+ case state_error:
+ default:
+ return DRM_ERR(EINVAL);
+ }
+ }
+ if (state == state_error) {
+ return DRM_ERR(EINVAL);
+ }
+ return 0;
+}
+
+
+
+static void
+setup_hazard_table(hz_init_t init_table[], hazard_t table[], int size)
+{
+ int i;
+
+ for(i=0; i<256; ++i) {
+ table[i] = forbidden_command;
+ }
+
+ for(i=0; i<size; ++i) {
+ table[init_table[i].code] = init_table[i].hz;
+ }
+}
+
+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));
+}
diff --git a/drivers/char/drm/via_verifier.h b/drivers/char/drm/via_verifier.h
new file mode 100644
index 000000000000..a8e13592620f
--- /dev/null
+++ b/drivers/char/drm/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
diff --git a/drivers/char/drm/via_video.c b/drivers/char/drm/via_video.c
new file mode 100644
index 000000000000..37a61c67b292
--- /dev/null
+++ b/drivers/char/drm/via_video.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2005 Thomas Hellstrom. 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 AUTHOR(S), AND/OR THE COPYRIGHT HOLDER(S) 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 Hellstrom 2005.
+ *
+ * Video and XvMC related functions.
+ */
+
+#include "drmP.h"
+#include "via_drm.h"
+#include "via_drv.h"
+
+void
+via_init_futex(drm_via_private_t *dev_priv)
+{
+ unsigned int i;
+
+ DRM_DEBUG("%s\n", __FUNCTION__);
+
+ for (i = 0; i < VIA_NR_XVMC_LOCKS; ++i) {
+ DRM_INIT_WAITQUEUE(&(dev_priv->decoder_queue[i]));
+ XVMCLOCKPTR(dev_priv->sarea_priv, i)->lock = 0;
+ }
+}
+
+void
+via_cleanup_futex(drm_via_private_t *dev_priv)
+{
+}
+
+void
+via_release_futex(drm_via_private_t *dev_priv, int context)
+{
+ unsigned int i;
+ volatile int *lock;
+
+ for (i=0; i < VIA_NR_XVMC_LOCKS; ++i) {
+ lock = (int *) XVMCLOCKPTR(dev_priv->sarea_priv, i);
+ if ( (_DRM_LOCKING_CONTEXT( *lock ) == context)) {
+ if (_DRM_LOCK_IS_HELD( *lock ) && (*lock & _DRM_LOCK_CONT)) {
+ DRM_WAKEUP( &(dev_priv->decoder_queue[i]));
+ }
+ *lock = 0;
+ }
+ }
+}
+
+int
+via_decoder_futex(DRM_IOCTL_ARGS)
+{
+ DRM_DEVICE;
+ drm_via_futex_t fx;
+ volatile int *lock;
+ drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+ drm_via_sarea_t *sAPriv = dev_priv->sarea_priv;
+ int ret = 0;
+
+ DRM_DEBUG("%s\n", __FUNCTION__);
+
+ DRM_COPY_FROM_USER_IOCTL(fx, (drm_via_futex_t *) data, sizeof(fx));
+
+ if (fx.lock > VIA_NR_XVMC_LOCKS)
+ return -EFAULT;
+
+ lock = (int *)XVMCLOCKPTR(sAPriv, fx.lock);
+
+ switch (fx.func) {
+ case VIA_FUTEX_WAIT:
+ DRM_WAIT_ON(ret, dev_priv->decoder_queue[fx.lock],
+ (fx.ms / 10) * (DRM_HZ / 100), *lock != fx.val);
+ return ret;
+ case VIA_FUTEX_WAKE:
+ DRM_WAKEUP(&(dev_priv->decoder_queue[fx.lock]));
+ return 0;
+ }
+ return 0;
+}
+
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c
index 88cd858f74d0..cddb789902db 100644
--- a/drivers/char/hvc_console.c
+++ b/drivers/char/hvc_console.c
@@ -22,6 +22,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <linux/config.h>
#include <linux/console.h>
#include <linux/cpumask.h>
#include <linux/init.h>
@@ -40,7 +41,6 @@
#include <linux/delay.h>
#include <asm/uaccess.h>
#include <asm/hvconsole.h>
-#include <asm/vio.h>
#define HVC_MAJOR 229
#define HVC_MINOR 0
@@ -61,16 +61,21 @@
*/
#define HVC_ALLOC_TTY_ADAPTERS 8
-static struct tty_driver *hvc_driver;
-#ifdef CONFIG_MAGIC_SYSRQ
-static int sysrq_pressed;
-#endif
-
#define N_OUTBUF 16
#define N_INBUF 16
#define __ALIGNED__ __attribute__((__aligned__(8)))
+static struct tty_driver *hvc_driver;
+static struct task_struct *hvc_task;
+
+/* Picks up late kicks after list walk but before schedule() */
+static int hvc_kicked;
+
+#ifdef CONFIG_MAGIC_SYSRQ
+static int sysrq_pressed;
+#endif
+
struct hvc_struct {
spinlock_t lock;
int index;
@@ -80,11 +85,11 @@ struct hvc_struct {
char outbuf[N_OUTBUF] __ALIGNED__;
int n_outbuf;
uint32_t vtermno;
+ struct hv_ops *ops;
int irq_requested;
int irq;
struct list_head next;
struct kobject kobj; /* ref count & hvc_struct lifetime */
- struct vio_dev *vdev;
};
/* dynamic list of hvc_struct instances */
@@ -97,26 +102,185 @@ static struct list_head hvc_structs = LIST_HEAD_INIT(hvc_structs);
static DEFINE_SPINLOCK(hvc_structs_lock);
/*
+ * This value is used to assign a tty->index value to a hvc_struct based
+ * upon order of exposure via hvc_probe(), when we can not match it to
+ * a console canidate registered with hvc_instantiate().
+ */
+static int last_hvc = -1;
+
+/*
+ * Do not call this function with either the hvc_strucst_lock or the hvc_struct
+ * lock held. If successful, this function increments the kobject reference
+ * count against the target hvc_struct so it should be released when finished.
+ */
+struct hvc_struct *hvc_get_by_index(int index)
+{
+ struct hvc_struct *hp;
+ unsigned long flags;
+
+ spin_lock(&hvc_structs_lock);
+
+ list_for_each_entry(hp, &hvc_structs, next) {
+ spin_lock_irqsave(&hp->lock, flags);
+ if (hp->index == index) {
+ kobject_get(&hp->kobj);
+ spin_unlock_irqrestore(&hp->lock, flags);
+ spin_unlock(&hvc_structs_lock);
+ return hp;
+ }
+ spin_unlock_irqrestore(&hp->lock, flags);
+ }
+ hp = NULL;
+
+ spin_unlock(&hvc_structs_lock);
+ return hp;
+}
+
+
+/*
* Initial console vtermnos for console API usage prior to full console
* initialization. Any vty adapter outside this range will not have usable
* console interfaces but can still be used as a tty device. This has to be
* static because kmalloc will not work during early console init.
*/
-static uint32_t vtermnos[MAX_NR_HVC_CONSOLES];
+static struct hv_ops *cons_ops[MAX_NR_HVC_CONSOLES];
+static uint32_t vtermnos[MAX_NR_HVC_CONSOLES] =
+ {[0 ... MAX_NR_HVC_CONSOLES - 1] = -1};
-/* Used for accounting purposes */
-static int num_vterms = 0;
+/*
+ * Console APIs, NOT TTY. These APIs are available immediately when
+ * hvc_console_setup() finds adapters.
+ */
-static struct task_struct *hvc_task;
+void hvc_console_print(struct console *co, const char *b, unsigned count)
+{
+ char c[16] __ALIGNED__;
+ unsigned i = 0, n = 0;
+ int r, donecr = 0, index = co->index;
+
+ /* Console access attempt outside of acceptable console range. */
+ if (index >= MAX_NR_HVC_CONSOLES)
+ return;
+
+ /* This console adapter was removed so it is not useable. */
+ if (vtermnos[index] < 0)
+ return;
+
+ while (count > 0 || i > 0) {
+ if (count > 0 && i < sizeof(c)) {
+ if (b[n] == '\n' && !donecr) {
+ c[i++] = '\r';
+ donecr = 1;
+ } else {
+ c[i++] = b[n++];
+ donecr = 0;
+ --count;
+ }
+ } else {
+ r = cons_ops[index]->put_chars(vtermnos[index], c, i);
+ if (r < 0) {
+ /* throw away chars on error */
+ i = 0;
+ } else if (r > 0) {
+ i -= r;
+ if (i > 0)
+ memmove(c, c+r, i);
+ }
+ }
+ }
+}
+
+static struct tty_driver *hvc_console_device(struct console *c, int *index)
+{
+ if (vtermnos[c->index] == -1)
+ return NULL;
+
+ *index = c->index;
+ return hvc_driver;
+}
+
+static int __init hvc_console_setup(struct console *co, char *options)
+{
+ if (co->index < 0 || co->index >= MAX_NR_HVC_CONSOLES)
+ return -ENODEV;
+
+ if (vtermnos[co->index] == -1)
+ return -ENODEV;
+
+ return 0;
+}
+
+struct console hvc_con_driver = {
+ .name = "hvc",
+ .write = hvc_console_print,
+ .device = hvc_console_device,
+ .setup = hvc_console_setup,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
+};
/*
- * This value is used to associate a tty->index value to a hvc_struct based
- * upon order of exposure via hvc_probe().
+ * Early console initialization. Preceeds driver initialization.
+ *
+ * (1) we are first, and the user specified another driver
+ * -- index will remain -1
+ * (2) we are first and the user specified no driver
+ * -- index will be set to 0, then we will fail setup.
+ * (3) we are first and the user specified our driver
+ * -- index will be set to user specified driver, and we will fail
+ * (4) we are after driver, and this initcall will register us
+ * -- if the user didn't specify a driver then the console will match
+ *
+ * Note that for cases 2 and 3, we will match later when the io driver
+ * calls hvc_instantiate() and call register again.
*/
-static int hvc_count = -1;
+static int __init hvc_console_init(void)
+{
+ register_console(&hvc_con_driver);
+ return 0;
+}
+console_initcall(hvc_console_init);
-/* Picks up late kicks after list walk but before schedule() */
-static int hvc_kicked;
+/*
+ * hvc_instantiate() is an early console discovery method which locates
+ * consoles * prior to the vio subsystem discovering them. Hotplugged
+ * vty adapters do NOT get an hvc_instantiate() callback since they
+ * appear after early console init.
+ */
+int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops)
+{
+ struct hvc_struct *hp;
+
+ if (index < 0 || index >= MAX_NR_HVC_CONSOLES)
+ return -1;
+
+ if (vtermnos[index] != -1)
+ return -1;
+
+ /* make sure no no tty has been registerd in this index */
+ hp = hvc_get_by_index(index);
+ if (hp) {
+ kobject_put(&hp->kobj);
+ return -1;
+ }
+
+ vtermnos[index] = vtermno;
+ cons_ops[index] = ops;
+
+ /* reserve all indices upto and including this index */
+ if (last_hvc < index)
+ last_hvc = index;
+
+ /* if this index is what the user requested, then register
+ * now (setup won't fail at this point). It's ok to just
+ * call register again if previously .setup failed.
+ */
+ if (index == hvc_con_driver.index)
+ register_console(&hvc_con_driver);
+
+ return 0;
+}
+EXPORT_SYMBOL(hvc_instantiate);
/* Wake the sleeping khvcd */
static void hvc_kick(void)
@@ -125,13 +289,17 @@ static void hvc_kick(void)
wake_up_process(hvc_task);
}
+static int hvc_poll(struct hvc_struct *hp);
+
/*
* NOTE: This API isn't used if the console adapter doesn't support interrupts.
* In this case the console is poll driven.
*/
static irqreturn_t hvc_handle_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
{
- hvc_kick();
+ /* if hvc_poll request a repoll, then kick the hvcd thread */
+ if (hvc_poll(dev_instance))
+ hvc_kick();
return IRQ_HANDLED;
}
@@ -141,34 +309,6 @@ static void hvc_unthrottle(struct tty_struct *tty)
}
/*
- * Do not call this function with either the hvc_strucst_lock or the hvc_struct
- * lock held. If successful, this function increments the kobject reference
- * count against the target hvc_struct so it should be released when finished.
- */
-struct hvc_struct *hvc_get_by_index(int index)
-{
- struct hvc_struct *hp;
- unsigned long flags;
-
- spin_lock(&hvc_structs_lock);
-
- list_for_each_entry(hp, &hvc_structs, next) {
- spin_lock_irqsave(&hp->lock, flags);
- if (hp->index == index) {
- kobject_get(&hp->kobj);
- spin_unlock_irqrestore(&hp->lock, flags);
- spin_unlock(&hvc_structs_lock);
- return hp;
- }
- spin_unlock_irqrestore(&hp->lock, flags);
- }
- hp = NULL;
-
- spin_unlock(&hvc_structs_lock);
- return hp;
-}
-
-/*
* The TTY interface won't be used until after the vio layer has exposed the vty
* adapter to the kernel.
*/
@@ -329,7 +469,7 @@ static void hvc_push(struct hvc_struct *hp)
{
int n;
- n = hvc_put_chars(hp->vtermno, hp->outbuf, hp->n_outbuf);
+ n = hp->ops->put_chars(hp->vtermno, hp->outbuf, hp->n_outbuf);
if (n <= 0) {
if (n == 0)
return;
@@ -467,7 +607,7 @@ static int hvc_poll(struct hvc_struct *hp)
break;
}
- n = hvc_get_chars(hp->vtermno, buf, count);
+ n = hp->ops->get_chars(hp->vtermno, buf, count);
if (n <= 0) {
/* Hangup the tty when disconnected from host */
if (n == -EPIPE) {
@@ -479,14 +619,17 @@ static int hvc_poll(struct hvc_struct *hp)
}
for (i = 0; i < n; ++i) {
#ifdef CONFIG_MAGIC_SYSRQ
- /* Handle the SysRq Hack */
- if (buf[i] == '\x0f') { /* ^O -- should support a sequence */
- sysrq_pressed = 1;
- continue;
- } else if (sysrq_pressed) {
- handle_sysrq(buf[i], NULL, tty);
- sysrq_pressed = 0;
- continue;
+ if (hp->index == hvc_con_driver.index) {
+ /* Handle the SysRq Hack */
+ /* XXX should support a sequence */
+ if (buf[i] == '\x0f') { /* ^O */
+ sysrq_pressed = 1;
+ continue;
+ } else if (sysrq_pressed) {
+ handle_sysrq(buf[i], NULL, tty);
+ sysrq_pressed = 0;
+ continue;
+ }
}
#endif /* CONFIG_MAGIC_SYSRQ */
tty_insert_flip_char(tty, buf[i], 0);
@@ -497,8 +640,8 @@ static int hvc_poll(struct hvc_struct *hp)
/*
* Account for the total amount read in one loop, and if above
- * 64 bytes, we do a quick schedule loop to let the tty grok the
- * data and eventually throttle us.
+ * 64 bytes, we do a quick schedule loop to let the tty grok
+ * the data and eventually throttle us.
*/
read_total += n;
if (read_total >= 64) {
@@ -542,7 +685,6 @@ int khvcd(void *unused)
if (cpus_empty(cpus_in_xmon)) {
spin_lock(&hvc_structs_lock);
list_for_each_entry(hp, &hvc_structs, next) {
- /*hp = list_entry(node, struct hvc_struct, * next); */
poll_mask |= hvc_poll(hp);
}
spin_unlock(&hvc_structs_lock);
@@ -577,14 +719,6 @@ static struct tty_operations hvc_ops = {
.chars_in_buffer = hvc_chars_in_buffer,
};
-char hvc_driver_name[] = "hvc_console";
-
-static struct vio_device_id hvc_driver_table[] __devinitdata= {
- {"serial", "hvterm1"},
- { NULL, }
-};
-MODULE_DEVICE_TABLE(vio, hvc_driver_table);
-
/* callback when the kboject ref count reaches zero. */
static void destroy_hvc_struct(struct kobject *kobj)
{
@@ -606,41 +740,51 @@ static struct kobj_type hvc_kobj_type = {
.release = destroy_hvc_struct,
};
-static int __devinit hvc_probe(
- struct vio_dev *dev,
- const struct vio_device_id *id)
+struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq,
+ struct hv_ops *ops)
{
struct hvc_struct *hp;
-
- /* probed with invalid parameters. */
- if (!dev || !id)
- return -EPERM;
+ int i;
hp = kmalloc(sizeof(*hp), GFP_KERNEL);
if (!hp)
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
memset(hp, 0x00, sizeof(*hp));
- hp->vtermno = dev->unit_address;
- hp->vdev = dev;
- hp->vdev->dev.driver_data = hp;
- hp->irq = dev->irq;
+
+ hp->vtermno = vtermno;
+ hp->irq = irq;
+ hp->ops = ops;
kobject_init(&hp->kobj);
hp->kobj.ktype = &hvc_kobj_type;
spin_lock_init(&hp->lock);
spin_lock(&hvc_structs_lock);
- hp->index = ++hvc_count;
+
+ /*
+ * find index to use:
+ * see if this vterm id matches one registered for console.
+ */
+ for (i=0; i < MAX_NR_HVC_CONSOLES; i++)
+ if (vtermnos[i] == hp->vtermno)
+ break;
+
+ /* no matching slot, just use a counter */
+ if (i >= MAX_NR_HVC_CONSOLES)
+ i = ++last_hvc;
+
+ hp->index = i;
+
list_add_tail(&(hp->next), &hvc_structs);
spin_unlock(&hvc_structs_lock);
- return 0;
+ return hp;
}
+EXPORT_SYMBOL(hvc_alloc);
-static int __devexit hvc_remove(struct vio_dev *dev)
+int __devexit hvc_remove(struct hvc_struct *hp)
{
- struct hvc_struct *hp = dev->dev.driver_data;
unsigned long flags;
struct kobject *kobjp;
struct tty_struct *tty;
@@ -673,23 +817,14 @@ static int __devexit hvc_remove(struct vio_dev *dev)
tty_hangup(tty);
return 0;
}
-
-static struct vio_driver hvc_vio_driver = {
- .name = hvc_driver_name,
- .id_table = hvc_driver_table,
- .probe = hvc_probe,
- .remove = hvc_remove,
-};
+EXPORT_SYMBOL(hvc_remove);
/* Driver initialization. Follow console initialization. This is where the TTY
* interfaces start to become available. */
int __init hvc_init(void)
{
- int rc;
-
- /* We need more than num_vterms adapters due to hotplug additions. */
+ /* We need more than hvc_count adapters due to hotplug additions. */
hvc_driver = alloc_tty_driver(HVC_ALLOC_TTY_ADAPTERS);
- /* hvc_driver = alloc_tty_driver(num_vterms); */
if (!hvc_driver)
return -ENOMEM;
@@ -716,116 +851,20 @@ int __init hvc_init(void)
return -EIO;
}
- /* Register as a vio device to receive callbacks */
- rc = vio_register_driver(&hvc_vio_driver);
-
- return rc;
+ return 0;
}
+module_init(hvc_init);
-/* This isn't particularily necessary due to this being a console driver but it
- * is nice to be thorough */
+/* This isn't particularily necessary due to this being a console driver
+ * but it is nice to be thorough.
+ */
static void __exit hvc_exit(void)
{
kthread_stop(hvc_task);
- vio_unregister_driver(&hvc_vio_driver);
tty_unregister_driver(hvc_driver);
/* return tty_struct instances allocated in hvc_init(). */
put_tty_driver(hvc_driver);
+ unregister_console(&hvc_con_driver);
}
-
-/*
- * Console APIs, NOT TTY. These APIs are available immediately when
- * hvc_console_setup() finds adapters.
- */
-
-/*
- * hvc_instantiate() is an early console discovery method which locates consoles
- * prior to the vio subsystem discovering them. Hotplugged vty adapters do NOT
- * get an hvc_instantiate() callback since the appear after early console init.
- */
-int hvc_instantiate(uint32_t vtermno, int index)
-{
- if (index < 0 || index >= MAX_NR_HVC_CONSOLES)
- return -1;
-
- if (vtermnos[index] != -1)
- return -1;
-
- vtermnos[index] = vtermno;
- return 0;
-}
-
-void hvc_console_print(struct console *co, const char *b, unsigned count)
-{
- char c[16] __ALIGNED__;
- unsigned i = 0, n = 0;
- int r, donecr = 0;
-
- /* Console access attempt outside of acceptable console range. */
- if (co->index >= MAX_NR_HVC_CONSOLES)
- return;
-
- /* This console adapter was removed so it is not useable. */
- if (vtermnos[co->index] < 0)
- return;
-
- while (count > 0 || i > 0) {
- if (count > 0 && i < sizeof(c)) {
- if (b[n] == '\n' && !donecr) {
- c[i++] = '\r';
- donecr = 1;
- } else {
- c[i++] = b[n++];
- donecr = 0;
- --count;
- }
- } else {
- r = hvc_put_chars(vtermnos[co->index], c, i);
- if (r < 0) {
- /* throw away chars on error */
- i = 0;
- } else if (r > 0) {
- i -= r;
- if (i > 0)
- memmove(c, c+r, i);
- }
- }
- }
-}
-
-static struct tty_driver *hvc_console_device(struct console *c, int *index)
-{
- *index = c->index;
- return hvc_driver;
-}
-
-static int __init hvc_console_setup(struct console *co, char *options)
-{
- return 0;
-}
-
-struct console hvc_con_driver = {
- .name = "hvc",
- .write = hvc_console_print,
- .device = hvc_console_device,
- .setup = hvc_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1,
-};
-
-/* Early console initialization. Preceeds driver initialization. */
-static int __init hvc_console_init(void)
-{
- int i;
-
- for (i=0; i<MAX_NR_HVC_CONSOLES; i++)
- vtermnos[i] = -1;
- num_vterms = hvc_find_vtys();
- register_console(&hvc_con_driver);
- return 0;
-}
-console_initcall(hvc_console_init);
-
-module_init(hvc_init);
module_exit(hvc_exit);
diff --git a/drivers/char/hvc_vio.c b/drivers/char/hvc_vio.c
new file mode 100644
index 000000000000..60bb9152b832
--- /dev/null
+++ b/drivers/char/hvc_vio.c
@@ -0,0 +1,152 @@
+/*
+ * vio driver interface to hvc_console.c
+ *
+ * This code was moved here to allow the remaing code to be reused as a
+ * generic polling mode with semi-reliable transport driver core to the
+ * console and tty subsystems.
+ *
+ *
+ * Copyright (C) 2001 Anton Blanchard <anton@au.ibm.com>, IBM
+ * Copyright (C) 2001 Paul Mackerras <paulus@au.ibm.com>, IBM
+ * Copyright (C) 2004 Benjamin Herrenschmidt <benh@kernel.crashing.org>, IBM Corp.
+ * Copyright (C) 2004 IBM Corporation
+ *
+ * Additional Author(s):
+ * Ryan S. Arnold <rsa@us.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <asm/hvconsole.h>
+#include <asm/vio.h>
+#include <asm/prom.h>
+
+char hvc_driver_name[] = "hvc_console";
+
+static struct vio_device_id hvc_driver_table[] __devinitdata = {
+ {"serial", "hvterm1"},
+ { NULL, }
+};
+MODULE_DEVICE_TABLE(vio, hvc_driver_table);
+
+static int filtered_get_chars(uint32_t vtermno, char *buf, int count)
+{
+ unsigned long got;
+ int i;
+
+ got = hvc_get_chars(vtermno, buf, count);
+
+ /*
+ * Work around a HV bug where it gives us a null
+ * after every \r. -- paulus
+ */
+ for (i = 1; i < got; ++i) {
+ if (buf[i] == 0 && buf[i-1] == '\r') {
+ --got;
+ if (i < got)
+ memmove(&buf[i], &buf[i+1],
+ got - i);
+ }
+ }
+ return got;
+}
+
+static struct hv_ops hvc_get_put_ops = {
+ .get_chars = filtered_get_chars,
+ .put_chars = hvc_put_chars,
+};
+
+static int __devinit hvc_vio_probe(struct vio_dev *vdev,
+ const struct vio_device_id *id)
+{
+ struct hvc_struct *hp;
+
+ /* probed with invalid parameters. */
+ if (!vdev || !id)
+ return -EPERM;
+
+ hp = hvc_alloc(vdev->unit_address, vdev->irq, &hvc_get_put_ops);
+ if (IS_ERR(hp))
+ return PTR_ERR(hp);
+ dev_set_drvdata(&vdev->dev, hp);
+
+ return 0;
+}
+
+static int __devexit hvc_vio_remove(struct vio_dev *vdev)
+{
+ struct hvc_struct *hp = dev_get_drvdata(&vdev->dev);
+
+ return hvc_remove(hp);
+}
+
+static struct vio_driver hvc_vio_driver = {
+ .name = hvc_driver_name,
+ .id_table = hvc_driver_table,
+ .probe = hvc_vio_probe,
+ .remove = hvc_vio_remove,
+ .driver = {
+ .owner = THIS_MODULE,
+ }
+};
+
+static int hvc_vio_init(void)
+{
+ int rc;
+
+ /* Register as a vio device to receive callbacks */
+ rc = vio_register_driver(&hvc_vio_driver);
+
+ return rc;
+}
+module_init(hvc_vio_init); /* after drivers/char/hvc_console.c */
+
+static void hvc_vio_exit(void)
+{
+ vio_unregister_driver(&hvc_vio_driver);
+}
+module_exit(hvc_vio_exit);
+
+/* the device tree order defines our numbering */
+static int hvc_find_vtys(void)
+{
+ struct device_node *vty;
+ int num_found = 0;
+
+ for (vty = of_find_node_by_name(NULL, "vty"); vty != NULL;
+ vty = of_find_node_by_name(vty, "vty")) {
+ uint32_t *vtermno;
+
+ /* We have statically defined space for only a certain number
+ * of console adapters.
+ */
+ if (num_found >= MAX_NR_HVC_CONSOLES)
+ break;
+
+ vtermno = (uint32_t *)get_property(vty, "reg", NULL);
+ if (!vtermno)
+ continue;
+
+ if (device_is_compatible(vty, "hvterm1")) {
+ hvc_instantiate(*vtermno, num_found, &hvc_get_put_ops);
+ ++num_found;
+ }
+ }
+
+ return num_found;
+}
+console_initcall(hvc_find_vtys);
diff --git a/drivers/char/hvsi.c b/drivers/char/hvsi.c
index f1f1192ba2b5..a22aa940e01e 100644
--- a/drivers/char/hvsi.c
+++ b/drivers/char/hvsi.c
@@ -291,15 +291,13 @@ static void dump_packet(uint8_t *packet)
dump_hex(packet, header->len);
}
-/* can't use hvc_get_chars because that strips CRs */
static int hvsi_read(struct hvsi_struct *hp, char *buf, int count)
{
unsigned long got;
- if (plpar_hcall(H_GET_TERM_CHAR, hp->vtermno, 0, 0, 0, &got,
- (unsigned long *)buf, (unsigned long *)buf+1) == H_Success)
- return got;
- return 0;
+ got = hvc_get_chars(hp->vtermno, buf, count);
+
+ return got;
}
static void hvsi_recv_control(struct hvsi_struct *hp, uint8_t *packet,
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c
index edba5a35bf21..09103b3d8f05 100644
--- a/drivers/char/n_tty.c
+++ b/drivers/char/n_tty.c
@@ -770,10 +770,8 @@ send_signal:
}
if (c == '\n') {
if (L_ECHO(tty) || L_ECHONL(tty)) {
- if (tty->read_cnt >= N_TTY_BUF_SIZE-1) {
+ if (tty->read_cnt >= N_TTY_BUF_SIZE-1)
put_char('\a', tty);
- return;
- }
opost('\n', tty);
}
goto handle_newline;
@@ -790,10 +788,8 @@ send_signal:
* XXX are EOL_CHAR and EOL2_CHAR echoed?!?
*/
if (L_ECHO(tty)) {
- if (tty->read_cnt >= N_TTY_BUF_SIZE-1) {
+ if (tty->read_cnt >= N_TTY_BUF_SIZE-1)
put_char('\a', tty);
- return;
- }
/* Record the column of first canon char. */
if (tty->canon_head == tty->read_head)
tty->canon_column = tty->column;
@@ -862,12 +858,9 @@ static int n_tty_receive_room(struct tty_struct *tty)
* that erase characters will be handled. Other excess
* characters will be beeped.
*/
- if (tty->icanon && !tty->canon_data)
- return N_TTY_BUF_SIZE;
-
- if (left > 0)
- return left;
- return 0;
+ if (left <= 0)
+ left = tty->icanon && !tty->canon_data;
+ return left;
}
/**
@@ -1473,13 +1466,17 @@ static ssize_t write_chan(struct tty_struct * tty, struct file * file,
if (tty->driver->flush_chars)
tty->driver->flush_chars(tty);
} else {
- c = tty->driver->write(tty, b, nr);
- if (c < 0) {
- retval = c;
- goto break_out;
+ while (nr > 0) {
+ c = tty->driver->write(tty, b, nr);
+ if (c < 0) {
+ retval = c;
+ goto break_out;
+ }
+ if (!c)
+ break;
+ b += c;
+ nr -= c;
}
- b += c;
- nr -= c;
}
if (!nr)
break;
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index 8f36b1758eb6..7a0c74648124 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -71,7 +71,6 @@
#include <linux/workqueue.h>
#include <linux/hdlc.h>
-#include <pcmcia/version.h>
#include <pcmcia/cs_types.h>
#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
@@ -593,11 +592,6 @@ static dev_link_t *mgslpc_attach(void)
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.EventMask =
- CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
- CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
- CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
- client_reg.event_handler = &mgslpc_event;
client_reg.Version = 0x0210;
client_reg.event_callback_args.client_data = link;
@@ -3093,6 +3087,7 @@ static struct pcmcia_driver mgslpc_driver = {
.name = "synclink_cs",
},
.attach = mgslpc_attach,
+ .event = mgslpc_event,
.detach = mgslpc_detach,
.id_table = mgslpc_ids,
};
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 460b5d475edd..6b11d6b2129f 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -271,7 +271,7 @@ static int random_write_wakeup_thresh = 128;
* samples to avoid wasting CPU time and reduce lock contention.
*/
-static int trickle_thresh = INPUT_POOL_WORDS * 28;
+static int trickle_thresh __read_mostly = INPUT_POOL_WORDS * 28;
static DEFINE_PER_CPU(int, trickle_count) = 0;
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c
index af79805b5576..12d563c648f7 100644
--- a/drivers/char/sysrq.c
+++ b/drivers/char/sysrq.c
@@ -228,7 +228,7 @@ static struct sysrq_key_op sysrq_term_op = {
static void moom_callback(void *ignored)
{
- out_of_memory(GFP_KERNEL);
+ out_of_memory(GFP_KERNEL, 0);
}
static DECLARE_WORK(moom_work, moom_callback, NULL);
OpenPOWER on IntegriCloud