summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/fops.c5
-rw-r--r--xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_dma.c339
-rw-r--r--xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_drm_public.h3
-rw-r--r--xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_drv.h5
4 files changed, 285 insertions, 67 deletions
diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/fops.c b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/fops.c
index c33806f6e..63c746a67 100644
--- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/fops.c
+++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/fops.c
@@ -106,8 +106,9 @@ int drm_release(struct inode *inode, struct file *filp)
processed via a callback to the X
server. */
}
- drm_reclaim_buffers(dev, priv->pid);
-
+#if 0
+ drm_reclaim_buffers(dev, priv->pid);
+#endif
drm_fasync(-1, filp, 0);
down(&dev->struct_sem);
diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_dma.c b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_dma.c
index 8c17459bf..5253f27fb 100644
--- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_dma.c
+++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_dma.c
@@ -47,8 +47,12 @@
#define MGA_DEREF(reg) *(__volatile__ int *)MGA_ADDR(reg)
#define MGA_READ(reg) MGA_DEREF(reg)
#define MGA_WRITE(reg,val) do { MGA_DEREF(reg) = val; } while (0)
+#define MGA_DEREF8(reg) *(__volatile__ u8 *)MGA_ADDR(reg)
+#define MGA_READ8(reg) MGA_DEREF8(reg)
+#define MGA_WRITE8(reg,val) do { MGA_DEREF8(reg) = val; } while (0)
#define PDEA_pagpxfer_enable 0x2
+#define MGA_TOP_SYNC_TAG 0x3784f700
#define MGA_SYNC_TAG 0x423f4200
typedef enum {
@@ -58,6 +62,31 @@ typedef enum {
TT_VERTEX
} transferType_t;
+static unsigned long mga_alloc_page(drm_device_t *dev)
+{
+ unsigned long address;
+
+ address = __get_free_page(GFP_KERNEL);
+ if(address == 0UL) {
+ return 0;
+ }
+ atomic_inc(&mem_map[MAP_NR((void *) address)].count);
+ set_bit(PG_locked, &mem_map[MAP_NR((void *) address)].flags);
+
+ return address;
+}
+
+static void mga_free_page(drm_device_t *dev, unsigned long page)
+{
+ if(page == 0UL) {
+ return;
+ }
+ atomic_dec(&mem_map[MAP_NR((void *) page)].count);
+ clear_bit(PG_locked, &mem_map[MAP_NR((void *) page)].flags);
+ wake_up(&mem_map[MAP_NR((void *) page)].wait);
+ free_page(page);
+ return;
+}
static void mga_delay(void)
{
@@ -77,6 +106,12 @@ int mga_dma_cleanup(drm_device_t *dev)
drm_ioremapfree((void *) dev_priv->ioremap, temp);
}
+ if(dev_priv->status_page != NULL) {
+ iounmap(dev_priv->status_page);
+ }
+ if(dev_priv->real_status_page != 0UL) {
+ mga_free_page(dev, dev_priv->real_status_page);
+ }
drm_free(dev->dev_private, sizeof(drm_mga_private_t),
DRM_MEM_DRIVER);
@@ -145,6 +180,16 @@ static int mga_alloc_kernel_queue(drm_device_t *dev)
return DRM_KERNEL_CONTEXT;
}
+static unsigned int mga_create_sync_tag(drm_mga_private_t *dev_priv)
+{
+ unsigned int temp;
+
+ dev_priv->sync_tag++;
+ temp = dev_priv->sync_tag << 2;
+ printk("sync_tag : %x\n", temp);
+ return temp;
+}
+
static int mga_dma_initialize(drm_device_t *dev, drm_mga_init_t *init) {
drm_mga_private_t *dev_priv;
drm_map_t *prim_map = NULL;
@@ -152,7 +197,6 @@ static int mga_dma_initialize(drm_device_t *dev, drm_mga_init_t *init) {
int temp;
int i;
-
dev_priv = drm_alloc(sizeof(drm_mga_private_t), DRM_MEM_DRIVER);
if(dev_priv == NULL) return -ENOMEM;
dev->dev_private = (void *) dev_priv;
@@ -173,6 +217,7 @@ static int mga_dma_initialize(drm_device_t *dev, drm_mga_init_t *init) {
if(mga_alloc_kernel_queue(dev) != DRM_KERNEL_CONTEXT) {
mga_dma_cleanup(dev);
DRM_ERROR("Kernel context queue not present\n");
+ return -ENOMEM;
}
dev_priv->reserved_map_idx = init->reserved_map_idx;
@@ -248,6 +293,31 @@ static int mga_dma_initialize(drm_device_t *dev, drm_mga_init_t *init) {
dev_priv->current_dma_ptr = dev_priv->prim_head;
dev_priv->prim_num_dwords = 0;
dev_priv->prim_max_dwords = dev_priv->primary_size / 4;
+ dev_priv->real_status_page = mga_alloc_page(dev);
+ if(dev_priv->real_status_page == 0UL) {
+ mga_dma_cleanup(dev);
+ DRM_ERROR("Can not allocate status page\n");
+ return -ENOMEM;
+ }
+ printk("Status page at %lx\n", dev_priv->real_status_page);
+ dev_priv->status_page = ioremap_nocache(virt_to_bus((void *) dev_priv->real_status_page),
+ PAGE_SIZE);
+ if(dev_priv->status_page == NULL) {
+ mga_dma_cleanup(dev);
+ DRM_ERROR("Can not remap status page\n");
+ return -ENOMEM;
+ }
+
+ printk("Status page remapped to %p\n", dev_priv->status_page);
+ /* Write status page when secend or softrap occurs */
+ MGA_WRITE(MGAREG_PRIMPTR, virt_to_bus((void *)dev_priv->real_status_page) | 0x00000003);
+
+ dev_priv->device = pci_find_device(0x102b, 0x0525, NULL);
+ if(dev_priv->device == NULL) {
+ DRM_ERROR("Could not find pci device for card\n");
+ mga_dma_cleanup(dev);
+ return -EINVAL;
+ }
if (MGA_VERBOSE)
@@ -255,14 +325,17 @@ static int mga_dma_initialize(drm_device_t *dev, drm_mga_init_t *init) {
/* Private is now filled in, initialize the hardware */
{
+ __volatile__ unsigned int *status = (unsigned int *)dev_priv->status_page;
PRIMLOCALS;
PRIMRESET( dev_priv );
PRIMGETPTR( dev_priv );
-
+
+ dev_priv->last_sync_tag = mga_create_sync_tag(dev_priv);
+
PRIMOUTREG(MGAREG_DMAPAD, 0);
PRIMOUTREG(MGAREG_DMAPAD, 0);
- PRIMOUTREG(MGAREG_DWGSYNC, 0);
+ PRIMOUTREG(MGAREG_DWGSYNC, dev_priv->last_sync_tag);
PRIMOUTREG(MGAREG_SOFTRAP, 0);
PRIMADVANCE( dev_priv );
@@ -270,21 +343,20 @@ static int mga_dma_initialize(drm_device_t *dev, drm_mga_init_t *init) {
/* Poll for the first buffer to insure that
* the status register will be correct
*/
- MGA_WRITE(MGAREG_DWGSYNC, MGA_SYNC_TAG);
-
- while(MGA_READ(MGAREG_DWGSYNC) != MGA_SYNC_TAG) {
- for(i = 0 ; i < 4096; i++) mga_delay();
- }
+ printk("phys_head : %lx\n", (unsigned long)phys_head);
+ status[1] = 0;
+
MGA_WRITE(MGAREG_PRIMADDRESS, phys_head | TT_GENERAL);
MGA_WRITE(MGAREG_PRIMEND, ((phys_head + num_dwords * 4) |
PDEA_pagpxfer_enable));
-
- while(MGA_READ(MGAREG_DWGSYNC) == MGA_SYNC_TAG) {
- for(i = 0; i < 4096; i++) mga_delay();
- }
-
+
+ while(MGA_READ(MGAREG_DWGSYNC) != dev_priv->last_sync_tag) ;
+ printk("status[0] after initialization : %x\n", status[0]);
+ printk("status[1] after initialization : %x\n", status[1]);
+ printk("status[2] after initialization : %x\n", status[2]);
+ printk("status[3] after initialization : %x\n", status[3]);
}
if (MGA_VERBOSE)
@@ -312,12 +384,13 @@ int mga_dma_init(struct inode *inode, struct file *filp,
}
-
+#if 0
static void __mga_iload_small(drm_device_t *dev, drm_buf_t *buf)
{
int use_agp = PDEA_pagpxfer_enable;
drm_mga_private_t *dev_priv = dev->dev_private;
drm_mga_buf_priv_t *buf_priv = buf->dev_private;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
unsigned long address = (unsigned long)buf->bus_address;
int length = buf->used;
int y1 = buf_priv->boxes[0].y1;
@@ -331,6 +404,8 @@ static void __mga_iload_small(drm_device_t *dev, drm_buf_t *buf)
PRIMRESET(dev_priv);
PRIMGETPTR(dev_priv);
+ dev_priv->last_sync_tag = mga_create_sync_tag(dev_priv);
+
PRIMOUTREG(MGAREG_DSTORG, dstorg );
PRIMOUTREG(MGAREG_MACCESS, maccess);
PRIMOUTREG(MGAREG_PITCH, (1 << 15));
@@ -350,11 +425,23 @@ static void __mga_iload_small(drm_device_t *dev, drm_buf_t *buf)
PRIMOUTREG(MGAREG_DMAPAD, 0);
PRIMOUTREG(MGAREG_SECADDRESS, ((__u32)address) | TT_BLIT);
PRIMOUTREG(MGAREG_SECEND, ((__u32)(address + length)) | use_agp);
-
- PRIMOUTREG(MGAREG_DMAPAD, 0);
+
PRIMOUTREG(MGAREG_DMAPAD, 0);
PRIMOUTREG(MGAREG_DMAPAD, 0);
+ PRIMOUTREG(MGAREG_DWGSYNC, dev_priv->last_sync_tag);
PRIMOUTREG(MGAREG_SOFTRAP, 0);
+
+ PRIMADVANCE(dev_priv);
+#if 0
+ /* For now we need to set this in the ioctl */
+ sarea_priv->dirty |= MGASAREA_NEW_CONTEXT;
+#endif
+
+ if(sarea_priv->dirty & MGA_DMA_FLUSH) {
+ printk("Dma top flush\n");
+ while((MGA_READ(MGAREG_STATUS) & 0x00030001) != 0x00020000) ;
+ sarea_priv->dirty &= ~(MGA_DMA_FLUSH);
+ }
PRIMADVANCE(dev_priv);
MGA_WRITE(MGAREG_PRIMADDRESS, dev_priv->prim_phys_head | TT_GENERAL);
@@ -366,6 +453,7 @@ static void __mga_iload_xy(drm_device_t *dev, drm_buf_t *buf )
int use_agp = PDEA_pagpxfer_enable;
drm_mga_private_t *dev_priv = dev->dev_private;
drm_mga_buf_priv_t *buf_priv = buf->dev_private;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
unsigned long address = (unsigned long)buf->bus_address;
int length = buf->used;
int y1 = buf_priv->boxes[0].y1;
@@ -400,6 +488,8 @@ static void __mga_iload_xy(drm_device_t *dev, drm_buf_t *buf )
x2 = (x2 + (texperdword - 1)) & ~(texperdword - 1);
x1 = (x1 + (texperdword - 1)) & ~(texperdword - 1);
width = x2 - x1;
+
+ dev_priv->last_sync_tag = mga_create_sync_tag(dev_priv);
PRIMRESET(dev_priv);
PRIMGETPTR(dev_priv);
@@ -418,12 +508,21 @@ static void __mga_iload_xy(drm_device_t *dev, drm_buf_t *buf )
PRIMOUTREG(MGAREG_SECADDRESS, ((__u32)address) | TT_BLIT);
PRIMOUTREG(MGAREG_SECEND, ((__u32)(address + length)) | use_agp);
- PRIMOUTREG(MGAREG_DSTORG, dev_priv->frontOffset);
- PRIMOUTREG(MGAREG_MACCESS, dev_priv->mAccess);
- PRIMOUTREG(MGAREG_PITCH, dev_priv->stride);
+ PRIMOUTREG(MGAREG_DMAPAD, 0);
+ PRIMOUTREG(MGAREG_DMAPAD, 0);
+ PRIMOUTREG(MGAREG_DWGSYNC, dev_priv->last_sync_tag);
PRIMOUTREG(MGAREG_SOFTRAP, 0);
PRIMADVANCE(dev_priv);
-
+#if 0
+ /* For now we need to set this in the ioctl */
+ sarea_priv->dirty |= MGASAREA_NEW_CONTEXT;
+#endif
+ if(sarea_priv->dirty & MGA_DMA_FLUSH) {
+ printk("Dma top flush\n");
+ while((MGA_READ(MGAREG_STATUS) & 0x00030001) != 0x00020000) ;
+ sarea_priv->dirty &= ~(MGA_DMA_FLUSH);
+ }
+
MGA_WRITE(MGAREG_PRIMADDRESS, dev_priv->prim_phys_head | TT_GENERAL);
MGA_WRITE(MGAREG_PRIMEND, (phys_head + num_dwords * 4) | use_agp);
}
@@ -445,12 +544,14 @@ static void mga_dma_dispatch_iload(drm_device_t *dev, drm_buf_t *buf)
__mga_iload_xy(dev, buf);
}
}
+#endif
static void mga_dma_dispatch_tex_blit(drm_device_t *dev, drm_buf_t *buf )
{
int use_agp = PDEA_pagpxfer_enable;
drm_mga_private_t *dev_priv = dev->dev_private;
drm_mga_buf_priv_t *buf_priv = buf->dev_private;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
unsigned long address = (unsigned long)buf->bus_address;
int length = buf->used;
int y1 = buf_priv->boxes[0].y1;
@@ -509,6 +610,13 @@ static void mga_dma_dispatch_tex_blit(drm_device_t *dev, drm_buf_t *buf )
PRIMOUTREG(MGAREG_SOFTRAP, 0);
PRIMADVANCE(dev_priv);
+ if(sarea_priv->dirty & MGA_DMA_FLUSH) {
+ printk("Dma top flush\n");
+ while((MGA_READ(MGAREG_STATUS) & 0x00030001) != 0x00020000) ;
+ sarea_priv->dirty &= ~(MGA_DMA_FLUSH);
+ }
+
+
MGA_WRITE(MGAREG_PRIMADDRESS, dev_priv->prim_phys_head | TT_GENERAL);
MGA_WRITE(MGAREG_PRIMEND, (phys_head + num_dwords * 4) | use_agp);
@@ -519,6 +627,8 @@ static void mga_dma_dispatch_vertex(drm_device_t *dev, drm_buf_t *buf)
drm_mga_private_t *dev_priv = dev->dev_private;
drm_mga_buf_priv_t *buf_priv = buf->dev_private;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+
drm_buf_t *real_buf = dev->dma->buflist[ buf_priv->vertex_real_idx ];
unsigned long address = (unsigned long)real_buf->bus_address;
int length = buf->used; /* this is correct */
@@ -548,12 +658,21 @@ static void mga_dma_dispatch_vertex(drm_device_t *dev, drm_buf_t *buf)
use_agp));
PRIMADVANCE( dev_priv );
}
+
+ dev_priv->last_sync_tag = mga_create_sync_tag(dev_priv);
- PRIMGETPTR(dev_priv);
- PRIMOUTREG( MGAREG_DMAPAD, 0);
- PRIMOUTREG( MGAREG_DMAPAD, 0);
- PRIMOUTREG( MGAREG_DMAPAD, 0);
- PRIMOUTREG( MGAREG_SOFTRAP, 0);
+ PRIMGETPTR( dev_priv );
+ PRIMOUTREG(MGAREG_DMAPAD, 0);
+ PRIMOUTREG(MGAREG_DMAPAD, 0);
+ PRIMOUTREG(MGAREG_DWGSYNC, dev_priv->last_sync_tag);
+ PRIMOUTREG(MGAREG_SOFTRAP, 0);
+
+ if(sarea_priv->dirty & MGA_DMA_FLUSH) {
+ printk("Dma top flush\n");
+ while((MGA_READ(MGAREG_STATUS) & 0x00030001) != 0x00020000) ;
+ sarea_priv->dirty &= ~(MGA_DMA_FLUSH);
+ }
+
PRIMADVANCE( dev_priv );
MGA_WRITE(MGAREG_PRIMADDRESS, dev_priv->prim_phys_head | TT_GENERAL);
@@ -566,6 +685,7 @@ static void mga_dma_dispatch_vertex(drm_device_t *dev, drm_buf_t *buf)
static void mga_dma_dispatch_general(drm_device_t *dev, drm_buf_t *buf)
{
drm_mga_private_t *dev_priv = dev->dev_private;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
unsigned long address = (unsigned long)buf->bus_address;
int length = buf->used;
int use_agp = PDEA_pagpxfer_enable;
@@ -574,26 +694,77 @@ static void mga_dma_dispatch_general(drm_device_t *dev, drm_buf_t *buf)
PRIMRESET(dev_priv);
PRIMGETPTR(dev_priv);
+ dev_priv->last_sync_tag = mga_create_sync_tag(dev_priv);
+
PRIMOUTREG( MGAREG_DMAPAD, 0);
PRIMOUTREG( MGAREG_DMAPAD, 0);
- PRIMOUTREG( MGAREG_SECADDRESS, ((__u32)address) | TT_GENERAL);
+ PRIMOUTREG( MGAREG_SECADDRESS, ((__u32)address) | TT_GENERAL);
PRIMOUTREG( MGAREG_SECEND, (((__u32)(address + length)) | use_agp));
-
PRIMOUTREG( MGAREG_DMAPAD, 0);
PRIMOUTREG( MGAREG_DMAPAD, 0);
- PRIMOUTREG( MGAREG_DMAPAD, 0);
+ PRIMOUTREG( MGAREG_DWGSYNC, dev_priv->last_sync_tag);
PRIMOUTREG( MGAREG_SOFTRAP, 0);
PRIMADVANCE(dev_priv);
-
+
+ if(sarea_priv->dirty & MGA_DMA_FLUSH) {
+ printk("Dma top flush\n");
+ while((MGA_READ(MGAREG_STATUS) & 0x00030001) != 0x00020000) ;
+ sarea_priv->dirty &= ~(MGA_DMA_FLUSH);
+ }
+
MGA_WRITE(MGAREG_PRIMADDRESS, dev_priv->prim_phys_head | TT_GENERAL);
MGA_WRITE(MGAREG_PRIMEND, (phys_head + num_dwords * 4) | use_agp);
}
+void mga_wait_usec(int waittime)
+{
+ struct timeval timep;
+ int top_usec = 0;
+ int bot_usec = 0;
+ int i;
+
+ while(1) {
+ do_gettimeofday(&timep);
+ top_usec = timep.tv_usec;
+ if((bot_usec = 0) || (top_usec < bot_usec)) {
+ bot_usec = top_usec;
+ } else if ((top_usec - bot_usec) > waittime) {
+ break;
+ }
+ for(i = 0 ; i < 4096; i++) mga_delay();
+ }
+
+ return;
+}
+
+void mga_reset_abort(drm_device_t *dev)
+{
+ drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
+ u32 temp;
+ u32 reset;
+
+ pci_read_config_dword(dev_priv->device,
+ 0x04,
+ &temp);
+ reset = temp;
+ reset &= 0x38000000;
+ if(reset != 0) {
+ /* Do a softreset */
+ printk("Doing a soft reset : reset %x\n", reset);
+ MGA_WRITE(0x1e40, 0x00000001);
+ mga_wait_usec(10);
+ MGA_WRITE(0x1e40, 0x00000000);
+ pci_write_config_dword(dev_priv->device,
+ 0x04,
+ temp);
+ }
+}
static void mga_dma_dispatch_clear( drm_device_t *dev, drm_buf_t *buf )
{
drm_mga_private_t *dev_priv = dev->dev_private;
drm_mga_buf_priv_t *buf_priv = buf->dev_private;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
int nbox = buf_priv->nbox;
xf86drmClipRectRec *pbox = buf_priv->boxes;
int flags = buf_priv->clear_flags;
@@ -674,17 +845,21 @@ static void mga_dma_dispatch_clear( drm_device_t *dev, drm_buf_t *buf )
PRIMOUTREG( MGAREG_SOFTRAP, 0);
PRIMADVANCE(dev_priv);
+ if(sarea_priv->dirty & MGA_DMA_FLUSH) {
+ printk("Dma top flush\n");
+ while((MGA_READ(MGAREG_STATUS) & 0x00030001) != 0x00020000) ;
+ sarea_priv->dirty &= ~(MGA_DMA_FLUSH);
+ }
+
MGA_WRITE(MGAREG_PRIMADDRESS, dev_priv->prim_phys_head | TT_GENERAL);
MGA_WRITE(MGAREG_PRIMEND, (phys_head + num_dwords * 4) | use_agp);
}
-
-
-
static void mga_dma_dispatch_swap( drm_device_t *dev, drm_buf_t *buf )
{
drm_mga_private_t *dev_priv = dev->dev_private;
drm_mga_buf_priv_t *buf_priv = buf->dev_private;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
int nbox = buf_priv->nbox;
xf86drmClipRectRec *pbox = buf_priv->boxes;
int use_agp = PDEA_pagpxfer_enable;
@@ -726,15 +901,31 @@ static void mga_dma_dispatch_swap( drm_device_t *dev, drm_buf_t *buf )
PRIMOUTREG( MGAREG_DMAPAD, 0);
PRIMOUTREG( MGAREG_SOFTRAP, 0);
PRIMADVANCE(dev_priv);
+
+ if(sarea_priv->dirty & MGA_DMA_FLUSH) {
+ printk("Dma top flush\n");
+ while((MGA_READ(MGAREG_STATUS) & 0x00030001) != 0x00020000) ;
+ sarea_priv->dirty &= ~(MGA_DMA_FLUSH);
+ }
MGA_WRITE(MGAREG_PRIMADDRESS, dev_priv->prim_phys_head | TT_GENERAL);
MGA_WRITE(MGAREG_PRIMEND, (phys_head + num_dwords * 4) | use_agp);
}
+#if 0
+void mga_force_reset(drm_device_t *dev)
+{
+ printk("mga_force_reset\n");
+ MGA_WRITE(0x1e40, 0x00000001);
+ mga_wait_usec(10);
+ MGA_WRITE(0x1e40, 0x00000000);
+}
+#endif
static void mga_dma_dispatch_bad( drm_device_t *dev, drm_buf_t *buf )
{
drm_mga_private_t *dev_priv = dev->dev_private;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
int use_agp = PDEA_pagpxfer_enable;
PRIMLOCALS;
@@ -745,6 +936,12 @@ static void mga_dma_dispatch_bad( drm_device_t *dev, drm_buf_t *buf )
PRIMOUTREG( MGAREG_DMAPAD, 0);
PRIMOUTREG( MGAREG_SOFTRAP, 0);
PRIMADVANCE(dev_priv);
+
+ if(sarea_priv->dirty & MGA_DMA_FLUSH) {
+ printk("Dma top flush\n");
+ while((MGA_READ(MGAREG_STATUS) & 0x00030001) != 0x00020000) ;
+ sarea_priv->dirty &= ~(MGA_DMA_FLUSH);
+ }
MGA_WRITE(MGAREG_PRIMADDRESS, dev_priv->prim_phys_head | TT_GENERAL);
MGA_WRITE(MGAREG_PRIMEND, (phys_head + num_dwords * 4) | use_agp);
@@ -753,23 +950,27 @@ static void mga_dma_dispatch_bad( drm_device_t *dev, drm_buf_t *buf )
/* Frees dispatch lock */
static inline void mga_dma_quiescent(drm_device_t *dev)
{
- drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
-
- while(1) {
- atomic_inc(&dev_priv->dispatch_lock);
- if(atomic_read(&dev_priv->dispatch_lock) == 1) {
- break;
- } else {
- atomic_dec(&dev_priv->dispatch_lock);
- }
+ drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ __volatile__ unsigned int *status =
+ (__volatile__ unsigned int *)dev_priv->status_page;
+
+ while(1) {
+ atomic_inc(&dev_priv->dispatch_lock);
+ if(atomic_read(&dev_priv->dispatch_lock) == 1) {
+ break;
+ } else {
+ atomic_dec(&dev_priv->dispatch_lock);
+ }
}
-#if 1
- MGA_WRITE(MGAREG_DWGSYNC, MGA_SYNC_TAG);
- while(MGA_READ(MGAREG_DWGSYNC) != MGA_SYNC_TAG) ;
- MGA_WRITE(MGAREG_DWGSYNC, 0);
- while(MGA_READ(MGAREG_DWGSYNC) != 0) ;
-#endif
- atomic_dec(&dev_priv->dispatch_lock);
+
+ printk("quiescent status : %x\n", MGA_READ(MGAREG_STATUS));
+ mga_reset_abort(dev);
+ while((MGA_READ(MGAREG_STATUS) & 0x00030001) != 0x00020000) ;
+ printk("status[1] : %x last_sync_tag : %x\n", status[1],
+ dev_priv->last_sync_tag);
+ sarea_priv->dirty |= MGA_DMA_FLUSH;
+ atomic_dec(&dev_priv->dispatch_lock);
}
/* Keeps dispatch lock held */
@@ -778,9 +979,12 @@ static inline int mga_dma_is_ready(drm_device_t *dev)
{
drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
+ mga_reset_abort(dev);
+
atomic_inc(&dev_priv->dispatch_lock);
if(atomic_read(&dev_priv->dispatch_lock) == 1) {
/* We got the lock */
+ while((MGA_READ(MGAREG_STATUS) & 0x00020000) != 0x00020000) ;
return 1;
} else {
atomic_dec(&dev_priv->dispatch_lock);
@@ -811,7 +1015,7 @@ static void mga_dma_service(int irq, void *device, struct pt_regs *regs)
drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
atomic_inc(&dev->total_irq);
- MGA_WRITE(MGAREG_ICLEAR, 0xfa7);
+ MGA_WRITE(MGAREG_ICLEAR, 0x00000001);
atomic_dec(&dev_priv->dispatch_lock);
/* Free previous buffer */
@@ -1085,7 +1289,9 @@ int mga_irq_install(drm_device_t *dev, int irq)
dev->tq.data = dev;
/* Before installing handler */
- MGA_WRITE(MGAREG_ICLEAR, 0xfa7);
+#if 0
+ MGA_WRITE(MGAREG_ICLEAR, 0x00000001);
+#endif
MGA_WRITE(MGAREG_IEN, 0);
/* Install handler */
@@ -1101,7 +1307,7 @@ int mga_irq_install(drm_device_t *dev, int irq)
}
/* After installing handler */
- MGA_WRITE(MGAREG_ICLEAR, 0xfa7);
+ MGA_WRITE(MGAREG_ICLEAR, 0x00000001);
MGA_WRITE(MGAREG_IEN, 0x00000001);
return 0;
@@ -1121,10 +1327,11 @@ int mga_irq_uninstall(drm_device_t *dev)
if (MGA_VERBOSE)
printk("remove irq handler %d\n", irq);
- MGA_WRITE(MGAREG_ICLEAR, 0xfa7);
+ MGA_WRITE(MGAREG_ICLEAR, 0x00000001);
MGA_WRITE(MGAREG_IEN, 0);
- MGA_WRITE(MGAREG_ICLEAR, 0xfa7);
-
+#if 0
+ MGA_WRITE(MGAREG_ICLEAR, 0x00000001);
+#endif
free_irq(irq, dev);
return 0;
@@ -1243,10 +1450,12 @@ int mga_lock(struct inode *inode, struct file *filp, unsigned int cmd,
remove_wait_queue(&dev->lock.lock_queue, &entry);
}
- if (lock.flags & _DRM_LOCK_QUIESCENT) {
+ if ((lock.flags & _DRM_LOCK_QUIESCENT) && (ret == 0)) {
ret = mga_flush_queue(dev);
if(ret != 0) atomic_dec(&dev_priv->in_flush);
- } else {
+ wake_up_interruptible(&dev->lock.lock_queue);
+ goto out_lock;
+ } else if (ret == 0) {
atomic_dec(&dev_priv->in_flush);
}
/* Only one queue:
@@ -1285,19 +1494,21 @@ int mga_lock(struct inode *inode, struct file *filp, unsigned int cmd,
if (!ret) {
if (lock.flags & _DRM_LOCK_QUIESCENT) {
- if (MGA_VERBOSE) printk("_DRM_LOCK_QUIESCENT\n");
-#if 0
+ printk("_DRM_LOCK_QUIESCENT\n");
mga_dma_quiescent(dev);
-#endif
+/* atomic_set(&dev_priv->pending_bufs, 0); */
atomic_dec(&dev_priv->in_flush);
wake_up_interruptible(&dev->lock.lock_queue);
}
+ } else {
+ if (lock.flags & _DRM_LOCK_QUIESCENT) {
+ atomic_dec(&dev_priv->in_flush);
+ wake_up_interruptible(&dev->lock.lock_queue);
+ }
}
-
- if (MGA_VERBOSE)
- printk("%d %s\n", lock.context,
- ret ? "interrupted" : "has lock");
-
+
+out_lock:
+ printk("%d %s\n", lock.context, ret ? "interrupted" : "has lock");
return ret;
}
diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_drm_public.h b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_drm_public.h
index cded9314a..01e76e1a0 100644
--- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_drm_public.h
+++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_drm_public.h
@@ -156,7 +156,8 @@ typedef struct _xf86drmClipRectRec {
#define MGA_UPLOAD_2D 0x40
#define MGA_REQUIRE_QUIESCENT 0x80 /* handled client-side */
#define MGA_UPLOAD_CLIPRECTS 0x100
-
+#define MGA_DMA_FLUSH 0x200
+/* dirty flag when someone gets the lock quiescent */
#define MGA_DMA_BUF_ORDER 16
#define MGA_DMA_BUF_SZ (1<<MGA_DMA_BUF_ORDER)
diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_drv.h b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_drv.h
index ebbcab55d..0cb104b6e 100644
--- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_drv.h
+++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_drv.h
@@ -54,12 +54,17 @@ typedef struct _drm_mga_private {
atomic_t dispatch_lock;
atomic_t pending_bufs;
atomic_t in_flush;
+ unsigned int last_sync_tag;
+ unsigned int sync_tag;
+ void *status_page;
+ unsigned long real_status_page;
void *ioremap;
u32 *prim_head;
u32 *current_dma_ptr;
u32 prim_phys_head;
int prim_num_dwords;
int prim_max_dwords;
+ struct pci_dev *device;
/* Some validated register values: