Added multiple outstanding dma requests for the mga

This commit is contained in:
Jeff Hartmann 2000-02-21 01:37:50 +00:00
parent 4f4242d4c8
commit 5ae11234d9
9 changed files with 1072 additions and 1374 deletions

View file

@ -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)) {

View file

@ -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

View file

@ -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)) {

View file

@ -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;

File diff suppressed because it is too large Load diff

View file

@ -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 | \

View file

@ -204,10 +204,6 @@ typedef struct
int ctxOwner;
mgaTexRegion texList[MGA_NR_TEX_REGIONS+1];
int texAge;
} drm_mga_sarea_t;

View file

@ -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 */

View file

@ -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;
}