summaryrefslogtreecommitdiff
path: root/linux
diff options
context:
space:
mode:
authorLeif Delgass <ldelgass@users.sourceforge.net>2003-03-30 04:52:48 +0000
committerLeif Delgass <ldelgass@users.sourceforge.net>2003-03-30 04:52:48 +0000
commit89eb66d97db0af9f4444deb4b683e02a97223f67 (patch)
treea70a5cd7f6a4c692cae297cc59915059a0c499a1 /linux
parentae0b8f750ae4ee190f7567fee5aca95d92e7895e (diff)
Merge trunk - 4.3.0, filpmach64-0-0-6-20030330
Diffstat (limited to 'linux')
-rw-r--r--linux/Makefile.kernel6
-rw-r--r--linux/Makefile.linux40
-rw-r--r--linux/drmP.h24
-rw-r--r--linux/drm_agpsupport.h12
-rw-r--r--linux/drm_bufs.h12
-rw-r--r--linux/drm_dma.h38
-rw-r--r--linux/drm_drv.h33
-rw-r--r--linux/drm_fops.h6
-rw-r--r--linux/drm_ioctl.h45
-rw-r--r--linux/drm_lists.h4
-rw-r--r--linux/drm_lock.h10
-rw-r--r--linux/drm_os_linux.h15
-rw-r--r--linux/drm_proc.h6
-rw-r--r--linux/gamma_dma.c35
-rw-r--r--linux/gamma_drv.h10
-rw-r--r--linux/i810.h2
-rw-r--r--linux/i810_dma.c66
-rw-r--r--linux/i810_drv.h30
-rw-r--r--linux/i830.h82
-rw-r--r--linux/i830_dma.c536
-rw-r--r--linux/i830_drm.h100
-rw-r--r--linux/i830_drv.h84
-rw-r--r--linux/i830_irq.c178
-rw-r--r--linux/sis.h2
-rw-r--r--linux/sis_mm.c8
25 files changed, 1094 insertions, 290 deletions
diff --git a/linux/Makefile.kernel b/linux/Makefile.kernel
index c738173d..233b6309 100644
--- a/linux/Makefile.kernel
+++ b/linux/Makefile.kernel
@@ -3,7 +3,7 @@
# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
O_TARGET := drm.o
-list-multi := gamma.o tdfx.o r128.o mga.o i810.o i830.o ffb.o radeon.o mach64.o
+list-multi := gamma.o tdfx.o mach64.o r128.o mga.o i810.o i830.o radeon.o ffb.o
gamma-objs := gamma_drv.o gamma_dma.o
tdfx-objs := tdfx_drv.o
@@ -11,8 +11,8 @@ mach64-objs := mach64_drv.o mach64_dma.o mach64_irq.o mach64_state.o
r128-objs := r128_drv.o r128_cce.o r128_irq.o r128_state.o
mga-objs := mga_drv.o mga_dma.o mga_irq.o mga_state.o mga_warp.o
i810-objs := i810_drv.o i810_dma.o
-i830-objs := i830_drv.o i830_dma.o
-radeon-objs := radeon_drv.o radeon_cp.o radeon_irq.o radeon_state.o
+i830-objs := i830_drv.o i830_dma.o i830_irq.o
+radeon-objs := radeon_drv.o radeon_cp.o radeon_irq.o radeon_mem.o radeon_state.o
ffb-objs := ffb_drv.o ffb_context.o
obj-$(CONFIG_DRM_GAMMA) += gamma.o
diff --git a/linux/Makefile.linux b/linux/Makefile.linux
index 2447af0c..492b0e61 100644
--- a/linux/Makefile.linux
+++ b/linux/Makefile.linux
@@ -32,6 +32,8 @@
# make TREE=/usr/my-kernel-tree/include
#
+SHELL=/bin/sh
+
.SUFFIXES:
# *** Setup
@@ -44,7 +46,8 @@ LIBS =
DRMTEMPLATES = drm_auth.h drm_bufs.h drm_context.h drm_dma.h drm_drawable.h \
drm_drv.h drm_fops.h drm_init.h drm_ioctl.h drm_lists.h \
drm_lock.h drm_memory.h drm_proc.h drm_stub.h drm_vm.h
-DRMHEADERS = drm.h drmP.h drm_sarea.h
+DRMSHARED = drm_sarea.h
+DRMHEADERS = drm.h drmP.h $(DRMSHARED)
GAMMAOBJS = gamma_drv.o gamma_dma.o
GAMMAHEADERS = gamma_drv.h $(DRMHEADERS) $(DRMTEMPLATES)
@@ -54,12 +57,20 @@ TDFXHEADERS = tdfx.h $(DRMHEADERS) $(DRMTEMPLATES)
R128OBJS = r128_drv.o r128_cce.o r128_state.o r128_irq.o
R128HEADERS = r128.h r128_drv.h r128_drm.h $(DRMHEADERS) $(DRMTEMPLATES)
+R128SHARED = r128.h r128_drv.h r128_drm.h r128_cce.c r128_state.c r128_irq.c
+
+MACH64OBJS = mach64_drv.o mach64_dma.o mach64_irq.o mach64_state.o
+MACH64HEADERS = mach64.h mach64_drv.h mach64_drm.h $(DRMHEADERS) \
+ $(DRMTEMPLATES)
+MACH64SHARED = mach64.h mach64_drv.h mach64_drm.h mach64_dma.c mach64_irq.c \
+ mach64_state.c
-RADEONOBJS = radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o radeon_irq.o
+RADEONOBJS = radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o \
+ radeon_irq.o
RADEONHEADERS = radeon.h radeon_drv.h radeon_drm.h $(DRMHEADERS) \
$(DRMTEMPLATES)
-MACH64OBJS= mach64_drv.o mach64_dma.o mach64_irq.o mach64_state.o
-MACH64HEADERS= mach64.h mach64_drv.h mach64_drm.h $(DRMHEADERS) $(DRMTEMPLATES)
+RADEONSHARED = radeon.h radeon_drv.h radeon_drm.h radeon_cp.c radeon_irq.c \
+ radeon_mem.c radeon_state.c
INC = /usr/include
@@ -162,11 +173,13 @@ endif
MGAOBJS = mga_drv.o mga_dma.o mga_state.o mga_warp.o mga_irq.o
MGAHEADERS = mga.h mga_drv.h mga_drm.h $(DRMHEADERS) $(DRMTEMPLATES)
+MGASHARED = mga.h mga_dma.c mga_drm.h mga_drv.h mga_state.c \
+ mga_ucode.h mga_warp.c
I810OBJS = i810_drv.o i810_dma.o
I810HEADERS = i810.h i810_drv.h i810_drm.h $(DRMHEADERS) $(DRMTEMPLATES)
-I830OBJS = i830_drv.o i830_dma.o
+I830OBJS = i830_drv.o i830_dma.o i830_irq.o
I830HEADERS = i830.h i830_drv.h i830_drm.h $(DRMHEADERS) $(DRMTEMPLATES)
endif
@@ -174,6 +187,10 @@ endif
ifeq ($(MACHINE),alpha)
MODCFLAGS+= -ffixed-8 -mno-fp-regs -mcpu=ev56 -Wa,-mev6
endif
+ifeq ($(MACHINE),x86_64)
+MODCFLAGS+= -mcmodel=kernel
+endif
+
MODS += sis.o
@@ -210,6 +227,15 @@ endif
# **** End of configuration
+# Link in shared headers if needed
+
+SHAREDSRC = $(DRMSHARED) $(MGASHARED) $(R128SHARED) $(RADEONSHARED) $(MACH64SHARED)
+SHAREDDIR = ../../../shared/drm/kernel
+
+$(SHAREDSRC):
+ @if [ ! -r $@ ]; then (rm -f $@; set -x; ln -s $(SHAREDDIR)/$@ .); fi
+
+
dristat: dristat.c
$(CC) $(PRGCFLAGS) $< -o $@
@@ -288,3 +314,7 @@ endif
clean cleandir::
rm -f *.o *.a *~ core
+ @for i in $(SHAREDSRC); do \
+ if [ -L $$i ]; then (set -x; rm -f $$i); fi; \
+ done
+
diff --git a/linux/drmP.h b/linux/drmP.h
index 17262609..a6b32285 100644
--- a/linux/drmP.h
+++ b/linux/drmP.h
@@ -261,6 +261,7 @@ do { \
} \
} \
} while(0)
+#define DRM_DROP_MAP(_map)
/* Internal types and structures */
#define DRM_ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
@@ -275,6 +276,17 @@ do { \
(_map) = (_dev)->context_sareas[_ctx]; \
} while(0)
+#define LOCK_TEST_WITH_RETURN( dev, filp ) \
+do { \
+ if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || \
+ dev->lock.filp != filp ) { \
+ DRM_ERROR( "%s called without lock held\n", \
+ __FUNCTION__ ); \
+ return -EINVAL; \
+ } \
+} while (0)
+
+
typedef int drm_ioctl_t( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg );
@@ -323,7 +335,7 @@ typedef struct drm_buf {
__volatile__ int waiting; /* On kernel DMA queue */
__volatile__ int pending; /* On hardware DMA queue */
wait_queue_head_t dma_wait; /* Processes waiting */
- pid_t pid; /* PID of holding process */
+ struct file *filp; /* Pointer to holding file descr */
int context; /* Kernel queue for this buffer */
int while_locked;/* Dispatch this buffer while locked */
enum {
@@ -441,7 +453,7 @@ typedef struct drm_queue {
typedef struct drm_lock_data {
drm_hw_lock_t *hw_lock; /* Hardware lock */
- pid_t pid; /* PID of lock holder (0=kernel) */
+ struct file *filp; /* File descr of lock holder (0=kernel) */
wait_queue_head_t lock_queue; /* Queue of blocked processes */
unsigned long lock_time; /* Time of last lock in jiffies */
} drm_lock_data_t;
@@ -523,6 +535,8 @@ typedef struct drm_map_list {
drm_map_t *map;
} drm_map_list_t;
+typedef drm_map_t drm_local_map_t;
+
#if __HAVE_VBL_IRQ
typedef struct drm_vbl_sig {
@@ -815,15 +829,15 @@ extern int DRM(mapbufs)( struct inode *inode, struct file *filp,
extern int DRM(dma_setup)(drm_device_t *dev);
extern void DRM(dma_takedown)(drm_device_t *dev);
extern void DRM(free_buffer)(drm_device_t *dev, drm_buf_t *buf);
-extern void DRM(reclaim_buffers)(drm_device_t *dev, pid_t pid);
+extern void DRM(reclaim_buffers)( struct file *filp );
#if __HAVE_OLD_DMA
/* GH: This is a dirty hack for now...
*/
extern void DRM(clear_next_buffer)(drm_device_t *dev);
extern int DRM(select_queue)(drm_device_t *dev,
void (*wrapper)(unsigned long));
-extern int DRM(dma_enqueue)(drm_device_t *dev, drm_dma_t *dma);
-extern int DRM(dma_get_buffers)(drm_device_t *dev, drm_dma_t *dma);
+extern int DRM(dma_enqueue)(struct file *filp, drm_dma_t *dma);
+extern int DRM(dma_get_buffers)(struct file *filp, drm_dma_t *dma);
#endif
#if __HAVE_DMA_IRQ
extern int DRM(control)( struct inode *inode, struct file *filp,
diff --git a/linux/drm_agpsupport.h b/linux/drm_agpsupport.h
index 6d6b5911..35dd866f 100644
--- a/linux/drm_agpsupport.h
+++ b/linux/drm_agpsupport.h
@@ -267,12 +267,12 @@ drm_agp_head_t *DRM(agp_init)(void)
head->cant_use_aperture = head->agp_info.cant_use_aperture;
head->page_mask = head->agp_info.page_mask;
#endif
-
- DRM_DEBUG("AGP %d.%d, aperture @ 0x%08lx %ZuMB\n",
- head->agp_info.version.major,
- head->agp_info.version.minor,
- head->agp_info.aper_base,
- head->agp_info.aper_size);
+
+ DRM_INFO("AGP %d.%d aperture @ 0x%08lx %ZuMB\n",
+ head->agp_info.version.major,
+ head->agp_info.version.minor,
+ head->agp_info.aper_base,
+ head->agp_info.aper_size);
}
return head;
}
diff --git a/linux/drm_bufs.h b/linux/drm_bufs.h
index 9ce7cfff..b4e73699 100644
--- a/linux/drm_bufs.h
+++ b/linux/drm_bufs.h
@@ -404,7 +404,7 @@ int DRM(addbufs_agp)( struct inode *inode, struct file *filp,
buf->waiting = 0;
buf->pending = 0;
init_waitqueue_head( &buf->dma_wait );
- buf->pid = 0;
+ buf->filp = 0;
buf->dev_priv_size = sizeof(DRIVER_BUF_PRIV_T);
buf->dev_private = DRM(alloc)( sizeof(DRIVER_BUF_PRIV_T),
@@ -617,7 +617,7 @@ int DRM(addbufs_pci)( struct inode *inode, struct file *filp,
buf->waiting = 0;
buf->pending = 0;
init_waitqueue_head( &buf->dma_wait );
- buf->pid = 0;
+ buf->filp = 0;
#if __HAVE_DMA_HISTOGRAM
buf->time_queued = 0;
buf->time_dispatched = 0;
@@ -774,7 +774,7 @@ int DRM(addbufs_sg)( struct inode *inode, struct file *filp,
buf->waiting = 0;
buf->pending = 0;
init_waitqueue_head( &buf->dma_wait );
- buf->pid = 0;
+ buf->filp = 0;
buf->dev_priv_size = sizeof(DRIVER_BUF_PRIV_T);
buf->dev_private = DRM(alloc)( sizeof(DRIVER_BUF_PRIV_T),
@@ -1012,9 +1012,9 @@ int DRM(freebufs)( struct inode *inode, struct file *filp,
return -EINVAL;
}
buf = dma->buflist[idx];
- if ( buf->pid != current->pid ) {
- DRM_ERROR( "Process %d freeing buffer owned by %d\n",
- current->pid, buf->pid );
+ if ( buf->filp != filp ) {
+ DRM_ERROR( "Process %d freeing buffer not owned\n",
+ current->pid );
return -EINVAL;
}
DRM(free_buffer)( dev, buf );
diff --git a/linux/drm_dma.h b/linux/drm_dma.h
index df4ed809..d21c8b9d 100644
--- a/linux/drm_dma.h
+++ b/linux/drm_dma.h
@@ -189,7 +189,7 @@ void DRM(free_buffer)(drm_device_t *dev, drm_buf_t *buf)
buf->waiting = 0;
buf->pending = 0;
- buf->pid = 0;
+ buf->filp = 0;
buf->used = 0;
#if __HAVE_DMA_HISTOGRAM
buf->time_completed = get_cycles();
@@ -211,14 +211,16 @@ void DRM(free_buffer)(drm_device_t *dev, drm_buf_t *buf)
}
#if !__HAVE_DMA_RECLAIM
-void DRM(reclaim_buffers)(drm_device_t *dev, pid_t pid)
+void DRM(reclaim_buffers)( struct file *filp )
{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
drm_device_dma_t *dma = dev->dma;
int i;
if (!dma) return;
for (i = 0; i < dma->buf_count; i++) {
- if (dma->buflist[i]->pid == pid) {
+ if (dma->buflist[i]->filp == filp) {
switch (dma->buflist[i]->list) {
case DRM_LIST_NONE:
DRM(free_buffer)(dev, dma->buflist[i]);
@@ -319,8 +321,10 @@ int DRM(select_queue)(drm_device_t *dev, void (*wrapper)(unsigned long))
}
-int DRM(dma_enqueue)(drm_device_t *dev, drm_dma_t *d)
+int DRM(dma_enqueue)(struct file *filp, drm_dma_t *d)
{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
int i;
drm_queue_t *q;
drm_buf_t *buf;
@@ -382,10 +386,10 @@ int DRM(dma_enqueue)(drm_device_t *dev, drm_dma_t *d)
return -EINVAL;
}
buf = dma->buflist[ idx ];
- if (buf->pid != current->pid) {
+ if (buf->filp != filp) {
atomic_dec(&q->use_count);
- DRM_ERROR("Process %d using buffer owned by %d\n",
- current->pid, buf->pid);
+ DRM_ERROR("Process %d using buffer not owned\n",
+ current->pid);
return -EINVAL;
}
if (buf->list != DRM_LIST_NONE) {
@@ -427,9 +431,11 @@ int DRM(dma_enqueue)(drm_device_t *dev, drm_dma_t *d)
return 0;
}
-static int DRM(dma_get_buffers_of_order)(drm_device_t *dev, drm_dma_t *d,
+static int DRM(dma_get_buffers_of_order)(struct file *filp, drm_dma_t *d,
int order)
{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
int i;
drm_buf_t *buf;
drm_device_dma_t *dma = dev->dma;
@@ -439,13 +445,13 @@ static int DRM(dma_get_buffers_of_order)(drm_device_t *dev, drm_dma_t *d,
d->flags & _DRM_DMA_WAIT);
if (!buf) break;
if (buf->pending || buf->waiting) {
- DRM_ERROR("Free buffer %d in use by %d (w%d, p%d)\n",
+ DRM_ERROR("Free buffer %d in use by %x (w%d, p%d)\n",
buf->idx,
- buf->pid,
+ buf->filp,
buf->waiting,
buf->pending);
}
- buf->pid = current->pid;
+ buf->filp = filp;
if (copy_to_user(&d->request_indices[i],
&buf->idx,
sizeof(buf->idx)))
@@ -462,7 +468,7 @@ static int DRM(dma_get_buffers_of_order)(drm_device_t *dev, drm_dma_t *d,
}
-int DRM(dma_get_buffers)(drm_device_t *dev, drm_dma_t *dma)
+int DRM(dma_get_buffers)(struct file *filp, drm_dma_t *dma)
{
int order;
int retcode = 0;
@@ -471,7 +477,7 @@ int DRM(dma_get_buffers)(drm_device_t *dev, drm_dma_t *dma)
order = DRM(order)(dma->request_size);
dma->granted_count = 0;
- retcode = DRM(dma_get_buffers_of_order)(dev, dma, order);
+ retcode = DRM(dma_get_buffers_of_order)(filp, dma, order);
if (dma->granted_count < dma->request_count
&& (dma->flags & _DRM_DMA_SMALLER_OK)) {
@@ -481,7 +487,7 @@ int DRM(dma_get_buffers)(drm_device_t *dev, drm_dma_t *dma)
&& tmp_order >= DRM_MIN_ORDER;
--tmp_order) {
- retcode = DRM(dma_get_buffers_of_order)(dev, dma,
+ retcode = DRM(dma_get_buffers_of_order)(filp, dma,
tmp_order);
}
}
@@ -494,7 +500,7 @@ int DRM(dma_get_buffers)(drm_device_t *dev, drm_dma_t *dma)
&& tmp_order <= DRM_MAX_ORDER;
++tmp_order) {
- retcode = DRM(dma_get_buffers_of_order)(dev, dma,
+ retcode = DRM(dma_get_buffers_of_order)(filp, dma,
tmp_order);
}
}
@@ -714,7 +720,7 @@ void DRM(vbl_send_signals)( drm_device_t *dev )
list_del( (struct list_head *) vbl_sig );
- DRM_FREE( vbl_sig );
+ DRM_FREE( vbl_sig, sizeof(*vbl_sig) );
dev->vbl_pending--;
}
diff --git a/linux/drm_drv.h b/linux/drm_drv.h
index 3ebe7811..0a4f3aeb 100644
--- a/linux/drm_drv.h
+++ b/linux/drm_drv.h
@@ -496,7 +496,7 @@ static int DRM(takedown)( drm_device_t *dev )
#endif
if ( dev->lock.hw_lock ) {
dev->sigdata.lock = dev->lock.hw_lock = NULL; /* SHM removed */
- dev->lock.pid = 0;
+ dev->lock.filp = 0;
wake_up_interruptible( &dev->lock.lock_queue );
}
up( &dev->struct_sem );
@@ -732,8 +732,6 @@ int DRM(open)( struct inode *inode, struct file *filp )
return -ENODEV;
}
- DRM_DEBUG( "open_count = %d\n", dev->open_count );
-
retcode = DRM(open_helper)( inode, filp, dev );
if ( !retcode ) {
atomic_inc( &dev->counts[_DRM_STAT_OPENS] );
@@ -765,15 +763,15 @@ int DRM(release)( struct inode *inode, struct file *filp )
* Begin inline drm_release
*/
- DRM_DEBUG( "pid = %d, device = 0x%x, open_count = %d\n",
- current->pid, dev->device, dev->open_count );
+ DRM_DEBUG( "pid = %d, device = 0x%lx, open_count = %d\n",
+ current->pid, (long)dev->device, dev->open_count );
if ( dev->lock.hw_lock &&
_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) &&
- dev->lock.pid == current->pid ) {
- DRM_DEBUG( "Process %d dead, freeing lock for context %d\n",
- current->pid,
- _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock) );
+ dev->lock.filp == filp ) {
+ DRM_DEBUG( "File %p released, freeing lock for context %d\n",
+ filp,
+ _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock) );
#if __HAVE_RELEASE
DRIVER_RELEASE();
#endif
@@ -789,6 +787,7 @@ int DRM(release)( struct inode *inode, struct file *filp )
else if ( dev->lock.hw_lock ) {
/* The lock is required to reclaim buffers */
DECLARE_WAITQUEUE( entry, current );
+
add_wait_queue( &dev->lock.lock_queue, &entry );
for (;;) {
current->state = TASK_INTERRUPTIBLE;
@@ -799,7 +798,7 @@ int DRM(release)( struct inode *inode, struct file *filp )
}
if ( DRM(lock_take)( &dev->lock.hw_lock->lock,
DRM_KERNEL_CONTEXT ) ) {
- dev->lock.pid = priv->pid;
+ dev->lock.filp = filp;
dev->lock.lock_time = jiffies;
atomic_inc( &dev->counts[_DRM_STAT_LOCKS] );
break; /* Got lock */
@@ -823,7 +822,7 @@ int DRM(release)( struct inode *inode, struct file *filp )
}
}
#elif __HAVE_DMA
- DRM(reclaim_buffers)( dev, priv->pid );
+ DRM(reclaim_buffers)( filp );
#endif
DRM(fasync)( -1, filp, 0 );
@@ -847,7 +846,7 @@ int DRM(release)( struct inode *inode, struct file *filp )
dev->file_last = priv->prev;
}
up( &dev->struct_sem );
-
+
DRM(free)( priv, sizeof(*priv), DRM_MEM_FILES );
/* ========================================================
@@ -872,6 +871,7 @@ int DRM(release)( struct inode *inode, struct file *filp )
spin_unlock( &dev->count_lock );
unlock_kernel();
+
return retcode;
}
@@ -891,8 +891,9 @@ int DRM(ioctl)( struct inode *inode, struct file *filp,
atomic_inc( &dev->counts[_DRM_STAT_IOCTLS] );
++priv->ioctl_count;
- DRM_DEBUG( "pid=%d, cmd=0x%02x, nr=0x%02x, dev 0x%x, auth=%d\n",
- current->pid, cmd, nr, dev->device, priv->authenticated );
+ DRM_DEBUG( "pid=%d, cmd=0x%02x, nr=0x%02x, dev 0x%lx, auth=%d\n",
+ current->pid, cmd, nr, (long)dev->device,
+ priv->authenticated );
if ( nr >= DRIVER_IOCTL_COUNT ) {
retcode = -EINVAL;
@@ -968,7 +969,7 @@ int DRM(lock)( struct inode *inode, struct file *filp,
}
if ( DRM(lock_take)( &dev->lock.hw_lock->lock,
lock.context ) ) {
- dev->lock.pid = current->pid;
+ dev->lock.filp = filp;
dev->lock.lock_time = jiffies;
atomic_inc( &dev->counts[_DRM_STAT_LOCKS] );
break; /* Got lock */
@@ -1050,7 +1051,7 @@ int DRM(unlock)( struct inode *inode, struct file *filp,
* agent to request it then we should just be able to
* take it immediately and not eat the ioctl.
*/
- dev->lock.pid = 0;
+ dev->lock.filp = 0;
{
__volatile__ unsigned int *plock = &dev->lock.hw_lock->lock;
unsigned int old, new, prev, ctx;
diff --git a/linux/drm_fops.h b/linux/drm_fops.h
index 3d4bffa5..10d1aed1 100644
--- a/linux/drm_fops.h
+++ b/linux/drm_fops.h
@@ -95,8 +95,8 @@ int DRM(flush)(struct file *filp)
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->dev;
- DRM_DEBUG("pid = %d, device = 0x%x, open_count = %d\n",
- current->pid, dev->device, dev->open_count);
+ DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n",
+ current->pid, (long)dev->device, dev->open_count);
return 0;
}
@@ -106,7 +106,7 @@ int DRM(fasync)(int fd, struct file *filp, int on)
drm_device_t *dev = priv->dev;
int retcode;
- DRM_DEBUG("fd = %d, device = 0x%x\n", fd, dev->device);
+ DRM_DEBUG("fd = %d, device = 0x%lx\n", fd, (long)dev->device);
retcode = fasync_helper(fd, filp, on, &dev->buf_async);
if (retcode < 0) return retcode;
return 0;
diff --git a/linux/drm_ioctl.h b/linux/drm_ioctl.h
index 01604e75..d753cce0 100644
--- a/linux/drm_ioctl.h
+++ b/linux/drm_ioctl.h
@@ -41,6 +41,28 @@ int DRM(irq_busid)(struct inode *inode, struct file *filp,
if (copy_from_user(&p, (drm_irq_busid_t *)arg, sizeof(p)))
return -EFAULT;
+#ifdef __alpha__
+ {
+ int domain = p.busnum >> 8;
+ p.busnum &= 0xff;
+
+ /*
+ * Find the hose the device is on (the domain number is the
+ * hose index) and offset the bus by the root bus of that
+ * hose.
+ */
+ for(dev = pci_find_device(PCI_ANY_ID,PCI_ANY_ID,NULL);
+ dev;
+ dev = pci_find_device(PCI_ANY_ID,PCI_ANY_ID,dev)) {
+ struct pci_controller *hose = dev->sysdata;
+
+ if (hose->index == domain) {
+ p.busnum += hose->bus->number;
+ break;
+ }
+ }
+ }
+#endif
dev = pci_find_slot(p.busnum, PCI_DEVFN(p.devnum, p.funcnum));
if (!dev) {
DRM_ERROR("pci_find_slot failed for %d:%d:%d\n",
@@ -113,7 +135,7 @@ int DRM(setunique)(struct inode *inode, struct file *filp,
do {
struct pci_dev *pci_dev;
- int b, d, f;
+ int domain, b, d, f;
char *p;
for(p = dev->unique; p && *p && *p != ':'; p++);
@@ -125,6 +147,27 @@ int DRM(setunique)(struct inode *inode, struct file *filp,
f = (int)simple_strtoul(p+1, &p, 10);
if (*p) break;
+ domain = b >> 8;
+ b &= 0xff;
+
+#ifdef __alpha__
+ /*
+ * Find the hose the device is on (the domain number is the
+ * hose index) and offset the bus by the root bus of that
+ * hose.
+ */
+ for(pci_dev = pci_find_device(PCI_ANY_ID,PCI_ANY_ID,NULL);
+ pci_dev;
+ pci_dev = pci_find_device(PCI_ANY_ID,PCI_ANY_ID,pci_dev)) {
+ struct pci_controller *hose = pci_dev->sysdata;
+
+ if (hose->index == domain) {
+ b += hose->bus->number;
+ break;
+ }
+ }
+#endif
+
pci_dev = pci_find_slot(b, PCI_DEVFN(d,f));
if (pci_dev) {
dev->pdev = pci_dev;
diff --git a/linux/drm_lists.h b/linux/drm_lists.h
index 5cd8cd47..4a64df71 100644
--- a/linux/drm_lists.h
+++ b/linux/drm_lists.h
@@ -73,8 +73,8 @@ int DRM(waitlist_put)(drm_waitlist_t *bl, drm_buf_t *buf)
left = DRM_LEFTCOUNT(bl);
if (!left) {
- DRM_ERROR("Overflow while adding buffer %d from pid %d\n",
- buf->idx, buf->pid);
+ DRM_ERROR("Overflow while adding buffer %d from filp %p\n",
+ buf->idx, buf->filp);
return -EINVAL;
}
#if __HAVE_DMA_HISTOGRAM
diff --git a/linux/drm_lock.h b/linux/drm_lock.h
index c887d1f6..e9b17cc4 100644
--- a/linux/drm_lock.h
+++ b/linux/drm_lock.h
@@ -79,7 +79,7 @@ int DRM(lock_transfer)(drm_device_t *dev,
{
unsigned int old, new, prev;
- dev->lock.pid = 0;
+ dev->lock.filp = 0;
do {
old = *lock;
new = context | _DRM_LOCK_HELD;
@@ -92,19 +92,17 @@ int DRM(lock_free)(drm_device_t *dev,
__volatile__ unsigned int *lock, unsigned int context)
{
unsigned int old, new, prev;
- pid_t pid = dev->lock.pid;
- dev->lock.pid = 0;
+ dev->lock.filp = 0;
do {
old = *lock;
new = 0;
prev = cmpxchg(lock, old, new);
} while (prev != old);
if (_DRM_LOCK_IS_HELD(old) && _DRM_LOCKING_CONTEXT(old) != context) {
- DRM_ERROR("%d freed heavyweight lock held by %d (pid %d)\n",
+ DRM_ERROR("%d freed heavyweight lock held by %d\n",
context,
- _DRM_LOCKING_CONTEXT(old),
- pid);
+ _DRM_LOCKING_CONTEXT(old));
return 1;
}
wake_up_interruptible(&dev->lock.lock_queue);
diff --git a/linux/drm_os_linux.h b/linux/drm_os_linux.h
index a9ad02af..585c67d4 100644
--- a/linux/drm_os_linux.h
+++ b/linux/drm_os_linux.h
@@ -3,16 +3,17 @@
#include <linux/interrupt.h> /* For task queue support */
#include <linux/delay.h>
+#define DRMFILE struct file *
#define DRM_IOCTL_ARGS struct inode *inode, struct file *filp, unsigned int cmd, unsigned long data
#define DRM_ERR(d) -(d)
#define DRM_CURRENTPID current->pid
#define DRM_UDELAY(d) udelay(d)
-#define DRM_READ8(addr) readb(addr)
-#define DRM_READ32(addr) readl(addr)
-#define DRM_WRITE8(addr, val) writeb(val, addr)
-#define DRM_WRITE32(addr, val) writel(val, addr)
-#define DRM_READMEMORYBARRIER() mb()
-#define DRM_WRITEMEMORYBARRIER() wmb()
+#define DRM_READ8(map, offset) readb(((unsigned long)(map)->handle) + (offset))
+#define DRM_READ32(map, offset) readl(((unsigned long)(map)->handle) + (offset))
+#define DRM_WRITE8(map, offset, val) writeb(val, ((unsigned long)(map)->handle) + (offset))
+#define DRM_WRITE32(map, offset, val) writel(val, ((unsigned long)(map)->handle) + (offset))
+#define DRM_READMEMORYBARRIER(map) mb()
+#define DRM_WRITEMEMORYBARRIER(map) wmb()
#define DRM_DEVICE drm_file_t *priv = filp->private_data; \
drm_device_t *dev = priv->dev
@@ -42,7 +43,7 @@
/* malloc/free without the overhead of DRM(alloc) */
#define DRM_MALLOC(x) kmalloc(x, GFP_KERNEL)
-#define DRM_FREE(x) kfree(x)
+#define DRM_FREE(x,size) kfree(x)
#define DRM_GETSAREA() \
do { \
diff --git a/linux/drm_proc.h b/linux/drm_proc.h
index d29db7b7..510df672 100644
--- a/linux/drm_proc.h
+++ b/linux/drm_proc.h
@@ -148,10 +148,10 @@ static int DRM(name_info)(char *buf, char **start, off_t offset, int request,
*eof = 0;
if (dev->unique) {
- DRM_PROC_PRINT("%s 0x%x %s\n",
- dev->name, dev->device, dev->unique);
+ DRM_PROC_PRINT("%s 0x%lx %s\n",
+ dev->name, (long)dev->device, dev->unique);
} else {
- DRM_PROC_PRINT("%s 0x%x\n", dev->name, dev->device);
+ DRM_PROC_PRINT("%s 0x%lx\n", dev->name, (long)dev->device);
}
if (len > request + offset) return request;
diff --git a/linux/gamma_dma.c b/linux/gamma_dma.c
index e18a577c..a3c21d11 100644
--- a/linux/gamma_dma.c
+++ b/linux/gamma_dma.c
@@ -190,7 +190,7 @@ static int gamma_do_dma(drm_device_t *dev, int locked)
if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
DRM_ERROR("Dispatching buffer %d from pid %d"
" \"while locked\", but no lock held\n",
- buf->idx, buf->pid);
+ buf->idx, current->pid);
}
} else {
if (!locked && !gamma_lock_take(&dev->lock.hw_lock->lock,
@@ -342,7 +342,8 @@ again:
return retcode;
}
-static int gamma_dma_priority(drm_device_t *dev, drm_dma_t *d)
+static int gamma_dma_priority(struct file *filp,
+ drm_device_t *dev, drm_dma_t *d)
{
unsigned long address;
unsigned long length;
@@ -380,15 +381,15 @@ static int gamma_dma_priority(drm_device_t *dev, drm_dma_t *d)
continue;
}
buf = dma->buflist[ idx ];
- if (buf->pid != current->pid) {
- DRM_ERROR("Process %d using buffer owned by %d\n",
- current->pid, buf->pid);
+ if (buf->filp != filp) {
+ DRM_ERROR("Process %d using buffer not owned\n",
+ current->pid);
retcode = -EINVAL;
goto cleanup;
}
if (buf->list != DRM_LIST_NONE) {
- DRM_ERROR("Process %d using %d's buffer on list %d\n",
- current->pid, buf->pid, buf->list);
+ DRM_ERROR("Process %d using buffer on list %d\n",
+ current->pid, buf->list);
retcode = -EINVAL;
goto cleanup;
}
@@ -480,7 +481,8 @@ cleanup:
return retcode;
}
-static int gamma_dma_send_buffers(drm_device_t *dev, drm_dma_t *d)
+static int gamma_dma_send_buffers(struct file *filp,
+ drm_device_t *dev, drm_dma_t *d)
{
DECLARE_WAITQUEUE(entry, current);
drm_buf_t *last_buf = NULL;
@@ -492,7 +494,7 @@ static int gamma_dma_send_buffers(drm_device_t *dev, drm_dma_t *d)
add_wait_queue(&last_buf->dma_wait, &entry);
}
- if ((retcode = gamma_dma_enqueue(dev, d))) {
+ if ((retcode = gamma_dma_enqueue(filp, d))) {
if (d->flags & _DRM_DMA_BLOCK)
remove_wait_queue(&last_buf->dma_wait, &entry);
return retcode;
@@ -522,14 +524,13 @@ static int gamma_dma_send_buffers(drm_device_t *dev, drm_dma_t *d)
}
}
if (retcode) {
- DRM_ERROR("ctx%d w%d p%d c%d i%d l%d %d/%d\n",
+ DRM_ERROR("ctx%d w%d p%d c%ld i%d l%d pid:%d\n",
d->context,
last_buf->waiting,
last_buf->pending,
- DRM_WAITCOUNT(dev, d->context),
+ (long)DRM_WAITCOUNT(dev, d->context),
last_buf->idx,
last_buf->list,
- last_buf->pid,
current->pid);
}
}
@@ -562,15 +563,15 @@ int gamma_dma(struct inode *inode, struct file *filp, unsigned int cmd,
if (d.send_count) {
if (d.flags & _DRM_DMA_PRIORITY)
- retcode = gamma_dma_priority(dev, &d);
+ retcode = gamma_dma_priority(filp, dev, &d);
else
- retcode = gamma_dma_send_buffers(dev, &d);
+ retcode = gamma_dma_send_buffers(filp, dev, &d);
}
d.granted_count = 0;
if (!retcode && d.request_count) {
- retcode = gamma_dma_get_buffers(dev, &d);
+ retcode = gamma_dma_get_buffers(filp, &d);
}
DRM_DEBUG("%d returning, granted = %d\n",
@@ -592,7 +593,7 @@ static int gamma_do_init_dma( drm_device_t *dev, drm_gamma_init_t *init )
drm_buf_t *buf;
int i;
struct list_head *list;
- unsigned int *pgt;
+ unsigned long *pgt;
DRM_DEBUG( "%s\n", __FUNCTION__ );
@@ -645,7 +646,7 @@ static int gamma_do_init_dma( drm_device_t *dev, drm_gamma_init_t *init )
for (i = 0; i < GLINT_DRI_BUF_COUNT; i++) {
buf = dma->buflist[i];
- *pgt = (unsigned int)buf->address + 0x07;
+ *pgt = (unsigned long)buf->address + 0x07;
pgt++;
}
diff --git a/linux/gamma_drv.h b/linux/gamma_drv.h
index e7d0c896..2f7d3588 100644
--- a/linux/gamma_drv.h
+++ b/linux/gamma_drv.h
@@ -42,16 +42,6 @@ typedef struct drm_gamma_private {
drm_map_t *mmio3;
} drm_gamma_private_t;
-#define LOCK_TEST_WITH_RETURN( dev ) \
-do { \
- if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || \
- dev->lock.pid != current->pid ) { \
- DRM_ERROR( "%s called without lock held\n", \
- __FUNCTION__ ); \
- return -EINVAL; \
- } \
-} while (0)
-
/* gamma_dma.c */
extern int gamma_dma_init( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg );
diff --git a/linux/i810.h b/linux/i810.h
index ea1e7fe5..f37cb2e8 100644
--- a/linux/i810.h
+++ b/linux/i810.h
@@ -86,7 +86,7 @@
*/
#define __HAVE_RELEASE 1
#define DRIVER_RELEASE() do { \
- i810_reclaim_buffers( dev, priv->pid ); \
+ i810_reclaim_buffers( filp ); \
} while (0)
/* DMA customization:
diff --git a/linux/i810_dma.c b/linux/i810_dma.c
index ffb7c708..de9345e3 100644
--- a/linux/i810_dma.c
+++ b/linux/i810_dma.c
@@ -53,30 +53,10 @@
#define I810_BUF_UNMAPPED 0
#define I810_BUF_MAPPED 1
-#define RING_LOCALS unsigned int outring, ringmask; volatile char *virt;
-
-#define BEGIN_LP_RING(n) do { \
- if (0) DRM_DEBUG("BEGIN_LP_RING(%d) in %s\n", n, __FUNCTION__); \
- if (dev_priv->ring.space < n*4) \
- i810_wait_ring(dev, n*4); \
- dev_priv->ring.space -= n*4; \
- outring = dev_priv->ring.tail; \
- ringmask = dev_priv->ring.tail_mask; \
- virt = dev_priv->ring.virtual_start; \
-} while (0)
-
-#define ADVANCE_LP_RING() do { \
- if (0) DRM_DEBUG("ADVANCE_LP_RING\n"); \
- dev_priv->ring.tail = outring; \
- I810_WRITE(LP_RING + RING_TAIL, outring); \
-} while(0)
-
-#define OUT_RING(n) do { \
- if (0) DRM_DEBUG(" OUT_RING %x\n", (int)(n)); \
- *(volatile unsigned int *)(virt + outring) = n; \
- outring += 4; \
- outring &= ringmask; \
-} while (0)
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,2)
+#define down_write down
+#define up_write up
+#endif
static inline void i810_print_status_page(drm_device_t *dev)
{
@@ -185,11 +165,7 @@ static int i810_map_buffer(drm_buf_t *buf, struct file *filp)
if(buf_priv->currently_mapped == I810_BUF_MAPPED) return -EINVAL;
-#if LINUX_VERSION_CODE <= 0x020402
- down( &current->mm->mmap_sem );
-#else
down_write( &current->mm->mmap_sem );
-#endif
old_fops = filp->f_op;
filp->f_op = &i810_buffer_fops;
dev_priv->mmap_buffer = buf;
@@ -201,15 +177,12 @@ static int i810_map_buffer(drm_buf_t *buf, struct file *filp)
filp->f_op = old_fops;
if ((unsigned long)buf_priv->virtual > -1024UL) {
/* Real error */
- DRM_DEBUG("mmap error\n");
+ DRM_ERROR("mmap error\n");
retcode = (signed int)buf_priv->virtual;
buf_priv->virtual = 0;
}
-#if LINUX_VERSION_CODE <= 0x020402
- up( &current->mm->mmap_sem );
-#else
up_write( &current->mm->mmap_sem );
-#endif
+
return retcode;
}
@@ -220,19 +193,13 @@ static int i810_unmap_buffer(drm_buf_t *buf)
if(buf_priv->currently_mapped != I810_BUF_MAPPED)
return -EINVAL;
-#if LINUX_VERSION_CODE <= 0x020402
- down( &current->mm->mmap_sem );
-#else
- down_write( &current->mm->mmap_sem );
-#endif
+
+ down_write(&current->mm->mmap_sem);
retcode = DO_MUNMAP(current->mm,
(unsigned long)buf_priv->virtual,
(size_t) buf->total);
-#if LINUX_VERSION_CODE <= 0x020402
- up( &current->mm->mmap_sem );
-#else
- up_write( &current->mm->mmap_sem );
-#endif
+ up_write(&current->mm->mmap_sem);
+
buf_priv->currently_mapped = I810_BUF_UNMAPPED;
buf_priv->virtual = 0;
@@ -242,7 +209,6 @@ static int i810_unmap_buffer(drm_buf_t *buf)
static int i810_dma_get_buffer(drm_device_t *dev, drm_i810_dma_t *d,
struct file *filp)
{
- drm_file_t *priv = filp->private_data;
drm_buf_t *buf;
drm_i810_buf_priv_t *buf_priv;
int retcode = 0;
@@ -257,10 +223,10 @@ static int i810_dma_get_buffer(drm_device_t *dev, drm_i810_dma_t *d,
retcode = i810_map_buffer(buf, filp);
if(retcode) {
i810_freelist_put(dev, buf);
- DRM_DEBUG("mapbuf failed, retcode %d\n", retcode);
+ DRM_ERROR("mapbuf failed, retcode %d\n", retcode);
return retcode;
}
- buf->pid = priv->pid;
+ buf->filp = filp;
buf_priv = buf->dev_private;
d->granted = 1;
d->request_idx = buf->idx;
@@ -321,7 +287,7 @@ static int i810_wait_ring(drm_device_t *dev, int n)
end = jiffies + (HZ*3);
iters++;
- if((signed)(end - jiffies) <= 0) {
+ if(time_before(end, jiffies)) {
DRM_ERROR("space: %d wanted %d\n", ring->space, n);
DRM_ERROR("lockup\n");
goto out_wait_ring;
@@ -889,8 +855,10 @@ static int i810_flush_queue(drm_device_t *dev)
}
/* Must be called with the lock held */
-void i810_reclaim_buffers(drm_device_t *dev, pid_t pid)
+void i810_reclaim_buffers(struct file *filp)
{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
drm_device_dma_t *dma = dev->dma;
int i;
@@ -904,7 +872,7 @@ void i810_reclaim_buffers(drm_device_t *dev, pid_t pid)
drm_buf_t *buf = dma->buflist[ i ];
drm_i810_buf_priv_t *buf_priv = buf->dev_private;
- if (buf->pid == pid && buf_priv) {
+ if (buf->filp == filp && buf_priv) {
int used = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT,
I810_BUF_FREE);
diff --git a/linux/i810_drv.h b/linux/i810_drv.h
index 106abf56..bbb570bc 100644
--- a/linux/i810_drv.h
+++ b/linux/i810_drv.h
@@ -88,7 +88,7 @@ extern int i810_dma_init(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern int i810_flush_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
-extern void i810_reclaim_buffers(drm_device_t *dev, pid_t pid);
+extern void i810_reclaim_buffers(struct file *filp);
extern int i810_getage(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma);
@@ -136,6 +136,33 @@ int i810_clear_bufs(struct inode *inode, struct file *filp,
#define I810_READ16(reg) I810_DEREF16(reg)
#define I810_WRITE16(reg,val) do { I810_DEREF16(reg) = val; } while (0)
+#define I810_VERBOSE 0
+#define RING_LOCALS unsigned int outring, ringmask; \
+ volatile char *virt;
+
+#define BEGIN_LP_RING(n) do { \
+ if (I810_VERBOSE) \
+ DRM_DEBUG("BEGIN_LP_RING(%d) in %s\n", n, __FUNCTION__); \
+ if (dev_priv->ring.space < n*4) \
+ i810_wait_ring(dev, n*4); \
+ dev_priv->ring.space -= n*4; \
+ outring = dev_priv->ring.tail; \
+ ringmask = dev_priv->ring.tail_mask; \
+ virt = dev_priv->ring.virtual_start; \
+} while (0)
+
+#define ADVANCE_LP_RING() do { \
+ if (I810_VERBOSE) DRM_DEBUG("ADVANCE_LP_RING\n"); \
+ dev_priv->ring.tail = outring; \
+ I810_WRITE(LP_RING + RING_TAIL, outring); \
+} while(0)
+
+#define OUT_RING(n) do { \
+ if (I810_VERBOSE) DRM_DEBUG(" OUT_RING %x\n", (int)(n)); \
+ *(volatile unsigned int *)(virt + outring) = n; \
+ outring += 4; \
+ outring &= ringmask; \
+} while (0)
#define GFX_OP_USER_INTERRUPT ((0<<29)|(2<<23))
#define GFX_OP_BREAKPOINT_INTERRUPT ((0<<29)|(1<<23))
@@ -198,6 +225,7 @@ int i810_clear_bufs(struct inode *inode, struct file *filp,
#define CMD_OP_Z_BUFFER_INFO ((0x0<<29)|(0x16<<23))
#define CMD_OP_DESTBUFFER_INFO ((0x0<<29)|(0x15<<23))
+#define CMD_OP_FRONTBUFFER_INFO ((0x0<<29)|(0x14<<23))
#define BR00_BITBLT_CLIENT 0x40000000
#define BR00_OP_COLOR_BLT 0x10000000
diff --git a/linux/i830.h b/linux/i830.h
index b9752188..a351a4cf 100644
--- a/linux/i830.h
+++ b/linux/i830.h
@@ -45,22 +45,37 @@
#define DRIVER_NAME "i830"
#define DRIVER_DESC "Intel 830M"
-#define DRIVER_DATE "20020828"
+#define DRIVER_DATE "20021108"
+/* Interface history:
+ *
+ * 1.1: Original.
+ * 1.2: ?
+ * 1.3: New irq emit/wait ioctls.
+ * New pageflip ioctl.
+ * New getparam ioctl.
+ * State for texunits 3&4 in sarea.
+ * New (alternative) layout for texture state.
+ */
#define DRIVER_MAJOR 1
-#define DRIVER_MINOR 2
-#define DRIVER_PATCHLEVEL 1
+#define DRIVER_MINOR 3
+#define DRIVER_PATCHLEVEL 2
#define DRIVER_IOCTLS \
[DRM_IOCTL_NR(DRM_IOCTL_I830_INIT)] = { i830_dma_init, 1, 1 }, \
- [DRM_IOCTL_NR(DRM_IOCTL_I830_VERTEX)] = { i830_dma_vertex, 1, 0 }, \
- [DRM_IOCTL_NR(DRM_IOCTL_I830_CLEAR)] = { i830_clear_bufs, 1, 0 }, \
- [DRM_IOCTL_NR(DRM_IOCTL_I830_FLUSH)] = { i830_flush_ioctl, 1, 0 }, \
- [DRM_IOCTL_NR(DRM_IOCTL_I830_GETAGE)] = { i830_getage, 1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_I830_VERTEX)] = { i830_dma_vertex, 1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_I830_CLEAR)] = { i830_clear_bufs, 1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_I830_FLUSH)] = { i830_flush_ioctl, 1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_I830_GETAGE)] = { i830_getage, 1, 0 }, \
[DRM_IOCTL_NR(DRM_IOCTL_I830_GETBUF)] = { i830_getbuf, 1, 0 }, \
- [DRM_IOCTL_NR(DRM_IOCTL_I830_SWAP)] = { i830_swap_bufs, 1, 0 }, \
- [DRM_IOCTL_NR(DRM_IOCTL_I830_COPY)] = { i830_copybuf, 1, 0 }, \
- [DRM_IOCTL_NR(DRM_IOCTL_I830_DOCOPY)] = { i830_docopy, 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_I830_SWAP)] = { i830_swap_bufs, 1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_I830_COPY)] = { i830_copybuf, 1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_I830_DOCOPY)] = { i830_docopy, 1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_I830_FLIP)] = { i830_flip_bufs, 1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_I830_IRQ_EMIT)] = { i830_irq_emit, 1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_I830_IRQ_WAIT)] = { i830_irq_wait, 1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_I830_GETPARAM)] = { i830_getparam, 1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_I830_SETPARAM)] = { i830_setparam, 1, 0 }
#define __HAVE_COUNTERS 4
#define __HAVE_COUNTER6 _DRM_STAT_IRQ
@@ -72,7 +87,7 @@
*/
#define __HAVE_RELEASE 1
#define DRIVER_RELEASE() do { \
- i830_reclaim_buffers( dev, priv->pid ); \
+ i830_reclaim_buffers( filp ); \
} while (0)
/* DMA customization:
@@ -87,10 +102,49 @@
i830_dma_quiescent( dev ); \
} while (0)
-/* Don't need an irq any more. The template code will make sure that
- * a noop stub is generated for compatibility.
+
+/* Driver will work either way: IRQ's save cpu time when waiting for
+ * the card, but are subject to subtle interactions between bios,
+ * hardware and the driver.
+ */
+#define USE_IRQS 0
+
+
+#if USE_IRQS
+#define __HAVE_DMA_IRQ 1
+#define __HAVE_SHARED_IRQ 1
+
+#define DRIVER_PREINSTALL() do { \
+ drm_i830_private_t *dev_priv = \
+ (drm_i830_private_t *)dev->dev_private; \
+ \
+ I830_WRITE16( I830REG_HWSTAM, 0xffff ); \
+ I830_WRITE16( I830REG_INT_MASK_R, 0x0 ); \
+ I830_WRITE16( I830REG_INT_ENABLE_R, 0x0 ); \
+} while (0)
+
+
+#define DRIVER_POSTINSTALL() do { \
+ drm_i830_private_t *dev_priv = \
+ (drm_i830_private_t *)dev->dev_private; \
+ I830_WRITE16( I830REG_INT_ENABLE_R, 0x2 ); \
+ atomic_set(&dev_priv->irq_received, 0); \
+ atomic_set(&dev_priv->irq_emitted, 0); \
+ init_waitqueue_head(&dev_priv->irq_queue); \
+} while (0)
+
+
+/* This gets called too late to be useful: dev_priv has already been
+ * freed.
*/
-#define __HAVE_DMA_IRQ 0
+#define DRIVER_UNINSTALL() do { \
+} while (0)
+
+#else
+#define __HAVE_DMA_IRQ 0
+#endif
+
+
/* Buffer customization:
*/
diff --git a/linux/i830_dma.c b/linux/i830_dma.c
index d29e21cb..d2555c92 100644
--- a/linux/i830_dma.c
+++ b/linux/i830_dma.c
@@ -38,6 +38,7 @@
#include "i830_drm.h"
#include "i830_drv.h"
#include <linux/interrupt.h> /* For task queue support */
+#include <linux/pagemap.h> /* For FASTCALL on unlock_page() */
#include <linux/delay.h>
#ifdef DO_MUNMAP_4_ARGS
@@ -53,8 +54,6 @@
#define I830_BUF_UNMAPPED 0
#define I830_BUF_MAPPED 1
-#define RING_LOCALS unsigned int outring, ringmask; volatile char *virt;
-
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,2)
#define down_write down
#define up_write up
@@ -67,32 +66,6 @@
#define UnlockPage(page) unlock_page(page)
#endif
-#define I830_VERBOSE 0
-
-#define BEGIN_LP_RING(n) do { \
- if (I830_VERBOSE) \
- printk("BEGIN_LP_RING(%d) in %s\n", \
- n, __FUNCTION__); \
- if (dev_priv->ring.space < n*4) \
- i830_wait_ring(dev, n*4); \
- dev_priv->ring.space -= n*4; \
- outring = dev_priv->ring.tail; \
- ringmask = dev_priv->ring.tail_mask; \
- virt = dev_priv->ring.virtual_start; \
-} while (0)
-
-#define ADVANCE_LP_RING() do { \
- if (I830_VERBOSE) printk("ADVANCE_LP_RING %x\n", outring); \
- dev_priv->ring.tail = outring; \
- I830_WRITE(LP_RING + RING_TAIL, outring); \
-} while(0)
-
-#define OUT_RING(n) do { \
- if (I830_VERBOSE) printk(" OUT_RING %x\n", (int)(n)); \
- *(volatile unsigned int *)(virt + outring) = n; \
- outring += 4; \
- outring &= ringmask; \
-} while (0)
static inline void i830_print_status_page(drm_device_t *dev)
{
@@ -244,7 +217,6 @@ static int i830_unmap_buffer(drm_buf_t *buf)
static int i830_dma_get_buffer(drm_device_t *dev, drm_i830_dma_t *d,
struct file *filp)
{
- drm_file_t *priv = filp->private_data;
drm_buf_t *buf;
drm_i830_buf_priv_t *buf_priv;
int retcode = 0;
@@ -252,7 +224,7 @@ static int i830_dma_get_buffer(drm_device_t *dev, drm_i830_dma_t *d,
buf = i830_freelist_get(dev);
if (!buf) {
retcode = -ENOMEM;
- DRM_ERROR("retcode=%d\n", retcode);
+ DRM_DEBUG("retcode=%d\n", retcode);
return retcode;
}
@@ -262,7 +234,7 @@ static int i830_dma_get_buffer(drm_device_t *dev, drm_i830_dma_t *d,
DRM_ERROR("mapbuf failed, retcode %d\n", retcode);
return retcode;
}
- buf->pid = priv->pid;
+ buf->filp = filp;
buf_priv = buf->dev_private;
d->granted = 1;
d->request_idx = buf->idx;
@@ -286,12 +258,21 @@ static int i830_dma_cleanup(drm_device_t *dev)
dev_priv->ring.Size);
}
if(dev_priv->hw_status_page != 0UL) {
- pci_free_consistent(dev->pdev, PAGE_SIZE,
+ pci_free_consistent(dev->pdev, PAGE_SIZE,
(void *)dev_priv->hw_status_page,
dev_priv->dma_status_page);
/* Need to rewrite hardware status page */
I830_WRITE(0x02080, 0x1ffff000);
}
+
+ /* Disable interrupts here because after dev_private
+ * is freed, it's too late.
+ */
+ if (dev->irq) {
+ I830_WRITE16( I830REG_INT_MASK_R, 0xffff );
+ I830_WRITE16( I830REG_INT_ENABLE_R, 0x0 );
+ }
+
DRM(free)(dev->dev_private, sizeof(drm_i830_private_t),
DRM_MEM_DRIVER);
dev->dev_private = NULL;
@@ -305,7 +286,7 @@ static int i830_dma_cleanup(drm_device_t *dev)
return 0;
}
-static int i830_wait_ring(drm_device_t *dev, int n)
+int i830_wait_ring(drm_device_t *dev, int n, const char *caller)
{
drm_i830_private_t *dev_priv = dev->dev_private;
drm_i830_ring_buffer_t *ring = &(dev_priv->ring);
@@ -331,6 +312,7 @@ static int i830_wait_ring(drm_device_t *dev, int n)
goto out_wait_ring;
}
udelay(1);
+ dev_priv->sarea_priv->perf_boxes |= I830_BOX_WAIT;
}
out_wait_ring:
@@ -346,6 +328,9 @@ static void i830_kernel_lost_context(drm_device_t *dev)
ring->tail = I830_READ(LP_RING + RING_TAIL) & TAIL_ADDR;
ring->space = ring->head - (ring->tail+8);
if (ring->space < 0) ring->space += ring->Size;
+
+ if (ring->head == ring->tail)
+ dev_priv->sarea_priv->perf_boxes |= I830_BOX_RING_EMPTY;
}
static int i830_freelist_init(drm_device_t *dev, drm_i830_private_t *dev_priv)
@@ -460,6 +445,8 @@ static int i830_dma_initialize(drm_device_t *dev,
dev_priv->back_pitch = init->back_pitch;
dev_priv->depth_pitch = init->depth_pitch;
+ dev_priv->do_boxes = 0;
+ dev_priv->use_mi_batchbuffer_start = 0;
/* Program Hardware Status Page */
dev_priv->hw_status_page =
@@ -474,7 +461,7 @@ static int i830_dma_initialize(drm_device_t *dev,
memset((void *) dev_priv->hw_status_page, 0, PAGE_SIZE);
DRM_DEBUG("hw status page @ %lx\n", dev_priv->hw_status_page);
- I830_WRITE(0x02080, dev_priv->dma_status_page);
+ I830_WRITE(0x02080, virt_to_bus((void *)dev_priv->hw_status_page));
DRM_DEBUG("Enabled hardware status page\n");
/* Now we need to init our freelist */
@@ -535,11 +522,7 @@ static void i830EmitContextVerified( drm_device_t *dev,
unsigned int tmp;
RING_LOCALS;
- BEGIN_LP_RING( I830_CTX_SETUP_SIZE + 2 );
-
- OUT_RING( GFX_OP_STIPPLE );
- OUT_RING( 0 );
-
+ BEGIN_LP_RING( I830_CTX_SETUP_SIZE + 4 );
for ( i = 0 ; i < I830_CTXREG_BLENDCOLR0 ; i++ ) {
tmp = code[i];
@@ -577,38 +560,44 @@ static void i830EmitContextVerified( drm_device_t *dev,
ADVANCE_LP_RING();
}
-static void i830EmitTexVerified( drm_device_t *dev,
- volatile unsigned int *code )
+static void i830EmitTexVerified( drm_device_t *dev, unsigned int *code )
{
drm_i830_private_t *dev_priv = dev->dev_private;
int i, j = 0;
unsigned int tmp;
RING_LOCALS;
- BEGIN_LP_RING( I830_TEX_SETUP_SIZE );
+ if (code[I830_TEXREG_MI0] == GFX_OP_MAP_INFO ||
+ (code[I830_TEXREG_MI0] & ~(0xf*LOAD_TEXTURE_MAP0)) ==
+ (STATE3D_LOAD_STATE_IMMEDIATE_2|4)) {
- OUT_RING( GFX_OP_MAP_INFO );
- OUT_RING( code[I830_TEXREG_MI1] );
- OUT_RING( code[I830_TEXREG_MI2] );
- OUT_RING( code[I830_TEXREG_MI3] );
- OUT_RING( code[I830_TEXREG_MI4] );
- OUT_RING( code[I830_TEXREG_MI5] );
+ BEGIN_LP_RING( I830_TEX_SETUP_SIZE );
- for ( i = 6 ; i < I830_TEX_SETUP_SIZE ; i++ ) {
- tmp = code[i];
- OUT_RING( tmp );
- j++;
- }
+ OUT_RING( code[I830_TEXREG_MI0] ); /* TM0LI */
+ OUT_RING( code[I830_TEXREG_MI1] ); /* TM0S0 */
+ OUT_RING( code[I830_TEXREG_MI2] ); /* TM0S1 */
+ OUT_RING( code[I830_TEXREG_MI3] ); /* TM0S2 */
+ OUT_RING( code[I830_TEXREG_MI4] ); /* TM0S3 */
+ OUT_RING( code[I830_TEXREG_MI5] ); /* TM0S4 */
+
+ for ( i = 6 ; i < I830_TEX_SETUP_SIZE ; i++ ) {
+ tmp = code[i];
+ OUT_RING( tmp );
+ j++;
+ }
- if (j & 1)
- OUT_RING( 0 );
+ if (j & 1)
+ OUT_RING( 0 );
- ADVANCE_LP_RING();
+ ADVANCE_LP_RING();
+ }
+ else
+ printk("rejected packet %x\n", code[0]);
}
static void i830EmitTexBlendVerified( drm_device_t *dev,
- volatile unsigned int *code,
- volatile unsigned int num)
+ unsigned int *code,
+ unsigned int num)
{
drm_i830_private_t *dev_priv = dev->dev_private;
int i, j = 0;
@@ -618,7 +607,7 @@ static void i830EmitTexBlendVerified( drm_device_t *dev,
if (!num)
return;
- BEGIN_LP_RING( num );
+ BEGIN_LP_RING( num + 1 );
for ( i = 0 ; i < num ; i++ ) {
tmp = code[i];
@@ -641,6 +630,8 @@ static void i830EmitTexPalette( drm_device_t *dev,
int i;
RING_LOCALS;
+ return;
+
BEGIN_LP_RING( 258 );
if(is_shared == 1) {
@@ -654,42 +645,41 @@ static void i830EmitTexPalette( drm_device_t *dev,
OUT_RING(palette[i]);
}
OUT_RING(0);
+ /* KW: WHERE IS THE ADVANCE_LP_RING? This is effectively a noop!
+ */
}
/* Need to do some additional checking when setting the dest buffer.
*/
static void i830EmitDestVerified( drm_device_t *dev,
- volatile unsigned int *code )
+ unsigned int *code )
{
drm_i830_private_t *dev_priv = dev->dev_private;
unsigned int tmp;
RING_LOCALS;
- BEGIN_LP_RING( I830_DEST_SETUP_SIZE + 6 );
+ BEGIN_LP_RING( I830_DEST_SETUP_SIZE + 10 );
+
tmp = code[I830_DESTREG_CBUFADDR];
- if (tmp == dev_priv->front_di1) {
- /* Don't use fence when front buffer rendering */
- OUT_RING( CMD_OP_DESTBUFFER_INFO );
- OUT_RING( BUF_3D_ID_COLOR_BACK |
- BUF_3D_PITCH(dev_priv->back_pitch * dev_priv->cpp) );
- OUT_RING( tmp );
+ if (tmp == dev_priv->front_di1 || tmp == dev_priv->back_di1) {
+ if (((int)outring) & 8) {
+ OUT_RING(0);
+ OUT_RING(0);
+ }
OUT_RING( CMD_OP_DESTBUFFER_INFO );
- OUT_RING( BUF_3D_ID_DEPTH |
- BUF_3D_PITCH(dev_priv->depth_pitch * dev_priv->cpp));
- OUT_RING( dev_priv->zi1 );
- } else if(tmp == dev_priv->back_di1) {
- OUT_RING( CMD_OP_DESTBUFFER_INFO );
OUT_RING( BUF_3D_ID_COLOR_BACK |
BUF_3D_PITCH(dev_priv->back_pitch * dev_priv->cpp) |
BUF_3D_USE_FENCE);
OUT_RING( tmp );
+ OUT_RING( 0 );
OUT_RING( CMD_OP_DESTBUFFER_INFO );
OUT_RING( BUF_3D_ID_DEPTH | BUF_3D_USE_FENCE |
BUF_3D_PITCH(dev_priv->depth_pitch * dev_priv->cpp));
OUT_RING( dev_priv->zi1 );
+ OUT_RING( 0 );
} else {
DRM_ERROR("bad di1 %x (allow %x or %x)\n",
tmp, dev_priv->front_di1, dev_priv->back_di1);
@@ -717,21 +707,35 @@ static void i830EmitDestVerified( drm_device_t *dev,
OUT_RING( 0 );
}
- OUT_RING( code[I830_DESTREG_SENABLE] );
-
OUT_RING( GFX_OP_SCISSOR_RECT );
OUT_RING( code[I830_DESTREG_SR1] );
OUT_RING( code[I830_DESTREG_SR2] );
+ OUT_RING( 0 );
ADVANCE_LP_RING();
}
+static void i830EmitStippleVerified( drm_device_t *dev,
+ unsigned int *code )
+{
+ drm_i830_private_t *dev_priv = dev->dev_private;
+ RING_LOCALS;
+
+ BEGIN_LP_RING( 2 );
+ OUT_RING( GFX_OP_STIPPLE );
+ OUT_RING( code[1] );
+ ADVANCE_LP_RING();
+}
+
+
static void i830EmitState( drm_device_t *dev )
{
drm_i830_private_t *dev_priv = dev->dev_private;
drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
unsigned int dirty = sarea_priv->dirty;
+ DRM_DEBUG("%s %x\n", __FUNCTION__, dirty);
+
if (dirty & I830_UPLOAD_BUFFERS) {
i830EmitDestVerified( dev, sarea_priv->BufferState );
sarea_priv->dirty &= ~I830_UPLOAD_BUFFERS;
@@ -765,17 +769,154 @@ static void i830EmitState( drm_device_t *dev )
}
if (dirty & I830_UPLOAD_TEX_PALETTE_SHARED) {
- i830EmitTexPalette(dev, sarea_priv->Palette[0], 0, 1);
+ i830EmitTexPalette(dev, sarea_priv->Palette[0], 0, 1);
} else {
- if (dirty & I830_UPLOAD_TEX_PALETTE_N(0)) {
- i830EmitTexPalette(dev, sarea_priv->Palette[0], 0, 0);
- sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(0);
- }
- if (dirty & I830_UPLOAD_TEX_PALETTE_N(1)) {
- i830EmitTexPalette(dev, sarea_priv->Palette[1], 1, 0);
- sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(1);
- }
+ if (dirty & I830_UPLOAD_TEX_PALETTE_N(0)) {
+ i830EmitTexPalette(dev, sarea_priv->Palette[0], 0, 0);
+ sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(0);
+ }
+ if (dirty & I830_UPLOAD_TEX_PALETTE_N(1)) {
+ i830EmitTexPalette(dev, sarea_priv->Palette[1], 1, 0);
+ sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(1);
+ }
+
+ /* 1.3:
+ */
+#if 0
+ if (dirty & I830_UPLOAD_TEX_PALETTE_N(2)) {
+ i830EmitTexPalette(dev, sarea_priv->Palette2[0], 0, 0);
+ sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(2);
+ }
+ if (dirty & I830_UPLOAD_TEX_PALETTE_N(3)) {
+ i830EmitTexPalette(dev, sarea_priv->Palette2[1], 1, 0);
+ sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(2);
+ }
+#endif
+ }
+
+ /* 1.3:
+ */
+ if (dirty & I830_UPLOAD_STIPPLE) {
+ i830EmitStippleVerified( dev,
+ sarea_priv->StippleState);
+ sarea_priv->dirty &= ~I830_UPLOAD_STIPPLE;
}
+
+ if (dirty & I830_UPLOAD_TEX2) {
+ i830EmitTexVerified( dev, sarea_priv->TexState2 );
+ sarea_priv->dirty &= ~I830_UPLOAD_TEX2;
+ }
+
+ if (dirty & I830_UPLOAD_TEX3) {
+ i830EmitTexVerified( dev, sarea_priv->TexState3 );
+ sarea_priv->dirty &= ~I830_UPLOAD_TEX3;
+ }
+
+
+ if (dirty & I830_UPLOAD_TEXBLEND2) {
+ i830EmitTexBlendVerified(
+ dev,
+ sarea_priv->TexBlendState2,
+ sarea_priv->TexBlendStateWordsUsed2);
+
+ sarea_priv->dirty &= ~I830_UPLOAD_TEXBLEND2;
+ }
+
+ if (dirty & I830_UPLOAD_TEXBLEND3) {
+ i830EmitTexBlendVerified(
+ dev,
+ sarea_priv->TexBlendState3,
+ sarea_priv->TexBlendStateWordsUsed3);
+ sarea_priv->dirty &= ~I830_UPLOAD_TEXBLEND3;
+ }
+}
+
+/* ================================================================
+ * Performance monitoring functions
+ */
+
+static void i830_fill_box( drm_device_t *dev,
+ int x, int y, int w, int h,
+ int r, int g, int b )
+{
+ drm_i830_private_t *dev_priv = dev->dev_private;
+ u32 color;
+ unsigned int BR13, CMD;
+ RING_LOCALS;
+
+ BR13 = (0xF0 << 16) | (dev_priv->pitch * dev_priv->cpp) | (1<<24);
+ CMD = XY_COLOR_BLT_CMD;
+ x += dev_priv->sarea_priv->boxes[0].x1;
+ y += dev_priv->sarea_priv->boxes[0].y1;
+
+ if (dev_priv->cpp == 4) {
+ BR13 |= (1<<25);
+ CMD |= (XY_COLOR_BLT_WRITE_ALPHA | XY_COLOR_BLT_WRITE_RGB);
+ color = (((0xff) << 24) | (r << 16) | (g << 8) | b);
+ } else {
+ color = (((r & 0xf8) << 8) |
+ ((g & 0xfc) << 3) |
+ ((b & 0xf8) >> 3));
+ }
+
+ BEGIN_LP_RING( 6 );
+ OUT_RING( CMD );
+ OUT_RING( BR13 );
+ OUT_RING( (y << 16) | x );
+ OUT_RING( ((y+h) << 16) | (x+w) );
+
+ if ( dev_priv->current_page == 1 ) {
+ OUT_RING( dev_priv->front_offset );
+ } else {
+ OUT_RING( dev_priv->back_offset );
+ }
+
+ OUT_RING( color );
+ ADVANCE_LP_RING();
+}
+
+static void i830_cp_performance_boxes( drm_device_t *dev )
+{
+ drm_i830_private_t *dev_priv = dev->dev_private;
+
+ /* Purple box for page flipping
+ */
+ if ( dev_priv->sarea_priv->perf_boxes & I830_BOX_FLIP )
+ i830_fill_box( dev, 4, 4, 8, 8, 255, 0, 255 );
+
+ /* Red box if we have to wait for idle at any point
+ */
+ if ( dev_priv->sarea_priv->perf_boxes & I830_BOX_WAIT )
+ i830_fill_box( dev, 16, 4, 8, 8, 255, 0, 0 );
+
+ /* Blue box: lost context?
+ */
+ if ( dev_priv->sarea_priv->perf_boxes & I830_BOX_LOST_CONTEXT )
+ i830_fill_box( dev, 28, 4, 8, 8, 0, 0, 255 );
+
+ /* Yellow box for texture swaps
+ */
+ if ( dev_priv->sarea_priv->perf_boxes & I830_BOX_TEXTURE_LOAD )
+ i830_fill_box( dev, 40, 4, 8, 8, 255, 255, 0 );
+
+ /* Green box if hardware never idles (as far as we can tell)
+ */
+ if ( !(dev_priv->sarea_priv->perf_boxes & I830_BOX_RING_EMPTY) )
+ i830_fill_box( dev, 64, 4, 8, 8, 0, 255, 0 );
+
+
+ /* Draw bars indicating number of buffers allocated
+ * (not a great measure, easily confused)
+ */
+ if (dev_priv->dma_used) {
+ int bar = dev_priv->dma_used / 10240;
+ if (bar > 100) bar = 100;
+ if (bar < 1) bar = 1;
+ i830_fill_box( dev, 4, 16, bar, 4, 196, 128, 128 );
+ dev_priv->dma_used = 0;
+ }
+
+ dev_priv->sarea_priv->perf_boxes = 0;
}
static void i830_dma_dispatch_clear( drm_device_t *dev, int flags,
@@ -793,6 +934,15 @@ static void i830_dma_dispatch_clear( drm_device_t *dev, int flags,
unsigned int BR13, CMD, D_CMD;
RING_LOCALS;
+
+ if ( dev_priv->current_page == 1 ) {
+ unsigned int tmp = flags;
+
+ flags &= ~(I830_FRONT | I830_BACK);
+ if ( tmp & I830_FRONT ) flags |= I830_BACK;
+ if ( tmp & I830_BACK ) flags |= I830_FRONT;
+ }
+
i830_kernel_lost_context(dev);
switch(cpp) {
@@ -872,13 +1022,17 @@ static void i830_dma_dispatch_swap( drm_device_t *dev )
drm_clip_rect_t *pbox = sarea_priv->boxes;
int pitch = dev_priv->pitch;
int cpp = dev_priv->cpp;
- int ofs = dev_priv->back_offset;
int i;
unsigned int CMD, BR13;
RING_LOCALS;
DRM_DEBUG("swapbuffers\n");
+ i830_kernel_lost_context(dev);
+
+ if (dev_priv->do_boxes)
+ i830_cp_performance_boxes( dev );
+
switch(cpp) {
case 2:
BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24);
@@ -895,7 +1049,6 @@ static void i830_dma_dispatch_swap( drm_device_t *dev )
break;
}
- i830_kernel_lost_context(dev);
if (nbox > I830_NR_SAREA_CLIPRECTS)
nbox = I830_NR_SAREA_CLIPRECTS;
@@ -915,23 +1068,72 @@ static void i830_dma_dispatch_swap( drm_device_t *dev )
BEGIN_LP_RING( 8 );
OUT_RING( CMD );
OUT_RING( BR13 );
+ OUT_RING( (pbox->y1 << 16) | pbox->x1 );
+ OUT_RING( (pbox->y2 << 16) | pbox->x2 );
- OUT_RING( (pbox->y1 << 16) |
- pbox->x1 );
- OUT_RING( (pbox->y2 << 16) |
- pbox->x2 );
-
- OUT_RING( dev_priv->front_offset );
- OUT_RING( (pbox->y1 << 16) |
- pbox->x1 );
+ if (dev_priv->current_page == 0)
+ OUT_RING( dev_priv->front_offset );
+ else
+ OUT_RING( dev_priv->back_offset );
+ OUT_RING( (pbox->y1 << 16) | pbox->x1 );
OUT_RING( BR13 & 0xffff );
- OUT_RING( ofs );
+
+ if (dev_priv->current_page == 0)
+ OUT_RING( dev_priv->back_offset );
+ else
+ OUT_RING( dev_priv->front_offset );
ADVANCE_LP_RING();
}
}
+static void i830_dma_dispatch_flip( drm_device_t *dev )
+{
+ drm_i830_private_t *dev_priv = dev->dev_private;
+ RING_LOCALS;
+
+ DRM_DEBUG( "%s: page=%d pfCurrentPage=%d\n",
+ __FUNCTION__,
+ dev_priv->current_page,
+ dev_priv->sarea_priv->pf_current_page);
+
+ i830_kernel_lost_context(dev);
+
+ if (dev_priv->do_boxes) {
+ dev_priv->sarea_priv->perf_boxes |= I830_BOX_FLIP;
+ i830_cp_performance_boxes( dev );
+ }
+
+
+ BEGIN_LP_RING( 2 );
+ OUT_RING( INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE );
+ OUT_RING( 0 );
+ ADVANCE_LP_RING();
+
+ BEGIN_LP_RING( 6 );
+ OUT_RING( CMD_OP_DISPLAYBUFFER_INFO | ASYNC_FLIP );
+ OUT_RING( 0 );
+ if ( dev_priv->current_page == 0 ) {
+ OUT_RING( dev_priv->back_offset );
+ dev_priv->current_page = 1;
+ } else {
+ OUT_RING( dev_priv->front_offset );
+ dev_priv->current_page = 0;
+ }
+ OUT_RING(0);
+ ADVANCE_LP_RING();
+
+
+ BEGIN_LP_RING( 2 );
+ OUT_RING( MI_WAIT_FOR_EVENT |
+ MI_WAIT_FOR_PLANE_A_FLIP );
+ OUT_RING( 0 );
+ ADVANCE_LP_RING();
+
+
+ dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
+}
static void i830_dma_dispatch_vertex(drm_device_t *dev,
drm_buf_t *buf,
@@ -984,8 +1186,10 @@ static void i830_dma_dispatch_vertex(drm_device_t *dev,
sarea_priv->vertex_prim |
((used/4)-2));
- vp[used/4] = MI_BATCH_BUFFER_END;
- used += 4;
+ if (dev_priv->use_mi_batchbuffer_start) {
+ vp[used/4] = MI_BATCH_BUFFER_END;
+ used += 4;
+ }
if (used & 4) {
vp[used/4] = 0;
@@ -1008,11 +1212,21 @@ static void i830_dma_dispatch_vertex(drm_device_t *dev,
ADVANCE_LP_RING();
}
- BEGIN_LP_RING(2);
- OUT_RING( MI_BATCH_BUFFER_START | (2<<6) );
- OUT_RING( start | MI_BATCH_NON_SECURE );
- ADVANCE_LP_RING();
-
+ if (dev_priv->use_mi_batchbuffer_start) {
+ BEGIN_LP_RING(2);
+ OUT_RING( MI_BATCH_BUFFER_START | (2<<6) );
+ OUT_RING( start | MI_BATCH_NON_SECURE );
+ ADVANCE_LP_RING();
+ }
+ else {
+ BEGIN_LP_RING(4);
+ OUT_RING( MI_BATCH_BUFFER );
+ OUT_RING( start | MI_BATCH_NON_SECURE );
+ OUT_RING( start + used - 4 );
+ OUT_RING( 0 );
+ ADVANCE_LP_RING();
+ }
+
} while (++i < nbox);
}
@@ -1050,7 +1264,7 @@ void i830_dma_quiescent(drm_device_t *dev)
OUT_RING( 0 );
ADVANCE_LP_RING();
- i830_wait_ring( dev, dev_priv->ring.Size - 8 );
+ i830_wait_ring( dev, dev_priv->ring.Size - 8, __FUNCTION__ );
}
static int i830_flush_queue(drm_device_t *dev)
@@ -1067,7 +1281,7 @@ static int i830_flush_queue(drm_device_t *dev)
OUT_RING( 0 );
ADVANCE_LP_RING();
- i830_wait_ring( dev, dev_priv->ring.Size - 8 );
+ i830_wait_ring( dev, dev_priv->ring.Size - 8, __FUNCTION__ );
for (i = 0; i < dma->buf_count; i++) {
drm_buf_t *buf = dma->buflist[ i ];
@@ -1086,8 +1300,10 @@ static int i830_flush_queue(drm_device_t *dev)
}
/* Must be called with the lock held */
-void i830_reclaim_buffers(drm_device_t *dev, pid_t pid)
+void i830_reclaim_buffers( struct file *filp )
{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
drm_device_dma_t *dma = dev->dma;
int i;
@@ -1101,7 +1317,7 @@ void i830_reclaim_buffers(drm_device_t *dev, pid_t pid)
drm_buf_t *buf = dma->buflist[ i ];
drm_i830_buf_priv_t *buf_priv = buf->dev_private;
- if (buf->pid == pid && buf_priv) {
+ if (buf->filp == filp && buf_priv) {
int used = cmpxchg(buf_priv->in_use, I830_BUF_CLIENT,
I830_BUF_FREE);
@@ -1207,6 +1423,53 @@ int i830_swap_bufs(struct inode *inode, struct file *filp,
return 0;
}
+
+
+/* Not sure why this isn't set all the time:
+ */
+static void i830_do_init_pageflip( drm_device_t *dev )
+{
+ drm_i830_private_t *dev_priv = dev->dev_private;
+
+ DRM_DEBUG("%s\n", __FUNCTION__);
+ dev_priv->page_flipping = 1;
+ dev_priv->current_page = 0;
+ dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
+}
+
+int i830_do_cleanup_pageflip( drm_device_t *dev )
+{
+ drm_i830_private_t *dev_priv = dev->dev_private;
+
+ DRM_DEBUG("%s\n", __FUNCTION__);
+ if (dev_priv->current_page != 0)
+ i830_dma_dispatch_flip( dev );
+
+ dev_priv->page_flipping = 0;
+ return 0;
+}
+
+int i830_flip_bufs(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_i830_private_t *dev_priv = dev->dev_private;
+
+ DRM_DEBUG("%s\n", __FUNCTION__);
+
+ if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
+ DRM_ERROR("i830_flip_buf called without lock held\n");
+ return -EINVAL;
+ }
+
+ if (!dev_priv->page_flipping)
+ i830_do_init_pageflip( dev );
+
+ i830_dma_dispatch_flip( dev );
+ return 0;
+}
+
int i830_getage(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg)
{
@@ -1270,3 +1533,66 @@ int i830_docopy(struct inode *inode, struct file *filp, unsigned int cmd,
{
return 0;
}
+
+
+
+int i830_getparam( struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg )
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_i830_private_t *dev_priv = dev->dev_private;
+ drm_i830_getparam_t param;
+ int value;
+
+ if ( !dev_priv ) {
+ DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+ return -EINVAL;
+ }
+
+ if (copy_from_user(&param, (drm_i830_getparam_t *)arg, sizeof(param) ))
+ return -EFAULT;
+
+ switch( param.param ) {
+ case I830_PARAM_IRQ_ACTIVE:
+ value = dev->irq ? 1 : 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if ( copy_to_user( param.value, &value, sizeof(int) ) ) {
+ DRM_ERROR( "copy_to_user\n" );
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+
+int i830_setparam( struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg )
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_i830_private_t *dev_priv = dev->dev_private;
+ drm_i830_setparam_t param;
+
+ if ( !dev_priv ) {
+ DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+ return -EINVAL;
+ }
+
+ if (copy_from_user(&param, (drm_i830_setparam_t *)arg, sizeof(param) ))
+ return -EFAULT;
+
+ switch( param.param ) {
+ case I830_SETPARAM_USE_MI_BATCHBUFFER_START:
+ dev_priv->use_mi_batchbuffer_start = param.value;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
diff --git a/linux/i830_drm.h b/linux/i830_drm.h
index 725ad369..664ab0ed 100644
--- a/linux/i830_drm.h
+++ b/linux/i830_drm.h
@@ -3,6 +3,9 @@
/* WARNING: These defines must be the same as what the Xserver uses.
* if you change them, you must change the defines in the Xserver.
+ *
+ * KW: Actually, you can't ever change them because doing so would
+ * break backwards compatibility.
*/
#ifndef _I830_DEFINES_
@@ -18,14 +21,12 @@
#define I830_NR_TEX_REGIONS 64
#define I830_LOG_MIN_TEX_REGION_SIZE 16
-/* if defining I830_ENABLE_4_TEXTURES, do it in i830_3d_reg.h, too */
-#if !defined(I830_ENABLE_4_TEXTURES)
+/* KW: These aren't correct but someone set them to two and then
+ * released the module. Now we can't change them as doing so would
+ * break backwards compatibility.
+ */
#define I830_TEXTURE_COUNT 2
-#define I830_TEXBLEND_COUNT 2 /* always same as TEXTURE_COUNT? */
-#else /* defined(I830_ENABLE_4_TEXTURES) */
-#define I830_TEXTURE_COUNT 4
-#define I830_TEXBLEND_COUNT 4 /* always same as TEXTURE_COUNT? */
-#endif /* I830_ENABLE_4_TEXTURES */
+#define I830_TEXBLEND_COUNT I830_TEXTURE_COUNT
#define I830_TEXBLEND_SIZE 12 /* (4 args + op) * 2 + COLOR_FACTOR */
@@ -57,6 +58,7 @@
#define I830_UPLOAD_TEXBLEND_MASK 0xf00000
#define I830_UPLOAD_TEX_PALETTE_N(n) (0x1000000 << (n))
#define I830_UPLOAD_TEX_PALETTE_SHARED 0x4000000
+#define I830_UPLOAD_STIPPLE 0x8000000
/* 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,
@@ -73,7 +75,6 @@
*/
#define I830_DESTREG_CBUFADDR 0
-/* Invarient */
#define I830_DESTREG_DBUFADDR 1
#define I830_DESTREG_DV0 2
#define I830_DESTREG_DV1 3
@@ -109,6 +110,13 @@
#define I830_CTXREG_MCSB1 16
#define I830_CTX_SETUP_SIZE 17
+/* 1.3: Stipple state
+ */
+#define I830_STPREG_ST0 0
+#define I830_STPREG_ST1 1
+#define I830_STP_SETUP_SIZE 2
+
+
/* Texture state (per tex unit)
*/
@@ -124,6 +132,18 @@
#define I830_TEXREG_MCS 9 /* GFX_OP_MAP_COORD_SETS */
#define I830_TEX_SETUP_SIZE 10
+#define I830_TEXREG_TM0LI 0 /* load immediate 2 texture map n */
+#define I830_TEXREG_TM0S0 1
+#define I830_TEXREG_TM0S1 2
+#define I830_TEXREG_TM0S2 3
+#define I830_TEXREG_TM0S3 4
+#define I830_TEXREG_TM0S4 5
+#define I830_TEXREG_NOP0 6 /* noop */
+#define I830_TEXREG_NOP1 7 /* noop */
+#define I830_TEXREG_NOP2 8 /* noop */
+#define __I830_TEXREG_MCS 9 /* GFX_OP_MAP_COORD_SETS -- shared */
+#define __I830_TEX_SETUP_SIZE 10
+
#define I830_FRONT 0x1
#define I830_BACK 0x2
#define I830_DEPTH 0x4
@@ -199,8 +219,35 @@ typedef struct _drm_i830_sarea {
int ctxOwner; /* last context to upload state */
int vertex_prim;
+
+ int pf_enabled; /* is pageflipping allowed? */
+ int pf_active;
+ int pf_current_page; /* which buffer is being displayed? */
+
+ int perf_boxes; /* performance boxes to be displayed */
+
+ /* Here's the state for texunits 2,3:
+ */
+ unsigned int TexState2[I830_TEX_SETUP_SIZE];
+ unsigned int TexBlendState2[I830_TEXBLEND_SIZE];
+ unsigned int TexBlendStateWordsUsed2;
+
+ unsigned int TexState3[I830_TEX_SETUP_SIZE];
+ unsigned int TexBlendState3[I830_TEXBLEND_SIZE];
+ unsigned int TexBlendStateWordsUsed3;
+
+ unsigned int StippleState[I830_STP_SETUP_SIZE];
} drm_i830_sarea_t;
+/* Flags for perf_boxes
+ */
+#define I830_BOX_RING_EMPTY 0x1 /* populated by kernel */
+#define I830_BOX_FLIP 0x2 /* populated by kernel */
+#define I830_BOX_WAIT 0x4 /* populated by kernel & client */
+#define I830_BOX_TEXTURE_LOAD 0x8 /* populated by kernel */
+#define I830_BOX_LOST_CONTEXT 0x10 /* populated by client */
+
+
/* I830 specific ioctls
* The device specific ioctl range is 0x40 to 0x79.
*/
@@ -213,6 +260,11 @@ typedef struct _drm_i830_sarea {
#define DRM_IOCTL_I830_SWAP DRM_IO ( 0x46)
#define DRM_IOCTL_I830_COPY DRM_IOW( 0x47, drm_i830_copy_t)
#define DRM_IOCTL_I830_DOCOPY DRM_IO ( 0x48)
+#define DRM_IOCTL_I830_FLIP DRM_IO ( 0x49)
+#define DRM_IOCTL_I830_IRQ_EMIT DRM_IOWR(0x4a, drm_i830_irq_emit_t)
+#define DRM_IOCTL_I830_IRQ_WAIT DRM_IOW( 0x4b, drm_i830_irq_wait_t)
+#define DRM_IOCTL_I830_GETPARAM DRM_IOWR(0x4c, drm_i830_getparam_t)
+#define DRM_IOCTL_I830_SETPARAM DRM_IOWR(0x4d, drm_i830_setparam_t)
typedef struct _drm_i830_clear {
int clear_color;
@@ -248,4 +300,36 @@ typedef struct drm_i830_dma {
int granted;
} drm_i830_dma_t;
+
+/* 1.3: Userspace can request & wait on irq's:
+ */
+typedef struct drm_i830_irq_emit {
+ int *irq_seq;
+} drm_i830_irq_emit_t;
+
+typedef struct drm_i830_irq_wait {
+ int irq_seq;
+} drm_i830_irq_wait_t;
+
+
+/* 1.3: New ioctl to query kernel params:
+ */
+#define I830_PARAM_IRQ_ACTIVE 1
+
+typedef struct drm_i830_getparam {
+ int param;
+ int *value;
+} drm_i830_getparam_t;
+
+
+/* 1.3: New ioctl to set kernel params:
+ */
+#define I830_SETPARAM_USE_MI_BATCHBUFFER_START 1
+
+typedef struct drm_i830_setparam {
+ int param;
+ int value;
+} drm_i830_setparam_t;
+
+
#endif /* _I830_DRM_H_ */
diff --git a/linux/i830_drv.h b/linux/i830_drv.h
index eec640ca..37313afd 100644
--- a/linux/i830_drv.h
+++ b/linux/i830_drv.h
@@ -78,6 +78,19 @@ typedef struct drm_i830_private {
int back_pitch;
int depth_pitch;
unsigned int cpp;
+
+ int do_boxes;
+ int dma_used;
+
+ int current_page;
+ int page_flipping;
+
+ wait_queue_head_t irq_queue;
+ atomic_t irq_received;
+ atomic_t irq_emitted;
+
+ int use_mi_batchbuffer_start;
+
} drm_i830_private_t;
/* i830_dma.c */
@@ -88,7 +101,7 @@ extern int i830_dma_init(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern int i830_flush_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
-extern void i830_reclaim_buffers(drm_device_t *dev, pid_t pid);
+extern void i830_reclaim_buffers(struct file *filp);
extern int i830_getage(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg);
extern int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma);
@@ -108,6 +121,23 @@ extern int i830_swap_bufs(struct inode *inode, struct file *filp,
extern int i830_clear_bufs(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
+extern int i830_flip_bufs(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+
+extern int i830_getparam( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg );
+
+extern int i830_setparam( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg );
+
+/* i830_irq.c */
+extern int i830_irq_emit( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg );
+extern int i830_irq_wait( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg );
+extern int i830_wait_irq(drm_device_t *dev, int irq_nr);
+extern int i830_emit_irq(drm_device_t *dev);
+
#define I830_BASE(reg) ((unsigned long) \
dev_priv->mmio_map->handle)
@@ -119,12 +149,53 @@ extern int i830_clear_bufs(struct inode *inode, struct file *filp,
#define I830_READ16(reg) I830_DEREF16(reg)
#define I830_WRITE16(reg,val) do { I830_DEREF16(reg) = val; } while (0)
+
+
+#define I830_VERBOSE 0
+
+#define RING_LOCALS unsigned int outring, ringmask, outcount; \
+ volatile char *virt;
+
+#define BEGIN_LP_RING(n) do { \
+ if (I830_VERBOSE) \
+ printk("BEGIN_LP_RING(%d) in %s\n", \
+ n, __FUNCTION__); \
+ if (dev_priv->ring.space < n*4) \
+ i830_wait_ring(dev, n*4, __FUNCTION__); \
+ outcount = 0; \
+ outring = dev_priv->ring.tail; \
+ ringmask = dev_priv->ring.tail_mask; \
+ virt = dev_priv->ring.virtual_start; \
+} while (0)
+
+
+#define OUT_RING(n) do { \
+ if (I830_VERBOSE) printk(" OUT_RING %x\n", (int)(n)); \
+ *(volatile unsigned int *)(virt + outring) = n; \
+ outcount++; \
+ outring += 4; \
+ outring &= ringmask; \
+} while (0)
+
+#define ADVANCE_LP_RING() do { \
+ if (I830_VERBOSE) printk("ADVANCE_LP_RING %x\n", outring); \
+ dev_priv->ring.tail = outring; \
+ dev_priv->ring.space -= outcount * 4; \
+ I830_WRITE(LP_RING + RING_TAIL, outring); \
+} while(0)
+
+extern int i830_wait_ring(drm_device_t *dev, int n, const char *caller);
+
+
#define GFX_OP_USER_INTERRUPT ((0<<29)|(2<<23))
#define GFX_OP_BREAKPOINT_INTERRUPT ((0<<29)|(1<<23))
#define CMD_REPORT_HEAD (7<<23)
#define CMD_STORE_DWORD_IDX ((0x21<<23) | 0x1)
#define CMD_OP_BATCH_BUFFER ((0x0<<29)|(0x30<<23)|0x1)
+#define STATE3D_LOAD_STATE_IMMEDIATE_2 ((0x3<<29)|(0x1d<<24)|(0x03<<16))
+#define LOAD_TEXTURE_MAP0 (1<<11)
+
#define INST_PARSER_CLIENT 0x00000000
#define INST_OP_FLUSH 0x02000000
#define INST_FLUSH_MAP_CACHE 0x00000001
@@ -140,6 +211,9 @@ extern int i830_clear_bufs(struct inode *inode, struct file *filp,
#define I830REG_INT_MASK_R 0x020a8
#define I830REG_INT_ENABLE_R 0x020a0
+#define I830_IRQ_RESERVED ((1<<13)|(3<<2))
+
+
#define LP_RING 0x2030
#define HP_RING 0x2040
#define RING_TAIL 0x00
@@ -182,6 +256,9 @@ extern int i830_clear_bufs(struct inode *inode, struct file *filp,
#define CMD_OP_DESTBUFFER_INFO ((0x3<<29)|(0x1d<<24)|(0x8e<<16)|1)
+#define CMD_OP_DISPLAYBUFFER_INFO ((0x0<<29)|(0x14<<23)|2)
+#define ASYNC_FLIP (1<<22)
+
#define CMD_3D (0x3<<29)
#define STATE3D_CONST_BLEND_COLOR_CMD (CMD_3D|(0x1d<<24)|(0x88<<16))
#define STATE3D_MAP_COORD_SETBIND_CMD (CMD_3D|(0x1d<<24)|(0x02<<16))
@@ -213,6 +290,11 @@ extern int i830_clear_bufs(struct inode *inode, struct file *filp,
#define MI_BATCH_BUFFER_END (0xA<<23)
#define MI_BATCH_NON_SECURE (1)
+#define MI_WAIT_FOR_EVENT ((0x3<<23))
+#define MI_WAIT_FOR_PLANE_A_FLIP (1<<2)
+#define MI_WAIT_FOR_PLANE_A_SCANLINES (1<<1)
+
+#define MI_LOAD_SCAN_LINES_INCL ((0x12<<23))
#endif
diff --git a/linux/i830_irq.c b/linux/i830_irq.c
new file mode 100644
index 00000000..cedafc0d
--- /dev/null
+++ b/linux/i830_irq.c
@@ -0,0 +1,178 @@
+/* i830_dma.c -- DMA support for the I830 -*- linux-c -*-
+ *
+ * Copyright 2002 Tungsten 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, 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
+ * 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: Keith Whitwell <keith@tungstengraphics.com>
+ *
+ */
+
+#define __NO_VERSION__
+#include "i830.h"
+#include "drmP.h"
+#include "drm.h"
+#include "i830_drm.h"
+#include "i830_drv.h"
+#include <linux/interrupt.h> /* For task queue support */
+#include <linux/delay.h>
+
+
+void DRM(dma_service)(int irq, void *device, struct pt_regs *regs)
+{
+ drm_device_t *dev = (drm_device_t *)device;
+ drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private;
+ u16 temp;
+
+ temp = I830_READ16(I830REG_INT_IDENTITY_R);
+ printk("%s: %x\n", __FUNCTION__, temp);
+
+ if(temp == 0)
+ return;
+
+ I830_WRITE16(I830REG_INT_IDENTITY_R, temp);
+
+ if (temp & 2) {
+ atomic_inc(&dev_priv->irq_received);
+ wake_up_interruptible(&dev_priv->irq_queue);
+ }
+}
+
+
+int i830_emit_irq(drm_device_t *dev)
+{
+ drm_i830_private_t *dev_priv = dev->dev_private;
+ RING_LOCALS;
+
+ DRM_DEBUG("%s\n", __FUNCTION__);
+
+ atomic_inc(&dev_priv->irq_emitted);
+
+ BEGIN_LP_RING(2);
+ OUT_RING( 0 );
+ OUT_RING( GFX_OP_USER_INTERRUPT );
+ ADVANCE_LP_RING();
+
+ return atomic_read(&dev_priv->irq_emitted);
+}
+
+
+int i830_wait_irq(drm_device_t *dev, int irq_nr)
+{
+ drm_i830_private_t *dev_priv =
+ (drm_i830_private_t *)dev->dev_private;
+ DECLARE_WAITQUEUE(entry, current);
+ unsigned long end = jiffies + HZ*3;
+ int ret = 0;
+
+ DRM_DEBUG("%s\n", __FUNCTION__);
+
+ if (atomic_read(&dev_priv->irq_received) >= irq_nr)
+ return 0;
+
+ dev_priv->sarea_priv->perf_boxes |= I830_BOX_WAIT;
+
+ add_wait_queue(&dev_priv->irq_queue, &entry);
+
+ for (;;) {
+ current->state = TASK_INTERRUPTIBLE;
+ if (atomic_read(&dev_priv->irq_received) >= irq_nr)
+ break;
+ if((signed)(end - jiffies) <= 0) {
+ DRM_ERROR("timeout iir %x imr %x ier %x hwstam %x\n",
+ I830_READ16( I830REG_INT_IDENTITY_R ),
+ I830_READ16( I830REG_INT_MASK_R ),
+ I830_READ16( I830REG_INT_ENABLE_R ),
+ I830_READ16( I830REG_HWSTAM ));
+
+ ret = -EBUSY; /* Lockup? Missed irq? */
+ break;
+ }
+ schedule_timeout(HZ*3);
+ if (signal_pending(current)) {
+ ret = -EINTR;
+ break;
+ }
+ }
+
+ current->state = TASK_RUNNING;
+ remove_wait_queue(&dev_priv->irq_queue, &entry);
+ return ret;
+}
+
+
+/* Needs the lock as it touches the ring.
+ */
+int i830_irq_emit( struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg )
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_i830_private_t *dev_priv = dev->dev_private;
+ drm_i830_irq_emit_t emit;
+ int result;
+
+ if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
+ DRM_ERROR("i830_irq_emit called without lock held\n");
+ return -EINVAL;
+ }
+
+ if ( !dev_priv ) {
+ DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+ return -EINVAL;
+ }
+
+ if (copy_from_user( &emit, (drm_i830_irq_emit_t *)arg, sizeof(emit) ))
+ return -EFAULT;
+
+ result = i830_emit_irq( dev );
+
+ if ( copy_to_user( emit.irq_seq, &result, sizeof(int) ) ) {
+ DRM_ERROR( "copy_to_user\n" );
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+
+/* Doesn't need the hardware lock.
+ */
+int i830_irq_wait( struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg )
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_i830_private_t *dev_priv = dev->dev_private;
+ drm_i830_irq_wait_t irqwait;
+
+ if ( !dev_priv ) {
+ DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+ return -EINVAL;
+ }
+
+ if (copy_from_user( &irqwait, (drm_i830_irq_wait_t *)arg,
+ sizeof(irqwait) ))
+ return -EFAULT;
+
+ return i830_wait_irq( dev, irqwait.irq_seq );
+}
+
diff --git a/linux/sis.h b/linux/sis.h
index 0bf3dfa9..bc66f4dc 100644
--- a/linux/sis.h
+++ b/linux/sis.h
@@ -24,7 +24,7 @@
* DEALINGS IN THE SOFTWARE.
*
*/
-/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/sis.h,v 1.2 2001/12/19 21:25:59 dawes Exp $ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/sis.h,v 1.3 2002/10/30 12:52:38 alanh Exp $ */
#ifndef __SIS_H__
#define __SIS_H__
diff --git a/linux/sis_mm.c b/linux/sis_mm.c
index 81832769..b2aa22d4 100644
--- a/linux/sis_mm.c
+++ b/linux/sis_mm.c
@@ -183,10 +183,10 @@ int sisp_agp_alloc(struct inode *inode, struct file *filp, unsigned int cmd,
if(block){
/* TODO */
agp.offset = block->ofs;
- agp.free = (unsigned int)block;
+ agp.free = (unsigned long)block;
if(!add_alloc_set(agp.context, AGP_TYPE, agp.free)){
DRM_DEBUG("adding to allocation set fails\n");
- mmFreeMem((PMemBlock)agp.free);
+ mmFreeMem((PMemBlock)(unsigned long)agp.free);
retval = -1;
}
}
@@ -219,7 +219,7 @@ int sisp_agp_free(struct inode *inode, struct file *filp, unsigned int cmd,
return -1;
}
- mmFreeMem((PMemBlock)agp.free);
+ mmFreeMem((PMemBlock)(unsigned long)agp.free);
if(!del_alloc_set(agp.context, AGP_TYPE, agp.free))
retval = -1;
@@ -289,7 +289,7 @@ int sis_final_context(int context)
retval = setFirst(set, &item);
while(retval){
DRM_DEBUG("free agp memory 0x%x\n", item);
- mmFreeMem((PMemBlock)item);
+ mmFreeMem((PMemBlock)(unsigned long)item);
retval = setNext(set, &item);
}
setDestroy(set);