mirror of
https://gitlab.freedesktop.org/mesa/drm.git
synced 2026-05-08 11:38:13 +02:00
Added multiple outstanding dma requests for the mga
This commit is contained in:
parent
4f4242d4c8
commit
5ae11234d9
9 changed files with 1072 additions and 1374 deletions
|
|
@ -104,31 +104,16 @@ static drm_buf_t *i810_freelist_get(drm_device_t *dev)
|
|||
|
||||
/* Linear search might not be the best solution */
|
||||
|
||||
#if 0
|
||||
i810_print_status_page(dev);
|
||||
#endif
|
||||
for (i = 0; i < dma->buf_count; i++) {
|
||||
drm_buf_t *buf = dma->buflist[ i ];
|
||||
drm_i810_buf_priv_t *buf_priv = buf->dev_private;
|
||||
/* In use is already a pointer */
|
||||
#if 0
|
||||
printk("idx : %d in_use : %d\n", i, *buf_priv->in_use);
|
||||
#endif
|
||||
used = cmpxchg(buf_priv->in_use, I810_BUF_FREE,
|
||||
I810_BUF_USED);
|
||||
#if 0
|
||||
printk("used : %d\n", used);
|
||||
#endif
|
||||
if(used == I810_BUF_FREE) {
|
||||
#if 0
|
||||
printk("Got buffer\n");
|
||||
#endif
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
printk("Didn't get buffer\n");
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -142,9 +127,6 @@ static int i810_freelist_put(drm_device_t *dev, drm_buf_t *buf)
|
|||
int used;
|
||||
|
||||
/* In use is already a pointer */
|
||||
#if 0
|
||||
i810_print_status_page(dev);
|
||||
#endif
|
||||
used = cmpxchg(buf_priv->in_use, I810_BUF_USED, I810_BUF_FREE);
|
||||
if(used != I810_BUF_USED) {
|
||||
DRM_ERROR("Freeing buffer thats not in use : %d\n", buf->idx);
|
||||
|
|
@ -300,9 +282,6 @@ static int i810_freelist_init(drm_device_t *dev)
|
|||
buf_priv->my_use_idx = my_idx;
|
||||
my_idx += 4;
|
||||
}
|
||||
#if 0
|
||||
i810_print_status_page(dev);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -495,10 +474,7 @@ static inline void i810_dma_dispatch_vertex(drm_device_t *dev, drm_buf_t *buf)
|
|||
|
||||
static inline void i810_dma_quiescent(drm_device_t *dev)
|
||||
{
|
||||
#if 0
|
||||
/* Not written yet */
|
||||
drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Interrupts are only for flushing */
|
||||
|
|
@ -600,9 +576,7 @@ int i810_irq_uninstall(drm_device_t *dev)
|
|||
|
||||
if (!irq) return -EINVAL;
|
||||
|
||||
DRM_DEBUG( "Interrupt UnInstall: %d\n", irq);
|
||||
|
||||
|
||||
DRM_DEBUG( "Interrupt UnInstall: %d\n", irq);
|
||||
DRM_DEBUG("%d\n", irq);
|
||||
|
||||
temp = I810_READ16(I810REG_INT_IDENTITY_R);
|
||||
|
|
@ -669,16 +643,10 @@ static int i810_flush_queue(drm_device_t *dev)
|
|||
drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
|
||||
int ret = 0;
|
||||
|
||||
#if 0
|
||||
printk("i810_flush_queue\n");
|
||||
#endif
|
||||
if(dev_priv == NULL) {
|
||||
return 0;
|
||||
}
|
||||
atomic_set(&dev_priv->flush_done, 0);
|
||||
#if 0
|
||||
printk("got to flush\n");
|
||||
#endif
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
add_wait_queue(&dev_priv->flush_queue, &entry);
|
||||
for (;;) {
|
||||
|
|
@ -779,9 +747,6 @@ int i810_lock(struct inode *inode, struct file *filp, unsigned int cmd,
|
|||
/* Contention */
|
||||
atomic_inc(&dev->total_sleeps);
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
#if 0
|
||||
current->policy |= SCHED_YIELD;
|
||||
#endif
|
||||
DRM_DEBUG("Calling lock schedule\n");
|
||||
schedule();
|
||||
if (signal_pending(current)) {
|
||||
|
|
|
|||
|
|
@ -71,8 +71,7 @@ GAMMAHEADERS= gamma_drv.h $(DRMHEADERS)
|
|||
TDFXOBJS= tdfx_drv.o tdfx_context.o
|
||||
TDFXHEADERS= tdfx_drv.h $(DRMHEADERS)
|
||||
|
||||
MGAOBJS= mga_drv.o mga_dma.o mga_bufs.o mga_state.o mga_clear.o \
|
||||
mga_context.o
|
||||
MGAOBJS= mga_drv.o mga_dma.o mga_bufs.o mga_state.o mga_context.o
|
||||
MGAHEADERS= mga_drv.h mga_drm_public.h $(DRMHEADERS)
|
||||
|
||||
R128OBJS= r128_drv.o r128_context.o
|
||||
|
|
|
|||
|
|
@ -104,31 +104,16 @@ static drm_buf_t *i810_freelist_get(drm_device_t *dev)
|
|||
|
||||
/* Linear search might not be the best solution */
|
||||
|
||||
#if 0
|
||||
i810_print_status_page(dev);
|
||||
#endif
|
||||
for (i = 0; i < dma->buf_count; i++) {
|
||||
drm_buf_t *buf = dma->buflist[ i ];
|
||||
drm_i810_buf_priv_t *buf_priv = buf->dev_private;
|
||||
/* In use is already a pointer */
|
||||
#if 0
|
||||
printk("idx : %d in_use : %d\n", i, *buf_priv->in_use);
|
||||
#endif
|
||||
used = cmpxchg(buf_priv->in_use, I810_BUF_FREE,
|
||||
I810_BUF_USED);
|
||||
#if 0
|
||||
printk("used : %d\n", used);
|
||||
#endif
|
||||
if(used == I810_BUF_FREE) {
|
||||
#if 0
|
||||
printk("Got buffer\n");
|
||||
#endif
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
printk("Didn't get buffer\n");
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -142,9 +127,6 @@ static int i810_freelist_put(drm_device_t *dev, drm_buf_t *buf)
|
|||
int used;
|
||||
|
||||
/* In use is already a pointer */
|
||||
#if 0
|
||||
i810_print_status_page(dev);
|
||||
#endif
|
||||
used = cmpxchg(buf_priv->in_use, I810_BUF_USED, I810_BUF_FREE);
|
||||
if(used != I810_BUF_USED) {
|
||||
DRM_ERROR("Freeing buffer thats not in use : %d\n", buf->idx);
|
||||
|
|
@ -300,9 +282,6 @@ static int i810_freelist_init(drm_device_t *dev)
|
|||
buf_priv->my_use_idx = my_idx;
|
||||
my_idx += 4;
|
||||
}
|
||||
#if 0
|
||||
i810_print_status_page(dev);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -495,10 +474,7 @@ static inline void i810_dma_dispatch_vertex(drm_device_t *dev, drm_buf_t *buf)
|
|||
|
||||
static inline void i810_dma_quiescent(drm_device_t *dev)
|
||||
{
|
||||
#if 0
|
||||
/* Not written yet */
|
||||
drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Interrupts are only for flushing */
|
||||
|
|
@ -600,9 +576,7 @@ int i810_irq_uninstall(drm_device_t *dev)
|
|||
|
||||
if (!irq) return -EINVAL;
|
||||
|
||||
DRM_DEBUG( "Interrupt UnInstall: %d\n", irq);
|
||||
|
||||
|
||||
DRM_DEBUG( "Interrupt UnInstall: %d\n", irq);
|
||||
DRM_DEBUG("%d\n", irq);
|
||||
|
||||
temp = I810_READ16(I810REG_INT_IDENTITY_R);
|
||||
|
|
@ -669,16 +643,10 @@ static int i810_flush_queue(drm_device_t *dev)
|
|||
drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
|
||||
int ret = 0;
|
||||
|
||||
#if 0
|
||||
printk("i810_flush_queue\n");
|
||||
#endif
|
||||
if(dev_priv == NULL) {
|
||||
return 0;
|
||||
}
|
||||
atomic_set(&dev_priv->flush_done, 0);
|
||||
#if 0
|
||||
printk("got to flush\n");
|
||||
#endif
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
add_wait_queue(&dev_priv->flush_queue, &entry);
|
||||
for (;;) {
|
||||
|
|
@ -779,9 +747,6 @@ int i810_lock(struct inode *inode, struct file *filp, unsigned int cmd,
|
|||
/* Contention */
|
||||
atomic_inc(&dev->total_sleeps);
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
#if 0
|
||||
current->policy |= SCHED_YIELD;
|
||||
#endif
|
||||
DRM_DEBUG("Calling lock schedule\n");
|
||||
schedule();
|
||||
if (signal_pending(current)) {
|
||||
|
|
|
|||
|
|
@ -194,51 +194,11 @@ int mga_rmctx(struct inode *inode, struct file *filp, unsigned int cmd,
|
|||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->dev;
|
||||
drm_ctx_t ctx;
|
||||
drm_queue_t *q;
|
||||
drm_buf_t *buf;
|
||||
|
||||
copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT);
|
||||
printk("%d\n", ctx.handle);
|
||||
if(ctx.handle == DRM_KERNEL_CONTEXT) {
|
||||
q = dev->queuelist[ctx.handle];
|
||||
atomic_inc(&q->use_count);
|
||||
if (atomic_read(&q->use_count) == 1) {
|
||||
/* No longer in use */
|
||||
atomic_dec(&q->use_count);
|
||||
return -EINVAL;
|
||||
}
|
||||
atomic_inc(&q->finalization); /* Mark queue in finalization state */
|
||||
atomic_sub(2, &q->use_count);
|
||||
/* Mark queue as unused (pending finalization) */
|
||||
|
||||
while (test_and_set_bit(0, &dev->interrupt_flag)) {
|
||||
printk("Calling schedule from rmctx\n");
|
||||
schedule();
|
||||
if (signal_pending(current)) {
|
||||
clear_bit(0, &dev->interrupt_flag);
|
||||
return -EINTR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove queued buffers */
|
||||
while ((buf = drm_waitlist_get(&q->waitlist))) {
|
||||
drm_free_buffer(dev, buf);
|
||||
}
|
||||
clear_bit(0, &dev->interrupt_flag);
|
||||
|
||||
/* Wakeup blocked processes */
|
||||
wake_up_interruptible(&q->read_queue);
|
||||
wake_up_interruptible(&q->write_queue);
|
||||
wake_up_interruptible(&q->flush_queue);
|
||||
|
||||
/* Finalization over. Queue is made
|
||||
available when both use_count and
|
||||
finalization become 0, which won't
|
||||
happen until all the waiting processes
|
||||
stop waiting. */
|
||||
atomic_dec(&q->finalization);
|
||||
} else {
|
||||
drm_ctxbitmap_free(dev, ctx.handle);
|
||||
if(ctx.handle != DRM_KERNEL_CONTEXT) {
|
||||
drm_ctxbitmap_free(dev, ctx.handle);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
1445
linux/mga_dma.c
1445
linux/mga_dma.c
File diff suppressed because it is too large
Load diff
157
linux/mga_dma.h
157
linux/mga_dma.h
|
|
@ -2,35 +2,17 @@
|
|||
#define MGA_DMA_H
|
||||
|
||||
#include "mga_drm_public.h"
|
||||
typedef enum {
|
||||
TT_GENERAL,
|
||||
TT_BLIT,
|
||||
TT_VECTOR,
|
||||
TT_VERTEX
|
||||
} transferType_t;
|
||||
|
||||
|
||||
/* Isn't this fun - we copy the outstanding card state for every
|
||||
* MGA_DMA_VERTEX buffer. This has to be fixed asap by emitting
|
||||
* primary dma commands in the 'vertex_dma' ioctl.
|
||||
*/
|
||||
typedef struct {
|
||||
int dma_type;
|
||||
|
||||
unsigned int ContextState[MGA_CTX_SETUP_SIZE];
|
||||
unsigned int ServerState[MGA_2D_SETUP_SIZE];
|
||||
unsigned int TexState[2][MGA_TEX_SETUP_SIZE];
|
||||
unsigned int WarpPipe;
|
||||
unsigned int dirty;
|
||||
|
||||
unsigned short clear_color;
|
||||
unsigned short clear_zval;
|
||||
unsigned int clear_flags;
|
||||
|
||||
unsigned int vertex_real_idx;
|
||||
unsigned int vertex_discard;
|
||||
|
||||
unsigned int age;
|
||||
|
||||
unsigned int nbox;
|
||||
xf86drmClipRectRec boxes[MGA_NR_SAREA_CLIPRECTS];
|
||||
} drm_mga_buf_priv_t;
|
||||
|
||||
|
||||
#define MGA_DMA_GENERAL 0 /* not used */
|
||||
#define MGA_DMA_VERTEX 1
|
||||
#define MGA_DMA_SETUP 2
|
||||
|
|
@ -39,7 +21,6 @@ typedef struct {
|
|||
#define MGA_DMA_SWAP 5 /* placeholder */
|
||||
#define MGA_DMA_DISCARD 6
|
||||
|
||||
|
||||
#define DWGREG0 0x1c00
|
||||
#define DWGREG0_END 0x1dff
|
||||
#define DWGREG1 0x2c00
|
||||
|
|
@ -50,93 +31,72 @@ typedef struct {
|
|||
#define ADRINDEX1(r) (u8)(((r - DWGREG1) >> 2) | 0x80)
|
||||
#define ADRINDEX(r) (ISREG0(r) ? ADRINDEX0(r) : ADRINDEX1(r))
|
||||
|
||||
|
||||
|
||||
#define MGA_VERBOSE 0
|
||||
|
||||
|
||||
|
||||
/* Macros for inserting commands into a secondary dma buffer.
|
||||
*/
|
||||
#define DMALOCALS u8 tempIndex[4]; u32 *dma_ptr; \
|
||||
int outcount, num_dwords;
|
||||
|
||||
#define DMAGETPTR(buf) do { \
|
||||
dma_ptr = (u32 *)((u8 *)buf->address + buf->used); \
|
||||
outcount = 0; \
|
||||
num_dwords = buf->used / 4; \
|
||||
if (MGA_VERBOSE) \
|
||||
printk(KERN_INFO "DMAGETPTR in %s, start %d\n", \
|
||||
__FUNCTION__, num_dwords); \
|
||||
} while(0)
|
||||
|
||||
#define DMAADVANCE(buf) do { \
|
||||
if (MGA_VERBOSE) \
|
||||
printk(KERN_INFO "DMAADVANCE\n"); \
|
||||
buf->used = num_dwords * 4; \
|
||||
} while(0)
|
||||
|
||||
#define DMAOUTREG(reg, val) do { \
|
||||
tempIndex[outcount]=ADRINDEX(reg); \
|
||||
dma_ptr[++outcount] = val; \
|
||||
if (MGA_VERBOSE) \
|
||||
printk(KERN_INFO \
|
||||
" DMAOUT %d: 0x%x -- 0x%x\n", \
|
||||
num_dwords +1+outcount, ADRINDEX(reg), val); \
|
||||
if (outcount == 4) { \
|
||||
outcount = 0; \
|
||||
dma_ptr[0] = *(u32 *)tempIndex; \
|
||||
dma_ptr+=5; \
|
||||
num_dwords += 5; \
|
||||
} \
|
||||
}while (0)
|
||||
|
||||
|
||||
|
||||
#define MGA_NUM_PRIM_BUFS 4
|
||||
/* Primary buffer versions of above -- pretty similar really.
|
||||
*/
|
||||
|
||||
#define PRIMLOCALS u8 tempIndex[4]; u32 *dma_ptr; u32 phys_head; \
|
||||
int outcount, num_dwords
|
||||
|
||||
#define PRIMRESET(dev_priv) do { \
|
||||
dev_priv->prim_num_dwords = 0; \
|
||||
dev_priv->current_dma_ptr = dev_priv->prim_head; \
|
||||
} while (0)
|
||||
|
||||
#define PRIMGETPTR(dev_priv) do { \
|
||||
dma_ptr = dev_priv->current_dma_ptr; \
|
||||
phys_head = dev_priv->prim_phys_head; \
|
||||
num_dwords = dev_priv->prim_num_dwords; \
|
||||
outcount = 0; \
|
||||
if (MGA_VERBOSE) \
|
||||
printk(KERN_INFO "PRIMGETPTR in %s, start %d\n", \
|
||||
__FUNCTION__, num_dwords); \
|
||||
} while (0)
|
||||
#define PRIM_OVERFLOW(dev, dev_priv, length) do { \
|
||||
drm_mga_prim_buf_t *tmp_buf = \
|
||||
dev_priv->prim_bufs[dev_priv->current_prim_idx]; \
|
||||
if( (tmp_buf->max_dwords - tmp_buf->num_dwords) < length || \
|
||||
tmp_buf->sec_used > (MGA_DMA_BUF_NR / 2)) { \
|
||||
mga_advance_primary(dev); \
|
||||
mga_dma_schedule(dev, 1); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define PRIMADVANCEPAD(dev_priv) do { \
|
||||
while(outcount & 3) { \
|
||||
if (MGA_VERBOSE) \
|
||||
printk(KERN_INFO "PAD %d\n", \
|
||||
num_dwords + 1 + outcount); \
|
||||
tempIndex[outcount++]=0x15; \
|
||||
} \
|
||||
\
|
||||
if (MGA_VERBOSE) \
|
||||
printk(KERN_INFO "PRIMADVANCEPAD\n"); \
|
||||
dev_priv->prim_num_dwords = num_dwords; \
|
||||
dev_priv->current_dma_ptr = dma_ptr; \
|
||||
} while (0)
|
||||
#define PRIMGETPTR(dev_priv) do { \
|
||||
drm_mga_prim_buf_t *tmp_buf = \
|
||||
dev_priv->prim_bufs[dev_priv->current_prim_idx]; \
|
||||
if(MGA_VERBOSE) \
|
||||
printk("PRIMGETPTR in %s\n", __FUNCTION__); \
|
||||
dma_ptr = tmp_buf->current_dma_ptr; \
|
||||
num_dwords = tmp_buf->num_dwords; \
|
||||
phys_head = tmp_buf->phys_head; \
|
||||
outcount = 0; \
|
||||
} while(0)
|
||||
|
||||
#define PRIMADVANCE(dev_priv) do { \
|
||||
#define PRIMPTR(prim_buf) do { \
|
||||
if(MGA_VERBOSE) \
|
||||
printk("PRIMPTR in %s\n", __FUNCTION__); \
|
||||
dma_ptr = prim_buf->current_dma_ptr; \
|
||||
num_dwords = prim_buf->num_dwords; \
|
||||
phys_head = prim_buf->phys_head; \
|
||||
outcount = 0; \
|
||||
} while(0)
|
||||
|
||||
#define PRIMFINISH(prim_buf) do { \
|
||||
if (MGA_VERBOSE) { \
|
||||
printk(KERN_INFO "PRIMADVANCE\n"); \
|
||||
printk(KERN_INFO "PRIMFINISH in %s\n", __FUNCTION__); \
|
||||
if (outcount & 3) \
|
||||
printk(KERN_INFO " --- truncation\n"); \
|
||||
} \
|
||||
dev_priv->prim_num_dwords = num_dwords; \
|
||||
dev_priv->current_dma_ptr = dma_ptr; \
|
||||
prim_buf->num_dwords = num_dwords; \
|
||||
prim_buf->current_dma_ptr = dma_ptr; \
|
||||
} while(0)
|
||||
|
||||
#define PRIMADVANCE(dev_priv) do { \
|
||||
drm_mga_prim_buf_t *tmp_buf = \
|
||||
dev_priv->prim_bufs[dev_priv->current_prim_idx]; \
|
||||
if (MGA_VERBOSE) { \
|
||||
printk(KERN_INFO "PRIMADVANCE in %s\n", __FUNCTION__); \
|
||||
if (outcount & 3) \
|
||||
printk(KERN_INFO " --- truncation\n"); \
|
||||
} \
|
||||
tmp_buf->num_dwords = num_dwords; \
|
||||
tmp_buf->current_dma_ptr = dma_ptr; \
|
||||
} while (0)
|
||||
|
||||
#define PRIMUPDATE(dev_priv) do { \
|
||||
drm_mga_prim_buf_t *tmp_buf = \
|
||||
dev_priv->prim_bufs[dev_priv->current_prim_idx]; \
|
||||
tmp_buf->sec_used++; \
|
||||
} while (0)
|
||||
|
||||
#define PRIMOUTREG(reg, val) do { \
|
||||
tempIndex[outcount]=ADRINDEX(reg); \
|
||||
|
|
@ -153,9 +113,6 @@ typedef struct {
|
|||
} \
|
||||
}while (0)
|
||||
|
||||
|
||||
|
||||
|
||||
#define MGA_CLEAR_CMD (DC_opcod_trap | DC_arzero_enable | \
|
||||
DC_sgnzero_enable | DC_shftzero_enable | \
|
||||
(0xC << DC_bop_SHIFT) | DC_clipdis_enable | \
|
||||
|
|
|
|||
|
|
@ -204,10 +204,6 @@ typedef struct
|
|||
int ctxOwner;
|
||||
mgaTexRegion texList[MGA_NR_TEX_REGIONS+1];
|
||||
int texAge;
|
||||
|
||||
|
||||
|
||||
|
||||
} drm_mga_sarea_t;
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,18 @@
|
|||
#define _MGA_DRV_H_
|
||||
#include "mga_drm_public.h"
|
||||
|
||||
typedef struct {
|
||||
unsigned int num_dwords;
|
||||
unsigned int max_dwords;
|
||||
u32 *current_dma_ptr;
|
||||
u32 *head;
|
||||
u32 phys_head;
|
||||
int sec_used;
|
||||
int idx;
|
||||
u32 in_use;
|
||||
atomic_t force_fire;
|
||||
} drm_mga_prim_buf_t;
|
||||
|
||||
typedef struct _drm_mga_private {
|
||||
int reserved_map_idx;
|
||||
int buffer_map_idx;
|
||||
|
|
@ -52,26 +64,26 @@ typedef struct _drm_mga_private {
|
|||
mgaWarpIndex WarpIndex[MGA_MAX_G400_PIPES];
|
||||
unsigned int WarpPipe;
|
||||
__volatile__ unsigned long softrap_age;
|
||||
atomic_t dispatch_lock;
|
||||
atomic_t pending_bufs;
|
||||
u32 dispatch_lock;
|
||||
atomic_t in_flush;
|
||||
atomic_t in_wait;
|
||||
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;
|
||||
u8 *ioremap;
|
||||
drm_mga_prim_buf_t **prim_bufs;
|
||||
drm_mga_prim_buf_t *next_prim;
|
||||
drm_mga_prim_buf_t *last_prim;
|
||||
drm_mga_prim_buf_t *current_prim;
|
||||
int current_prim_idx;
|
||||
struct pci_dev *device;
|
||||
|
||||
wait_queue_head_t flush_queue; /* Processes waiting until flush */
|
||||
wait_queue_head_t wait_queue; /* Processes waiting until interrupt */
|
||||
|
||||
/* Some validated register values:
|
||||
*/
|
||||
u32 mAccess;
|
||||
|
||||
} drm_mga_private_t;
|
||||
|
||||
/* mga_drv.c */
|
||||
|
|
@ -97,13 +109,17 @@ extern int mga_control(struct inode *inode, struct file *filp,
|
|||
extern int mga_lock(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
|
||||
/* mga_dma_init does init and release */
|
||||
extern int mga_dma_init(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
extern int mga_dma_cleanup(drm_device_t *dev);
|
||||
extern int mga_flush_ioctl(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
|
||||
/* mga_dma_init does init and release */
|
||||
extern unsigned int mga_create_sync_tag(drm_mga_private_t *dev_priv);
|
||||
extern drm_buf_t *mga_freelist_get(drm_device_t *dev);
|
||||
extern int mga_freelist_put(drm_device_t *dev, drm_buf_t *buf);
|
||||
extern int mga_advance_primary(drm_device_t *dev);
|
||||
|
||||
|
||||
/* mga_bufs.c */
|
||||
|
|
|
|||
|
|
@ -35,13 +35,13 @@
|
|||
#include "mga_drv.h"
|
||||
#include "mgareg_flags.h"
|
||||
#include "mga_dma.h"
|
||||
#include "mga_state.h"
|
||||
#include "drm.h"
|
||||
|
||||
void mgaEmitClipRect( drm_mga_private_t *dev_priv, xf86drmClipRectRec *box )
|
||||
static void mgaEmitClipRect( drm_mga_private_t *dev_priv, xf86drmClipRectRec *box )
|
||||
{
|
||||
PRIMLOCALS;
|
||||
|
||||
/* This takes a max of 10 dwords */
|
||||
PRIMGETPTR( dev_priv );
|
||||
|
||||
/* The G400 seems to have an issue with the second WARP not
|
||||
|
|
@ -52,8 +52,8 @@ void mgaEmitClipRect( drm_mga_private_t *dev_priv, xf86drmClipRectRec *box )
|
|||
if (dev_priv->chipset == MGA_CARD_TYPE_G400) {
|
||||
PRIMOUTREG( MGAREG_DMAPAD, 0 );
|
||||
PRIMOUTREG( MGAREG_DMAPAD, 0 );
|
||||
PRIMOUTREG( MGAREG_DWGSYNC, 0 );
|
||||
PRIMOUTREG( MGAREG_DWGSYNC, 0 );
|
||||
PRIMOUTREG( MGAREG_DWGSYNC, dev_priv->last_sync_tag - 1 );
|
||||
PRIMOUTREG( MGAREG_DWGSYNC, dev_priv->last_sync_tag - 1 );
|
||||
}
|
||||
|
||||
PRIMOUTREG( MGAREG_CXBNDRY, ((box->x2)<<16)|(box->x1) );
|
||||
|
|
@ -64,13 +64,13 @@ void mgaEmitClipRect( drm_mga_private_t *dev_priv, xf86drmClipRectRec *box )
|
|||
PRIMADVANCE( dev_priv );
|
||||
}
|
||||
|
||||
|
||||
static void mgaEmitContext(drm_mga_private_t *dev_priv,
|
||||
drm_mga_buf_priv_t *buf_priv)
|
||||
static void mgaEmitContext(drm_mga_private_t *dev_priv )
|
||||
{
|
||||
unsigned int *regs = buf_priv->ContextState;
|
||||
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
unsigned int *regs = sarea_priv->ContextState;
|
||||
PRIMLOCALS;
|
||||
|
||||
/* This takes a max of 15 dwords */
|
||||
PRIMGETPTR( dev_priv );
|
||||
|
||||
PRIMOUTREG( MGAREG_DSTORG, regs[MGA_CTXREG_DSTORG] );
|
||||
|
|
@ -81,9 +81,7 @@ static void mgaEmitContext(drm_mga_private_t *dev_priv,
|
|||
PRIMOUTREG( MGAREG_ALPHACTRL, regs[MGA_CTXREG_ALPHACTRL] );
|
||||
PRIMOUTREG( MGAREG_FOGCOL, regs[MGA_CTXREG_FOGCOLOR] );
|
||||
PRIMOUTREG( MGAREG_WFLAG, regs[MGA_CTXREG_WFLAG] );
|
||||
|
||||
PRIMOUTREG( MGAREG_ZORG, dev_priv->depthOffset ); /* invarient */
|
||||
/* PRIMOUTREG( MGAREG_DMAPAD, 0 ); */
|
||||
|
||||
if (dev_priv->chipset == MGA_CARD_TYPE_G400) {
|
||||
PRIMOUTREG( MGAREG_WFLAG1, regs[MGA_CTXREG_WFLAG] );
|
||||
|
|
@ -92,16 +90,18 @@ static void mgaEmitContext(drm_mga_private_t *dev_priv,
|
|||
PRIMOUTREG( MGAREG_DMAPAD, 0 );
|
||||
}
|
||||
|
||||
PRIMADVANCE( dev_priv ); /* padded */
|
||||
PRIMADVANCE( dev_priv );
|
||||
}
|
||||
|
||||
static void mgaG200EmitTex( drm_mga_private_t *dev_priv,
|
||||
drm_mga_buf_priv_t *buf_priv )
|
||||
static void mgaG200EmitTex( drm_mga_private_t *dev_priv )
|
||||
{
|
||||
unsigned int *regs = buf_priv->TexState[0];
|
||||
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
unsigned int *regs = sarea_priv->TexState[0];
|
||||
PRIMLOCALS;
|
||||
|
||||
PRIMGETPTR( dev_priv );
|
||||
|
||||
/* This takes 20 dwords */
|
||||
|
||||
PRIMOUTREG(MGAREG_TEXCTL2, regs[MGA_TEXREG_CTL2] );
|
||||
PRIMOUTREG(MGAREG_TEXCTL, regs[MGA_TEXREG_CTL] );
|
||||
|
|
@ -126,14 +126,16 @@ static void mgaG200EmitTex( drm_mga_private_t *dev_priv,
|
|||
PRIMADVANCE( dev_priv );
|
||||
}
|
||||
|
||||
static void mgaG400EmitTex0( drm_mga_private_t *dev_priv,
|
||||
drm_mga_buf_priv_t *buf_priv )
|
||||
static void mgaG400EmitTex0( drm_mga_private_t *dev_priv )
|
||||
{
|
||||
unsigned int *regs = buf_priv->TexState[0];
|
||||
int multitex = buf_priv->WarpPipe & MGA_T2;
|
||||
|
||||
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
unsigned int *regs = sarea_priv->TexState[0];
|
||||
int multitex = sarea_priv->WarpPipe & MGA_T2;
|
||||
PRIMLOCALS;
|
||||
|
||||
PRIMGETPTR( dev_priv );
|
||||
|
||||
/* This takes a max of 30 dwords */
|
||||
|
||||
PRIMOUTREG(MGAREG_TEXCTL2, regs[MGA_TEXREG_CTL2] );
|
||||
PRIMOUTREG(MGAREG_TEXCTL, regs[MGA_TEXREG_CTL] );
|
||||
|
|
@ -167,21 +169,20 @@ static void mgaG400EmitTex0( drm_mga_private_t *dev_priv,
|
|||
PRIMOUTREG( MGAREG_TEXTRANS, 0xffff );
|
||||
PRIMOUTREG( MGAREG_TEXTRANSHIGH, 0xffff );
|
||||
|
||||
|
||||
PRIMADVANCE( dev_priv );
|
||||
}
|
||||
|
||||
#define TMC_map1_enable 0x80000000
|
||||
|
||||
|
||||
static void mgaG400EmitTex1( drm_mga_private_t *dev_priv,
|
||||
drm_mga_buf_priv_t *buf_priv )
|
||||
static void mgaG400EmitTex1( drm_mga_private_t *dev_priv )
|
||||
{
|
||||
unsigned int *regs = buf_priv->TexState[1];
|
||||
|
||||
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
unsigned int *regs = sarea_priv->TexState[1];
|
||||
PRIMLOCALS;
|
||||
|
||||
PRIMGETPTR(dev_priv);
|
||||
|
||||
/* This takes 25 dwords */
|
||||
PRIMOUTREG(MGAREG_TEXCTL2, regs[MGA_TEXREG_CTL2] | TMC_map1_enable);
|
||||
PRIMOUTREG(MGAREG_TEXCTL, regs[MGA_TEXREG_CTL] );
|
||||
PRIMOUTREG(MGAREG_TEXFILTER, regs[MGA_TEXREG_FILTER] );
|
||||
|
|
@ -207,19 +208,19 @@ static void mgaG400EmitTex1( drm_mga_private_t *dev_priv,
|
|||
PRIMOUTREG( MGAREG_TEXTRANSHIGH, 0xffff );
|
||||
PRIMOUTREG(MGAREG_TEXCTL2, regs[MGA_TEXREG_CTL2] );
|
||||
|
||||
PRIMADVANCE( dev_priv ); /* padded */
|
||||
PRIMADVANCE( dev_priv );
|
||||
}
|
||||
|
||||
|
||||
static void mgaG400EmitPipe(drm_mga_private_t *dev_priv,
|
||||
drm_mga_buf_priv_t *buf_priv)
|
||||
static void mgaG400EmitPipe(drm_mga_private_t *dev_priv )
|
||||
{
|
||||
unsigned int pipe = buf_priv->WarpPipe;
|
||||
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
unsigned int pipe = sarea_priv->WarpPipe;
|
||||
float fParam = 12800.0f;
|
||||
PRIMLOCALS;
|
||||
|
||||
PRIMGETPTR(dev_priv);
|
||||
|
||||
/* This takes 25 dwords */
|
||||
|
||||
/* Establish vertex size.
|
||||
*/
|
||||
|
|
@ -259,13 +260,15 @@ static void mgaG400EmitPipe(drm_mga_private_t *dev_priv,
|
|||
PRIMADVANCE(dev_priv);
|
||||
}
|
||||
|
||||
static void mgaG200EmitPipe( drm_mga_private_t *dev_priv,
|
||||
drm_mga_buf_priv_t *buf_priv )
|
||||
static void mgaG200EmitPipe( drm_mga_private_t *dev_priv )
|
||||
{
|
||||
unsigned int pipe = buf_priv->WarpPipe;
|
||||
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
unsigned int pipe = sarea_priv->WarpPipe;
|
||||
PRIMLOCALS;
|
||||
|
||||
PRIMGETPTR(dev_priv);
|
||||
|
||||
/* This takes 15 dwords */
|
||||
|
||||
PRIMOUTREG(MGAREG_WIADDR, WIA_wmode_suspend);
|
||||
PRIMOUTREG(MGAREG_WVRTXSZ, 7);
|
||||
|
|
@ -287,60 +290,94 @@ static void mgaG200EmitPipe( drm_mga_private_t *dev_priv,
|
|||
PRIMADVANCE(dev_priv);
|
||||
}
|
||||
|
||||
void mgaEmitState( drm_mga_private_t *dev_priv, drm_mga_buf_priv_t *buf_priv )
|
||||
static void mgaEmitState( drm_mga_private_t *dev_priv )
|
||||
{
|
||||
unsigned int dirty = buf_priv->dirty;
|
||||
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
unsigned int dirty = sarea_priv->dirty;
|
||||
|
||||
if (dev_priv->chipset == MGA_CARD_TYPE_G400) {
|
||||
int multitex = buf_priv->WarpPipe & MGA_T2;
|
||||
int multitex = sarea_priv->WarpPipe & MGA_T2;
|
||||
|
||||
/* printk("BUF PIPE: %x LOADED PIPE: %x\n", */
|
||||
/* buf_priv->WarpPipe, dev_priv->WarpPipe); */
|
||||
/* DRM_DEBUG("BUF PIPE: %x LOADED PIPE: %x\n", */
|
||||
/* sarea_priv->WarpPipe, dev_priv->WarpPipe); */
|
||||
|
||||
if (buf_priv->WarpPipe != dev_priv->WarpPipe) {
|
||||
mgaG400EmitPipe( dev_priv, buf_priv );
|
||||
dev_priv->WarpPipe = buf_priv->WarpPipe;
|
||||
if (sarea_priv->WarpPipe != dev_priv->WarpPipe) {
|
||||
mgaG400EmitPipe( dev_priv );
|
||||
dev_priv->WarpPipe = sarea_priv->WarpPipe;
|
||||
}
|
||||
|
||||
if (dirty & MGA_UPLOAD_CTX)
|
||||
mgaEmitContext( dev_priv, buf_priv );
|
||||
mgaEmitContext( dev_priv );
|
||||
|
||||
if (dirty & MGA_UPLOAD_TEX0)
|
||||
mgaG400EmitTex0( dev_priv, buf_priv );
|
||||
mgaG400EmitTex0( dev_priv );
|
||||
|
||||
if ((dirty & MGA_UPLOAD_TEX1) && multitex)
|
||||
mgaG400EmitTex1( dev_priv, buf_priv );
|
||||
mgaG400EmitTex1( dev_priv );
|
||||
} else {
|
||||
if (buf_priv->WarpPipe != dev_priv->WarpPipe) {
|
||||
mgaG200EmitPipe( dev_priv, buf_priv );
|
||||
dev_priv->WarpPipe = buf_priv->WarpPipe;
|
||||
if (sarea_priv->WarpPipe != dev_priv->WarpPipe) {
|
||||
mgaG200EmitPipe( dev_priv );
|
||||
dev_priv->WarpPipe = sarea_priv->WarpPipe;
|
||||
}
|
||||
|
||||
if (dirty & MGA_UPLOAD_CTX)
|
||||
mgaEmitContext( dev_priv, buf_priv );
|
||||
mgaEmitContext( dev_priv );
|
||||
|
||||
if (dirty & MGA_UPLOAD_TEX0)
|
||||
mgaG200EmitTex( dev_priv, buf_priv );
|
||||
}
|
||||
mgaG200EmitTex( dev_priv );
|
||||
}
|
||||
|
||||
sarea_priv->dirty = 0;
|
||||
}
|
||||
|
||||
/* WARNING if you change any of the state functions
|
||||
* verify these numbers */
|
||||
|
||||
static int mgaCalcState( drm_mga_private_t *dev_priv )
|
||||
{
|
||||
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
unsigned int dirty = sarea_priv->dirty;
|
||||
int size = 0;
|
||||
|
||||
if (dev_priv->chipset == MGA_CARD_TYPE_G400) {
|
||||
int multitex = sarea_priv->WarpPipe & MGA_T2;
|
||||
|
||||
if (sarea_priv->WarpPipe != dev_priv->WarpPipe) {
|
||||
size += 25;
|
||||
}
|
||||
if (dirty & MGA_UPLOAD_CTX) {
|
||||
size += 15;
|
||||
}
|
||||
if (dirty & MGA_UPLOAD_TEX0) {
|
||||
size += 30;
|
||||
}
|
||||
if ((dirty & MGA_UPLOAD_TEX1) && multitex) {
|
||||
size += 25;
|
||||
}
|
||||
} else {
|
||||
if (sarea_priv->WarpPipe != dev_priv->WarpPipe) {
|
||||
size += 15;
|
||||
}
|
||||
if (dirty & MGA_UPLOAD_CTX) {
|
||||
size += 15;
|
||||
}
|
||||
if (dirty & MGA_UPLOAD_TEX0) {
|
||||
size += 20;
|
||||
}
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/* Disallow all write destinations except the front and backbuffer.
|
||||
*/
|
||||
static int mgaCopyContext(drm_mga_private_t *dev_priv,
|
||||
drm_mga_buf_priv_t *buf_priv)
|
||||
static int mgaVerifyContext(drm_mga_private_t *dev_priv )
|
||||
{
|
||||
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
unsigned int *regs = buf_priv->ContextState;
|
||||
|
||||
memcpy(regs,
|
||||
sarea_priv->ContextState,
|
||||
sizeof(buf_priv->ContextState));
|
||||
unsigned int *regs = sarea_priv->ContextState;
|
||||
|
||||
if (regs[MGA_CTXREG_DSTORG] != dev_priv->frontOffset &&
|
||||
regs[MGA_CTXREG_DSTORG] != dev_priv->backOffset) {
|
||||
printk("BAD DSTORG: %x (front %x, back %x)\n\n",
|
||||
DRM_DEBUG("BAD DSTORG: %x (front %x, back %x)\n\n",
|
||||
regs[MGA_CTXREG_DSTORG], dev_priv->frontOffset,
|
||||
dev_priv->backOffset);
|
||||
regs[MGA_CTXREG_DSTORG] = 0;
|
||||
|
|
@ -350,79 +387,531 @@ static int mgaCopyContext(drm_mga_private_t *dev_priv,
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Disallow texture reads from PCI space.
|
||||
*/
|
||||
static int mgaCopyTex(drm_mga_private_t *dev_priv,
|
||||
drm_mga_buf_priv_t *buf_priv,
|
||||
static int mgaVerifyTex(drm_mga_private_t *dev_priv,
|
||||
int unit)
|
||||
{
|
||||
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
|
||||
memcpy(buf_priv->TexState[unit], sarea_priv->TexState[unit],
|
||||
sizeof(buf_priv->TexState[0]));
|
||||
|
||||
if ((buf_priv->TexState[unit][MGA_TEXREG_ORG] & 0x3) == 0x1) {
|
||||
printk("BAD TEXREG_ORG: %x, unit %d\n",
|
||||
if ((sarea_priv->TexState[unit][MGA_TEXREG_ORG] & 0x3) == 0x1) {
|
||||
DRM_DEBUG("BAD TEXREG_ORG: %x, unit %d\n",
|
||||
sarea_priv->TexState[unit][MGA_TEXREG_ORG],
|
||||
unit);
|
||||
buf_priv->TexState[unit][MGA_TEXREG_ORG] = 0;
|
||||
sarea_priv->TexState[unit][MGA_TEXREG_ORG] = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int mgaCopyAndVerifyState( drm_mga_private_t *dev_priv,
|
||||
drm_mga_buf_priv_t *buf_priv,
|
||||
unsigned int interested )
|
||||
static int mgaVerifyState( drm_mga_private_t *dev_priv )
|
||||
{
|
||||
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
unsigned int dirty = interested & sarea_priv->dirty;
|
||||
unsigned int dirty = sarea_priv->dirty;
|
||||
int rv = 0;
|
||||
|
||||
buf_priv->dirty = dirty;
|
||||
sarea_priv->dirty &= ~interested;
|
||||
|
||||
buf_priv->WarpPipe = sarea_priv->WarpPipe;
|
||||
|
||||
/* if (interested & MGA_UPLOAD_CLIPRECTS) */
|
||||
{
|
||||
buf_priv->nbox = sarea_priv->nbox;
|
||||
|
||||
if (buf_priv->nbox >= MGA_NR_SAREA_CLIPRECTS)
|
||||
buf_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
|
||||
|
||||
if (buf_priv->nbox)
|
||||
memcpy( buf_priv->boxes,
|
||||
sarea_priv->boxes,
|
||||
buf_priv->nbox * sizeof(xf86drmClipRectRec));
|
||||
}
|
||||
if (sarea_priv->nbox >= MGA_NR_SAREA_CLIPRECTS)
|
||||
sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
|
||||
|
||||
if (dirty & MGA_UPLOAD_CTX)
|
||||
rv |= mgaCopyContext( dev_priv, buf_priv );
|
||||
rv |= mgaVerifyContext( dev_priv );
|
||||
|
||||
if (dirty & MGA_UPLOAD_TEX0)
|
||||
rv |= mgaCopyTex( dev_priv, buf_priv, 0 );
|
||||
rv |= mgaVerifyTex( dev_priv, 0 );
|
||||
|
||||
if (dev_priv->chipset == MGA_CARD_TYPE_G400)
|
||||
{
|
||||
if (dirty & MGA_UPLOAD_TEX1)
|
||||
rv |= mgaCopyTex( dev_priv, buf_priv, 1 );
|
||||
rv |= mgaVerifyTex( dev_priv, 1 );
|
||||
|
||||
if (dirty & MGA_UPLOAD_PIPE)
|
||||
rv |= (buf_priv->WarpPipe > MGA_MAX_G400_PIPES);
|
||||
rv |= (sarea_priv->WarpPipe > MGA_MAX_G400_PIPES);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dirty & MGA_UPLOAD_PIPE)
|
||||
rv |= (buf_priv->WarpPipe > MGA_MAX_G200_PIPES);
|
||||
rv |= (sarea_priv->WarpPipe > MGA_MAX_G200_PIPES);
|
||||
}
|
||||
|
||||
|
||||
|
||||
return rv == 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* This is very broken */
|
||||
|
||||
static void mga_dma_dispatch_tex_blit(drm_device_t *dev, drm_buf_t *buf, u16 x1,
|
||||
u16 x2, u16 y1, u16 y2, unsigned int destOrg,
|
||||
unsigned int mAccess, unsigned int pitch)
|
||||
{
|
||||
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;
|
||||
int width, height;
|
||||
int texperdword = 0;
|
||||
PRIMLOCALS;
|
||||
|
||||
switch((maccess & 0x00000003)) {
|
||||
case 0:
|
||||
texperdword = 4;
|
||||
break;
|
||||
case 1:
|
||||
texperdword = 2;
|
||||
break;
|
||||
case 2:
|
||||
texperdword = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
length = (y2 - y1) * (x2 - x1) / texperdword;
|
||||
|
||||
x2 = (x2 + (texperdword - 1)) & ~(texperdword - 1);
|
||||
x1 = (x1 + (texperdword - 1)) & ~(texperdword - 1);
|
||||
width = x2 - x1;
|
||||
height = y2 - y1;
|
||||
|
||||
PRIMRESET(dev_priv);
|
||||
PRIMGETPTR(dev_priv);
|
||||
PRIMOUTREG(MGAREG_DSTORG, dstorg);
|
||||
PRIMOUTREG(MGAREG_MACCESS, maccess);
|
||||
PRIMOUTREG(MGAREG_PITCH, pitch);
|
||||
PRIMOUTREG(MGAREG_YDSTLEN, (y1 << 16) | height);
|
||||
|
||||
PRIMOUTREG(MGAREG_FXBNDRY, ((x1+width-1) << 16) | x1);
|
||||
PRIMOUTREG(MGAREG_AR0, width * height - 1);
|
||||
PRIMOUTREG(MGAREG_AR3, 0 );
|
||||
PRIMOUTREG(MGAREG_DWGCTL+MGAREG_MGA_EXEC, MGA_ILOAD_CMD);
|
||||
|
||||
PRIMOUTREG(MGAREG_DMAPAD, 0);
|
||||
PRIMOUTREG(MGAREG_DMAPAD, 0);
|
||||
PRIMOUTREG(MGAREG_SRCORG, ((__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_AR0, 0 );
|
||||
|
||||
PRIMOUTREG(MGAREG_AR3, 0 );
|
||||
PRIMOUTREG(MGAREG_DMAPAD, 0);
|
||||
PRIMOUTREG(MGAREG_DMAPAD, 0);
|
||||
PRIMOUTREG(MGAREG_SOFTRAP, 0);
|
||||
PRIMADVANCE(dev_priv);
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline void mga_dma_dispatch_vertex(drm_device_t *dev,
|
||||
drm_buf_t *buf, int real_idx,
|
||||
int idx)
|
||||
{
|
||||
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 use_agp = PDEA_pagpxfer_enable;
|
||||
int i = 0;
|
||||
PRIMLOCALS;
|
||||
int primary_needed;
|
||||
|
||||
DRM_DEBUG("dispatch vertex %d addr 0x%lx, length 0x%x nbox %d dirty %x\n",
|
||||
buf->idx, address, length, sarea_priv->nbox, sarea_priv->dirty);
|
||||
|
||||
primary_needed = mgaCalcState( dev_priv );
|
||||
/* Primary needed is in dwords */
|
||||
if (sarea_priv->nbox == 0) {
|
||||
primary_needed += 5;
|
||||
} else {
|
||||
primary_needed += (5 * sarea_priv->nbox);
|
||||
primary_needed += (10 * sarea_priv->nbox);
|
||||
}
|
||||
primary_needed += 5; /* For the dwgsync */
|
||||
PRIM_OVERFLOW(dev, dev_priv, primary_needed);
|
||||
dev_priv->last_sync_tag = mga_create_sync_tag(dev_priv);
|
||||
if(real_idx == idx) {
|
||||
buf_priv->age = dev_priv->last_sync_tag;
|
||||
}
|
||||
mgaEmitState( dev_priv );
|
||||
do {
|
||||
if (i < sarea_priv->nbox) {
|
||||
DRM_DEBUG("idx %d Emit box %d/%d:"
|
||||
"%d,%d - %d,%d\n",
|
||||
buf->idx,
|
||||
i, sarea_priv->nbox,
|
||||
sarea_priv->boxes[i].x1,
|
||||
sarea_priv->boxes[i].y1,
|
||||
sarea_priv->boxes[i].x2,
|
||||
sarea_priv->boxes[i].y2);
|
||||
|
||||
mgaEmitClipRect( dev_priv,
|
||||
&sarea_priv->boxes[i] );
|
||||
}
|
||||
|
||||
PRIMGETPTR(dev_priv);
|
||||
PRIMOUTREG( MGAREG_DMAPAD, 0);
|
||||
PRIMOUTREG( MGAREG_DMAPAD, 0);
|
||||
PRIMOUTREG( MGAREG_SECADDRESS,
|
||||
((__u32)address) | TT_VERTEX);
|
||||
PRIMOUTREG( MGAREG_SECEND,
|
||||
(((__u32)(address + length)) |
|
||||
use_agp));
|
||||
PRIMADVANCE( dev_priv );
|
||||
} while (++i < sarea_priv->nbox);
|
||||
|
||||
PRIMGETPTR( dev_priv );
|
||||
PRIMOUTREG(MGAREG_DMAPAD, 0);
|
||||
PRIMOUTREG(MGAREG_DMAPAD, 0);
|
||||
PRIMOUTREG(MGAREG_DMAPAD, 0);
|
||||
PRIMOUTREG(MGAREG_DWGSYNC, dev_priv->last_sync_tag);
|
||||
PRIMADVANCE( dev_priv );
|
||||
}
|
||||
|
||||
/* Not currently used
|
||||
*/
|
||||
static inline void mga_dma_dispatch_general(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;
|
||||
unsigned long address = (unsigned long)buf->bus_address;
|
||||
int length = buf->used;
|
||||
int use_agp = PDEA_pagpxfer_enable;
|
||||
PRIMLOCALS;
|
||||
|
||||
PRIM_OVERFLOW(dev, dev_priv, 10);
|
||||
PRIMGETPTR(dev_priv);
|
||||
|
||||
dev_priv->last_sync_tag = mga_create_sync_tag(dev_priv);
|
||||
buf_priv->age = dev_priv->last_sync_tag;
|
||||
|
||||
PRIMOUTREG( MGAREG_DMAPAD, 0);
|
||||
PRIMOUTREG( MGAREG_DMAPAD, 0);
|
||||
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);
|
||||
PRIMADVANCE(dev_priv);
|
||||
}
|
||||
|
||||
static inline void mga_dma_dispatch_clear( drm_device_t *dev, int flags,
|
||||
unsigned int clear_color,
|
||||
unsigned int clear_zval )
|
||||
{
|
||||
drm_mga_private_t *dev_priv = dev->dev_private;
|
||||
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
int nbox = sarea_priv->nbox;
|
||||
xf86drmClipRectRec *pbox = sarea_priv->boxes;
|
||||
unsigned int cmd;
|
||||
int i;
|
||||
int primary_needed;
|
||||
PRIMLOCALS;
|
||||
|
||||
if ( dev_priv->sgram )
|
||||
cmd = MGA_CLEAR_CMD | DC_atype_blk;
|
||||
else
|
||||
cmd = MGA_CLEAR_CMD | DC_atype_rstr;
|
||||
|
||||
primary_needed = nbox * 35;
|
||||
if(primary_needed == 0) primary_needed = 35;
|
||||
PRIM_OVERFLOW(dev, dev_priv, primary_needed);
|
||||
PRIMGETPTR( dev_priv );
|
||||
dev_priv->last_sync_tag = mga_create_sync_tag(dev_priv);
|
||||
|
||||
for (i = 0 ; i < nbox ; i++) {
|
||||
unsigned int height = pbox[i].y2 - pbox[i].y1;
|
||||
|
||||
DRM_DEBUG("dispatch clear %d,%d-%d,%d flags %x!\n",
|
||||
pbox[i].x1, pbox[i].y1, pbox[i].x2,
|
||||
pbox[i].y2, flags);
|
||||
|
||||
if ( flags & MGA_CLEAR_FRONT ) {
|
||||
DRM_DEBUG("clear front\n");
|
||||
PRIMOUTREG( MGAREG_DMAPAD, 0);
|
||||
PRIMOUTREG( MGAREG_DMAPAD, 0);
|
||||
PRIMOUTREG(MGAREG_YDSTLEN, (pbox[i].y1<<16)|height);
|
||||
PRIMOUTREG(MGAREG_FXBNDRY, (pbox[i].x2<<16)|pbox[i].x1);
|
||||
|
||||
PRIMOUTREG( MGAREG_DMAPAD, 0);
|
||||
PRIMOUTREG(MGAREG_FCOL, clear_color);
|
||||
PRIMOUTREG(MGAREG_DSTORG, dev_priv->frontOffset);
|
||||
PRIMOUTREG(MGAREG_DWGCTL+MGAREG_MGA_EXEC, cmd );
|
||||
}
|
||||
|
||||
if ( flags & MGA_CLEAR_BACK ) {
|
||||
DRM_DEBUG("clear back\n");
|
||||
PRIMOUTREG( MGAREG_DMAPAD, 0);
|
||||
PRIMOUTREG( MGAREG_DMAPAD, 0);
|
||||
PRIMOUTREG(MGAREG_YDSTLEN, (pbox[i].y1<<16)|height);
|
||||
PRIMOUTREG(MGAREG_FXBNDRY, (pbox[i].x2<<16)|pbox[i].x1);
|
||||
|
||||
PRIMOUTREG( MGAREG_DMAPAD, 0);
|
||||
PRIMOUTREG(MGAREG_FCOL, clear_color);
|
||||
PRIMOUTREG(MGAREG_DSTORG, dev_priv->backOffset);
|
||||
PRIMOUTREG(MGAREG_DWGCTL+MGAREG_MGA_EXEC, cmd );
|
||||
}
|
||||
|
||||
if ( flags & MGA_CLEAR_DEPTH ) {
|
||||
DRM_DEBUG("clear depth\n");
|
||||
PRIMOUTREG( MGAREG_DMAPAD, 0);
|
||||
PRIMOUTREG( MGAREG_DMAPAD, 0);
|
||||
PRIMOUTREG(MGAREG_YDSTLEN, (pbox[i].y1<<16)|height);
|
||||
PRIMOUTREG(MGAREG_FXBNDRY, (pbox[i].x2<<16)|pbox[i].x1);
|
||||
|
||||
PRIMOUTREG( MGAREG_DMAPAD, 0);
|
||||
PRIMOUTREG(MGAREG_FCOL, clear_zval);
|
||||
PRIMOUTREG(MGAREG_DSTORG, dev_priv->depthOffset);
|
||||
PRIMOUTREG(MGAREG_DWGCTL+MGAREG_MGA_EXEC, cmd );
|
||||
}
|
||||
}
|
||||
|
||||
PRIMOUTREG( MGAREG_DMAPAD, 0);
|
||||
PRIMOUTREG( MGAREG_DMAPAD, 0);
|
||||
PRIMOUTREG( MGAREG_DMAPAD, 0);
|
||||
PRIMOUTREG( MGAREG_DWGSYNC, dev_priv->last_sync_tag);
|
||||
PRIMADVANCE(dev_priv);
|
||||
}
|
||||
|
||||
static inline void mga_dma_dispatch_swap( drm_device_t *dev )
|
||||
{
|
||||
drm_mga_private_t *dev_priv = dev->dev_private;
|
||||
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
int nbox = sarea_priv->nbox;
|
||||
xf86drmClipRectRec *pbox = sarea_priv->boxes;
|
||||
int i;
|
||||
int primary_needed;
|
||||
PRIMLOCALS;
|
||||
|
||||
primary_needed = nbox * 5;
|
||||
primary_needed += 15;
|
||||
PRIM_OVERFLOW(dev, dev_priv, primary_needed);
|
||||
PRIMGETPTR( dev_priv );
|
||||
|
||||
dev_priv->last_sync_tag = mga_create_sync_tag(dev_priv);
|
||||
|
||||
PRIMOUTREG(MGAREG_DSTORG, dev_priv->frontOffset);
|
||||
PRIMOUTREG(MGAREG_MACCESS, dev_priv->mAccess);
|
||||
PRIMOUTREG(MGAREG_SRCORG, dev_priv->backOffset);
|
||||
PRIMOUTREG(MGAREG_AR5, dev_priv->stride/2);
|
||||
|
||||
PRIMOUTREG( MGAREG_DMAPAD, 0);
|
||||
PRIMOUTREG( MGAREG_DMAPAD, 0);
|
||||
PRIMOUTREG( MGAREG_DMAPAD, 0);
|
||||
PRIMOUTREG(MGAREG_DWGCTL, MGA_COPY_CMD);
|
||||
|
||||
for (i = 0 ; i < nbox; i++) {
|
||||
unsigned int h = pbox[i].y2 - pbox[i].y1;
|
||||
unsigned int start = pbox[i].y1 * dev_priv->stride/2;
|
||||
|
||||
DRM_DEBUG("dispatch swap %d,%d-%d,%d!\n",
|
||||
pbox[i].x1, pbox[i].y1,
|
||||
pbox[i].x2, pbox[i].y2);
|
||||
|
||||
PRIMOUTREG(MGAREG_AR0, start + pbox[i].x2 - 1);
|
||||
PRIMOUTREG(MGAREG_AR3, start + pbox[i].x1);
|
||||
PRIMOUTREG(MGAREG_FXBNDRY, pbox[i].x1|((pbox[i].x2 - 1)<<16));
|
||||
PRIMOUTREG(MGAREG_YDSTLEN+MGAREG_MGA_EXEC, (pbox[i].y1<<16)|h);
|
||||
}
|
||||
|
||||
PRIMOUTREG( MGAREG_SRCORG, 0);
|
||||
PRIMOUTREG( MGAREG_DMAPAD, 0);
|
||||
PRIMOUTREG( MGAREG_DMAPAD, 0);
|
||||
PRIMOUTREG( MGAREG_DWGSYNC, dev_priv->last_sync_tag);
|
||||
PRIMADVANCE(dev_priv);
|
||||
}
|
||||
|
||||
int mga_clear_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_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;
|
||||
|
||||
drm_mga_clear_t clear;
|
||||
|
||||
copy_from_user_ret(&clear, (drm_mga_clear_t *)arg, sizeof(clear),
|
||||
-EFAULT);
|
||||
|
||||
if (sarea_priv->nbox >= MGA_NR_SAREA_CLIPRECTS)
|
||||
sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
|
||||
|
||||
/* Make sure we restore the 3D state next time.
|
||||
*/
|
||||
dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CTX;
|
||||
mga_dma_dispatch_clear( dev, clear.flags,
|
||||
clear.clear_color,
|
||||
clear.clear_depth );
|
||||
PRIMUPDATE(dev_priv);
|
||||
mga_dma_schedule(dev, 1);
|
||||
sarea_priv->last_dispatch = status[1];
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mga_swap_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_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;
|
||||
|
||||
if (sarea_priv->nbox >= MGA_NR_SAREA_CLIPRECTS)
|
||||
sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
|
||||
|
||||
/* Make sure we restore the 3D state next time.
|
||||
*/
|
||||
dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CTX;
|
||||
mga_dma_dispatch_swap( dev );
|
||||
PRIMUPDATE(dev_priv);
|
||||
atomic_set(&dev_priv->current_prim->force_fire, 1);
|
||||
mga_dma_schedule(dev, 1);
|
||||
sarea_priv->last_dispatch = status[1];
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This is very broken */
|
||||
int mga_iload(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_device_dma_t *dma = dev->dma;
|
||||
drm_buf_t *buf;
|
||||
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;
|
||||
drm_mga_iload_t iload;
|
||||
|
||||
copy_from_user_ret(&iload, (drm_mga_iload_t *)arg, sizeof(iload),
|
||||
-EFAULT);
|
||||
buf = dma->buflist[iload.idx];
|
||||
#if 0
|
||||
sarea_priv->dirty |= (MGA_UPLOAD_CTX | MGA_UPLOAD_2D);
|
||||
|
||||
DRM_DEBUG("buf->used : %d\n", buf->used);
|
||||
|
||||
mga_dma_dispatch_tex_blit(dev, buf, iload.x1, iload.x2, iload.y1, iload.y2,
|
||||
iload.destOrg, iload.mAccess, iload.pitch);
|
||||
|
||||
mga_dma_schedule(dev, 1);
|
||||
#endif
|
||||
mga_freelist_put(dev, buf);
|
||||
sarea_priv->last_dispatch = status[1];
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mga_vertex(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_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;
|
||||
drm_device_dma_t *dma = dev->dma;
|
||||
drm_buf_t *buf;
|
||||
drm_mga_buf_priv_t *buf_priv;
|
||||
drm_mga_vertex_t vertex;
|
||||
|
||||
copy_from_user_ret(&vertex, (drm_mga_vertex_t *)arg, sizeof(vertex),
|
||||
-EFAULT);
|
||||
|
||||
buf = dma->buflist[ vertex.real_idx ];
|
||||
buf_priv = buf->dev_private;
|
||||
|
||||
if (!mgaVerifyState(dev_priv)) {
|
||||
if(vertex.real_idx == vertex.idx)
|
||||
buf_priv->age = dev_priv->last_sync_tag;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
buf->used = vertex.real_used;
|
||||
if(vertex.discard) {
|
||||
buf_priv->age = dev_priv->last_sync_tag;
|
||||
} else {
|
||||
mga_dma_dispatch_vertex(dev, buf, vertex.real_idx,
|
||||
vertex.idx);
|
||||
}
|
||||
PRIMUPDATE(dev_priv);
|
||||
mga_dma_schedule(dev, 1);
|
||||
sarea_priv->last_dispatch = status[1];
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mga_dma_get_buffers(drm_device_t *dev, drm_dma_t *d)
|
||||
{
|
||||
int i;
|
||||
drm_buf_t *buf;
|
||||
|
||||
for (i = d->granted_count; i < d->request_count; i++) {
|
||||
buf = mga_freelist_get(dev);
|
||||
if (!buf) break;
|
||||
buf->pid = current->pid;
|
||||
copy_to_user_ret(&d->request_indices[i],
|
||||
&buf->idx,
|
||||
sizeof(buf->idx),
|
||||
-EFAULT);
|
||||
copy_to_user_ret(&d->request_sizes[i],
|
||||
&buf->total,
|
||||
sizeof(buf->total),
|
||||
-EFAULT);
|
||||
++d->granted_count;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mga_dma(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_device_dma_t *dma = dev->dma;
|
||||
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;
|
||||
int retcode = 0;
|
||||
drm_dma_t d;
|
||||
|
||||
copy_from_user_ret(&d, (drm_dma_t *)arg, sizeof(d), -EFAULT);
|
||||
DRM_DEBUG("%d %d: %d send, %d req\n",
|
||||
current->pid, d.context, d.send_count, d.request_count);
|
||||
|
||||
/* Please don't send us buffers.
|
||||
*/
|
||||
if (d.send_count != 0) {
|
||||
DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n",
|
||||
current->pid, d.send_count);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* We'll send you buffers.
|
||||
*/
|
||||
if (d.request_count < 0 || d.request_count > dma->buf_count) {
|
||||
DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n",
|
||||
current->pid, d.request_count, dma->buf_count);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
d.granted_count = 0;
|
||||
|
||||
if (d.request_count) {
|
||||
retcode = mga_dma_get_buffers(dev, &d);
|
||||
}
|
||||
|
||||
DRM_DEBUG("%d returning, granted = %d\n",
|
||||
current->pid, d.granted_count);
|
||||
copy_to_user_ret((drm_dma_t *)arg, &d, sizeof(d), -EFAULT);
|
||||
sarea_priv->last_dispatch = status[1];
|
||||
return retcode;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue