diff options
author | Jeff Hartmann <jhartmann@valinux.com> | 2000-05-30 07:44:16 +0000 |
---|---|---|
committer | Jeff Hartmann <jhartmann@valinux.com> | 2000-05-30 07:44:16 +0000 |
commit | c37a7e26cd15a6a96587be2b17d22bdec4744a02 (patch) | |
tree | b955f1885fdc247e1e5bf7412450ad9d596f7733 /linux | |
parent | 7bb8be0aec1a301fc3cdf3c46ba6fadc6f9727b0 (diff) |
Merged trunk into mgadh-0-0-3-branchmgadh-0-0-3-branch
Diffstat (limited to 'linux')
-rw-r--r-- | linux/Makefile.kernel | 2 | ||||
-rw-r--r-- | linux/Makefile.linux | 12 | ||||
-rw-r--r-- | linux/agpsupport.c | 2 | ||||
-rw-r--r-- | linux/drm.h | 15 | ||||
-rw-r--r-- | linux/drmP.h | 14 | ||||
-rw-r--r-- | linux/fops.c | 5 | ||||
-rw-r--r-- | linux/i810_dma.c | 19 | ||||
-rw-r--r-- | linux/mga_drv.h | 68 | ||||
-rw-r--r-- | linux/mga_state.c | 1107 | ||||
-rw-r--r-- | linux/proc.c | 5 | ||||
-rw-r--r-- | linux/r128_bufs.c | 309 | ||||
-rw-r--r-- | linux/r128_context.c | 214 | ||||
-rw-r--r-- | linux/r128_dma.c | 908 | ||||
-rw-r--r-- | linux/r128_drm.h | 111 | ||||
-rw-r--r-- | linux/r128_drv.c | 737 | ||||
-rw-r--r-- | linux/r128_drv.h | 226 | ||||
-rw-r--r-- | linux/vm.c | 31 |
17 files changed, 3201 insertions, 584 deletions
diff --git a/linux/Makefile.kernel b/linux/Makefile.kernel index 2ea6c721..a169473a 100644 --- a/linux/Makefile.kernel +++ b/linux/Makefile.kernel @@ -49,3 +49,5 @@ i810.o: i810_drv.o i810_context.o $(L_TARGET) mga.o: mga_drv.o mga_context.o mga_dma.o mga_bufs.o $(L_TARGET) $(LD) $(LD_RFLAG) -r -o $@ mga_drv.o mga_bufs.o mga_dma.o mga_context.o mga_state.o -L. -ldrm +r128.o: r128_drv.o r128_context.o $(L_TARGET) + $(LD) $(LD_RFLAG) -r -o $@ r128_drv.o r128_context.o -L. -ldrm diff --git a/linux/Makefile.linux b/linux/Makefile.linux index 1a34ad0c..55a2f95d 100644 --- a/linux/Makefile.linux +++ b/linux/Makefile.linux @@ -1,8 +1,7 @@ # Makefile -- For the Direct Rendering Manager module (drm) # Created: Mon Jan 4 09:26:53 1999 by faith@precisioninsight.com -# Revised: Sun Feb 13 23:15:59 2000 by kevin@precisioninsight.com # -# Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. +# Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas. # All rights reserved. # # Permission is hereby granted, free of charge, to any person obtaining a @@ -33,7 +32,7 @@ # **** End of SMP/MODVERSIONS detection -MODS= gamma.o tdfx.o +MODS= gamma.o tdfx.o r128.o LIBS= libdrm.a PROGS= drmstat @@ -47,6 +46,9 @@ GAMMAHEADERS= gamma_drv.h $(DRMHEADERS) TDFXOBJS= tdfx_drv.o tdfx_context.o TDFXHEADERS= tdfx_drv.h $(DRMHEADERS) +R128OBJS= r128_drv.o r128_dma.o r128_bufs.o r128_context.o +R128HEADERS= r128_drv.h r128_drm.h $(DRMHEADERS) + PROGOBJS= drmstat.po xf86drm.po xf86drmHash.po xf86drmRandom.po sigio.po PROGHEADERS= xf86drm.h $(DRMHEADERS) @@ -153,6 +155,9 @@ gamma.o: $(GAMMAOBJS) $(LIBS) tdfx.o: $(TDFXOBJS) $(LIBS) $(LD) -r $^ -o $@ +r128.o: $(R128OBJS) $(LIBS) + $(LD) -r $^ -o $@ + ifeq ($(AGP),1) mga.o: $(MGAOBJS) $(LIBS) $(LD) -r $^ -o $@ @@ -182,6 +187,7 @@ ChangeLog: $(DRMOBJS): $(DRMHEADERS) $(GAMMAOBJS): $(GAMMAHEADERS) $(TDFXOBJS): $(TDFXHEADERS) +$(R128OBJS): $(R128HEADERS) ifeq ($(AGP),1) $(MGAOBJS): $(MGAHEADERS) $(I810OBJS): $(I810HEADERS) diff --git a/linux/agpsupport.c b/linux/agpsupport.c index c2da9ec7..14fb8b53 100644 --- a/linux/agpsupport.c +++ b/linux/agpsupport.c @@ -239,6 +239,8 @@ int drm_agp_bind(struct inode *inode, struct file *filp, unsigned int cmd, page = (request.offset + PAGE_SIZE - 1) / PAGE_SIZE; if ((retcode = drm_bind_agp(entry->memory, page))) return retcode; entry->bound = dev->agp->base + (page << PAGE_SHIFT); + DRM_DEBUG("base = 0x%lx entry->bound = 0x%lx\n", + dev->agp->base, entry->bound); return 0; } diff --git a/linux/drm.h b/linux/drm.h index 8418323c..74ef83f4 100644 --- a/linux/drm.h +++ b/linux/drm.h @@ -1,8 +1,7 @@ /* drm.h -- Header for Direct Rendering Manager -*- linux-c -*- * Created: Mon Jan 4 10:05:05 1999 by faith@precisioninsight.com - * Revised: Mon Feb 14 00:15:23 2000 by kevin@precisioninsight.com * - * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas. * All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a @@ -71,9 +70,10 @@ typedef struct drm_clip_rect { unsigned short y2; } drm_clip_rect_t; -/* Seperate include files for the i810/mga specific structures */ +/* Seperate include files for the i810/mga/r128 specific structures */ #include "mga_drm.h" #include "i810_drm.h" +#include "r128_drm.h" typedef struct drm_version { int version_major; /* Major version */ @@ -351,4 +351,13 @@ typedef struct drm_agp_info { #define DRM_IOCTL_I810_GETAGE DRM_IO ( 0x44) #define DRM_IOCTL_I810_GETBUF DRM_IOW( 0x45, drm_i810_dma_t) #define DRM_IOCTL_I810_SWAP DRM_IO ( 0x46) + +/* Rage 128 specific ioctls */ +#define DRM_IOCTL_R128_INIT DRM_IOW( 0x40, drm_r128_init_t) +#define DRM_IOCTL_R128_RESET DRM_IO( 0x41) +#define DRM_IOCTL_R128_FLUSH DRM_IO( 0x42) +#define DRM_IOCTL_R128_CCEIDL DRM_IO( 0x43) +#define DRM_IOCTL_R128_PACKET DRM_IOW( 0x44, drm_r128_packet_t) +#define DRM_IOCTL_R128_VERTEX DRM_IOW( 0x45, drm_r128_vertex_t) + #endif diff --git a/linux/drmP.h b/linux/drmP.h index f8e78eab..43670e28 100644 --- a/linux/drmP.h +++ b/linux/drmP.h @@ -1,8 +1,7 @@ /* drmP.h -- Private header for Direct Rendering Manager -*- linux-c -*- * Created: Mon Jan 4 10:05:05 1999 by faith@precisioninsight.com - * Revised: Sun Feb 13 23:34:30 2000 by kevin@precisioninsight.com * - * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas. * All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a @@ -228,8 +227,8 @@ typedef struct drm_magic_entry { } drm_magic_entry_t; typedef struct drm_magic_head { - struct drm_magic_entry *head; - struct drm_magic_entry *tail; + struct drm_magic_entry *head; + struct drm_magic_entry *tail; } drm_magic_head_t; typedef struct drm_vma_entry { @@ -262,16 +261,15 @@ typedef struct drm_buf { DRM_LIST_RECLAIM = 5 } list; /* Which list we're on */ - - void *dev_private; - int dev_priv_size; - #if DRM_DMA_HISTOGRAM cycles_t time_queued; /* Queued to kernel DMA queue */ cycles_t time_dispatched; /* Dispatched to hardware */ cycles_t time_completed; /* Completed by hardware */ cycles_t time_freed; /* Back on freelist */ #endif + + int dev_priv_size; /* Size of buffer private stoarge */ + void *dev_private; /* Per-buffer private storage */ } drm_buf_t; #if DRM_DMA_HISTOGRAM diff --git a/linux/fops.c b/linux/fops.c index 2a064e5d..1c1a3584 100644 --- a/linux/fops.c +++ b/linux/fops.c @@ -211,10 +211,11 @@ int drm_write_string(drm_device_t *dev, const char *s) send -= count; } -#if LINUX_VERSION_CODE < 0x020315 +#if LINUX_VERSION_CODE < 0x02020e || \ + ( LINUX_VERSION_CODE > 0x020300 && LINUX_VERSION_CODE < 0x020315 ) if (dev->buf_async) kill_fasync(dev->buf_async, SIGIO); #else - /* Parameter added in 2.3.21 */ + /* Parameter added in 2.2.14 and 2.3.21 */ if (dev->buf_async) kill_fasync(dev->buf_async, SIGIO, POLL_IN); #endif DRM_DEBUG("waking\n"); diff --git a/linux/i810_dma.c b/linux/i810_dma.c index 560e0783..f041f209 100644 --- a/linux/i810_dma.c +++ b/linux/i810_dma.c @@ -778,6 +778,9 @@ static void i810_dma_dispatch_vertex(drm_device_t *dev, } } + if (used > 4*1024) + used = 0; + if (sarea_priv->dirty) i810EmitState( dev ); @@ -791,16 +794,20 @@ static void i810_dma_dispatch_vertex(drm_device_t *dev, DRM_DEBUG( "used : %d\n", used); DRM_DEBUG( "start + used - 4 : %ld\n", start + used - 4); - if (used) { + if (buf_priv->currently_mapped == I810_BUF_MAPPED) { *(u32 *)buf_priv->virtual = (GFX_OP_PRIMITIVE | sarea_priv->vertex_prim | ((used/4)-2)); - + if (used & 4) { - *(u32 *)((u32)buf_priv->virtual + used) = 0; - used += 4; + *(u32 *)((u32)buf_priv->virtual + used) = 0; + used += 4; } + + i810_unmap_buffer(buf); + } + if (used) { do { if (i < nbox) { BEGIN_LP_RING(4); @@ -838,10 +845,6 @@ static void i810_dma_dispatch_vertex(drm_device_t *dev, OUT_RING( CMD_REPORT_HEAD ); OUT_RING( 0 ); ADVANCE_LP_RING(); - - if(buf_priv->currently_mapped == I810_BUF_MAPPED) { - i810_unmap_buffer(buf); - } } diff --git a/linux/mga_drv.h b/linux/mga_drv.h index 80d63c45..ee75a03e 100644 --- a/linux/mga_drv.h +++ b/linux/mga_drv.h @@ -371,28 +371,58 @@ drm_mga_prim_buf_t *tmp_buf = \ #define MGAREG_YTOP 0x1c98 #define MGAREG_ZORG 0x1c0c -#define DC_atype_rstr 0x10 -#define DC_atype_blk 0x40 #define PDEA_pagpxfer_enable 0x2 + #define WIA_wmode_suspend 0x0 #define WIA_wmode_start 0x3 #define WIA_wagp_agp 0x4 -#define DC_opcod_trap 0x4 -#define DC_arzero_enable 0x1000 -#define DC_sgnzero_enable 0x2000 -#define DC_shftzero_enable 0x4000 -#define DC_bop_SHIFT 16 -#define DC_clipdis_enable 0x80000000 -#define DC_solid_enable 0x800 -#define DC_transc_enable 0x40000000 + +#define DC_opcod_line_open 0x0 +#define DC_opcod_autoline_open 0x1 +#define DC_opcod_line_close 0x2 +#define DC_opcod_autoline_close 0x3 +#define DC_opcod_trap 0x4 +#define DC_opcod_texture_trap 0x6 #define DC_opcod_bitblt 0x8 -#define DC_atype_rpl 0x0 -#define DC_linear_xy 0x0 -#define DC_solid_disable 0x0 -#define DC_arzero_disable 0x0 -#define DC_bltmod_bfcol 0x4000000 -#define DC_pattern_disable 0x0 -#define DC_transc_disable 0x0 +#define DC_opcod_iload 0x9 +#define DC_atype_rpl 0x0 +#define DC_atype_rstr 0x10 +#define DC_atype_zi 0x30 +#define DC_atype_blk 0x40 +#define DC_atype_i 0x70 +#define DC_linear_xy 0x0 +#define DC_linear_linear 0x80 +#define DC_zmode_nozcmp 0x0 +#define DC_zmode_ze 0x200 +#define DC_zmode_zne 0x300 +#define DC_zmode_zlt 0x400 +#define DC_zmode_zlte 0x500 +#define DC_zmode_zgt 0x600 +#define DC_zmode_zgte 0x700 +#define DC_solid_disable 0x0 +#define DC_solid_enable 0x800 +#define DC_arzero_disable 0x0 +#define DC_arzero_enable 0x1000 +#define DC_sgnzero_disable 0x0 +#define DC_sgnzero_enable 0x2000 +#define DC_shftzero_disable 0x0 +#define DC_shftzero_enable 0x4000 +#define DC_bop_SHIFT 16 +#define DC_trans_SHIFT 20 +#define DC_bltmod_bmonolef 0x0 +#define DC_bltmod_bmonowf 0x8000000 +#define DC_bltmod_bplan 0x2000000 +#define DC_bltmod_bfcol 0x4000000 +#define DC_bltmod_bu32bgr 0x6000000 +#define DC_bltmod_bu32rgb 0xe000000 +#define DC_bltmod_bu24bgr 0x16000000 +#define DC_bltmod_bu24rgb 0x1e000000 +#define DC_pattern_disable 0x0 +#define DC_pattern_enable 0x20000000 +#define DC_transc_disable 0x0 +#define DC_transc_enable 0x40000000 +#define DC_clipdis_disable 0x0 +#define DC_clipdis_enable 0x80000000 #define SETADD_mode_vertlist 0x0 @@ -410,4 +440,8 @@ drm_mga_prim_buf_t *tmp_buf = \ DC_pattern_disable | DC_transc_disable | \ DC_clipdis_enable) \ +#define MGA_FLUSH_CMD (DC_opcod_texture_trap | (0xF << DC_trans_SHIFT) |\ + DC_arzero_enable | DC_sgnzero_enable | \ + DC_atype_i) + #endif diff --git a/linux/mga_state.c b/linux/mga_state.c index dc227769..5b2d44a1 100644 --- a/linux/mga_state.c +++ b/linux/mga_state.c @@ -29,316 +29,371 @@ * $XFree86$ * */ - + #define __NO_VERSION__ #include "drmP.h" #include "mga_drv.h" #include "drm.h" -static void mgaEmitClipRect( drm_mga_private_t *dev_priv, - drm_clip_rect_t *box ) +static void mgaEmitClipRect(drm_mga_private_t * dev_priv, + drm_clip_rect_t * box) { - drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; + drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; unsigned int *regs = sarea_priv->ContextState; PRIMLOCALS; DRM_DEBUG("%s\n", __FUNCTION__); - /* This takes 10 dwords */ - PRIMGETPTR( dev_priv ); - - /* Force reset of dwgctl (eliminates clip disable) */ - PRIMOUTREG( MGAREG_DMAPAD, 0 ); - PRIMOUTREG( MGAREG_DWGSYNC, 0 ); - PRIMOUTREG( MGAREG_DWGSYNC, 0 ); - PRIMOUTREG( MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL] ); - - PRIMOUTREG( MGAREG_DMAPAD, 0 ); - PRIMOUTREG( MGAREG_CXBNDRY, ((box->x2)<<16)|(box->x1) ); - PRIMOUTREG( MGAREG_YTOP, box->y1 * dev_priv->stride/2 ); - PRIMOUTREG( MGAREG_YBOT, box->y2 * dev_priv->stride/2 ); - - PRIMADVANCE( dev_priv ); + /* This takes 10 dwords */ + PRIMGETPTR(dev_priv); + + /* Force reset of dwgctl (eliminates clip disable) */ +#if 0 + PRIMOUTREG(MGAREG_DMAPAD, 0); + PRIMOUTREG(MGAREG_DWGSYNC, 0); + PRIMOUTREG(MGAREG_DWGSYNC, 0); + PRIMOUTREG(MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL]); +#else + PRIMOUTREG(MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL]); + PRIMOUTREG(MGAREG_LEN + MGAREG_MGA_EXEC, 0x80000000); + PRIMOUTREG(MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL]); + PRIMOUTREG(MGAREG_LEN + MGAREG_MGA_EXEC, 0x80000000); +#endif + + PRIMOUTREG(MGAREG_DMAPAD, 0); + PRIMOUTREG(MGAREG_CXBNDRY, ((box->x2) << 16) | (box->x1)); + PRIMOUTREG(MGAREG_YTOP, box->y1 * dev_priv->stride / 2); + PRIMOUTREG(MGAREG_YBOT, box->y2 * dev_priv->stride / 2); + + PRIMADVANCE(dev_priv); } -static void mgaEmitContext(drm_mga_private_t *dev_priv ) +static void mgaEmitContext(drm_mga_private_t * dev_priv) { - drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; + drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; unsigned int *regs = sarea_priv->ContextState; PRIMLOCALS; DRM_DEBUG("%s\n", __FUNCTION__); - - /* This takes a max of 15 dwords */ - PRIMGETPTR( dev_priv ); - - PRIMOUTREG( MGAREG_DSTORG, regs[MGA_CTXREG_DSTORG] ); - PRIMOUTREG( MGAREG_MACCESS, regs[MGA_CTXREG_MACCESS] ); - PRIMOUTREG( MGAREG_PLNWT, regs[MGA_CTXREG_PLNWT] ); - PRIMOUTREG( MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL] ); - - 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 */ - - if (dev_priv->chipset == MGA_CARD_TYPE_G400) { - PRIMOUTREG( MGAREG_WFLAG1, regs[MGA_CTXREG_WFLAG] ); - PRIMOUTREG( MGAREG_TDUALSTAGE0, regs[MGA_CTXREG_TDUAL0] ); - PRIMOUTREG( MGAREG_TDUALSTAGE1, regs[MGA_CTXREG_TDUAL1] ); - PRIMOUTREG( MGAREG_FCOL, regs[MGA_CTXREG_FCOL] ); + + /* This takes a max of 15 dwords */ + PRIMGETPTR(dev_priv); + + PRIMOUTREG(MGAREG_DSTORG, regs[MGA_CTXREG_DSTORG]); + PRIMOUTREG(MGAREG_MACCESS, regs[MGA_CTXREG_MACCESS]); + PRIMOUTREG(MGAREG_PLNWT, regs[MGA_CTXREG_PLNWT]); + PRIMOUTREG(MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL]); + + 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 */ + + if (dev_priv->chipset == MGA_CARD_TYPE_G400) { + PRIMOUTREG(MGAREG_WFLAG1, regs[MGA_CTXREG_WFLAG]); + PRIMOUTREG(MGAREG_TDUALSTAGE0, regs[MGA_CTXREG_TDUAL0]); + PRIMOUTREG(MGAREG_TDUALSTAGE1, regs[MGA_CTXREG_TDUAL1]); + PRIMOUTREG(MGAREG_FCOL, regs[MGA_CTXREG_FCOL]); } else { - PRIMOUTREG( MGAREG_FCOL, regs[MGA_CTXREG_FCOL] ); - PRIMOUTREG( MGAREG_DMAPAD, 0); - PRIMOUTREG( MGAREG_DMAPAD, 0); - PRIMOUTREG( MGAREG_DMAPAD, 0); + PRIMOUTREG(MGAREG_FCOL, regs[MGA_CTXREG_FCOL]); + PRIMOUTREG(MGAREG_DMAPAD, 0); + PRIMOUTREG(MGAREG_DMAPAD, 0); + PRIMOUTREG(MGAREG_DMAPAD, 0); } - - PRIMADVANCE( dev_priv ); + + PRIMADVANCE(dev_priv); } -static void mgaG200EmitTex( drm_mga_private_t *dev_priv ) +static void mgaG200EmitTex(drm_mga_private_t * dev_priv) { - drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; + drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; unsigned int *regs = sarea_priv->TexState[0]; PRIMLOCALS; DRM_DEBUG("%s\n", __FUNCTION__); - PRIMGETPTR( dev_priv ); - - /* This takes 20 dwords */ + PRIMGETPTR(dev_priv); - PRIMOUTREG(MGAREG_TEXCTL2, regs[MGA_TEXREG_CTL2] ); - PRIMOUTREG(MGAREG_TEXCTL, regs[MGA_TEXREG_CTL] ); - PRIMOUTREG(MGAREG_TEXFILTER, regs[MGA_TEXREG_FILTER] ); - PRIMOUTREG(MGAREG_TEXBORDERCOL, regs[MGA_TEXREG_BORDERCOL] ); + /* This takes 20 dwords */ - PRIMOUTREG(MGAREG_TEXORG, regs[MGA_TEXREG_ORG] ); - PRIMOUTREG(MGAREG_TEXORG1, regs[MGA_TEXREG_ORG1] ); - PRIMOUTREG(MGAREG_TEXORG2, regs[MGA_TEXREG_ORG2] ); - PRIMOUTREG(MGAREG_TEXORG3, regs[MGA_TEXREG_ORG3] ); + PRIMOUTREG(MGAREG_TEXCTL2, regs[MGA_TEXREG_CTL2]); + PRIMOUTREG(MGAREG_TEXCTL, regs[MGA_TEXREG_CTL]); + PRIMOUTREG(MGAREG_TEXFILTER, regs[MGA_TEXREG_FILTER]); + PRIMOUTREG(MGAREG_TEXBORDERCOL, regs[MGA_TEXREG_BORDERCOL]); - PRIMOUTREG(MGAREG_TEXORG4, regs[MGA_TEXREG_ORG4] ); - PRIMOUTREG(MGAREG_TEXWIDTH, regs[MGA_TEXREG_WIDTH] ); - PRIMOUTREG(MGAREG_TEXHEIGHT, regs[MGA_TEXREG_HEIGHT] ); - PRIMOUTREG(0x2d00 + 24*4, regs[MGA_TEXREG_WIDTH] ); + PRIMOUTREG(MGAREG_TEXORG, regs[MGA_TEXREG_ORG]); + PRIMOUTREG(MGAREG_TEXORG1, regs[MGA_TEXREG_ORG1]); + PRIMOUTREG(MGAREG_TEXORG2, regs[MGA_TEXREG_ORG2]); + PRIMOUTREG(MGAREG_TEXORG3, regs[MGA_TEXREG_ORG3]); - PRIMOUTREG(0x2d00 + 34*4, regs[MGA_TEXREG_HEIGHT] ); - PRIMOUTREG( MGAREG_TEXTRANS, 0xffff ); - PRIMOUTREG( MGAREG_TEXTRANSHIGH, 0xffff ); - PRIMOUTREG( MGAREG_DMAPAD, 0 ); + PRIMOUTREG(MGAREG_TEXORG4, regs[MGA_TEXREG_ORG4]); + PRIMOUTREG(MGAREG_TEXWIDTH, regs[MGA_TEXREG_WIDTH]); + PRIMOUTREG(MGAREG_TEXHEIGHT, regs[MGA_TEXREG_HEIGHT]); + PRIMOUTREG(0x2d00 + 24 * 4, regs[MGA_TEXREG_WIDTH]); - PRIMADVANCE( dev_priv ); + PRIMOUTREG(0x2d00 + 34 * 4, regs[MGA_TEXREG_HEIGHT]); + PRIMOUTREG(MGAREG_TEXTRANS, 0xffff); + PRIMOUTREG(MGAREG_TEXTRANSHIGH, 0xffff); + PRIMOUTREG(MGAREG_DMAPAD, 0); + + PRIMADVANCE(dev_priv); } -static void mgaG400EmitTex0( drm_mga_private_t *dev_priv ) +static void mgaG400EmitTex0(drm_mga_private_t * dev_priv) { - drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; + 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; DRM_DEBUG("%s\n", __FUNCTION__); - - PRIMGETPTR( dev_priv ); - - /* This takes a max of 30 dwords */ - - PRIMOUTREG(MGAREG_TEXCTL2, regs[MGA_TEXREG_CTL2] ); - PRIMOUTREG(MGAREG_TEXCTL, regs[MGA_TEXREG_CTL] ); - PRIMOUTREG(MGAREG_TEXFILTER, regs[MGA_TEXREG_FILTER] ); - PRIMOUTREG(MGAREG_TEXBORDERCOL, regs[MGA_TEXREG_BORDERCOL] ); - - PRIMOUTREG(MGAREG_TEXORG, regs[MGA_TEXREG_ORG] ); - PRIMOUTREG(MGAREG_TEXORG1, regs[MGA_TEXREG_ORG1] ); - PRIMOUTREG(MGAREG_TEXORG2, regs[MGA_TEXREG_ORG2] ); - PRIMOUTREG(MGAREG_TEXORG3, regs[MGA_TEXREG_ORG3] ); - - PRIMOUTREG(MGAREG_TEXORG4, regs[MGA_TEXREG_ORG4] ); - PRIMOUTREG(MGAREG_TEXWIDTH, regs[MGA_TEXREG_WIDTH] ); - PRIMOUTREG(MGAREG_TEXHEIGHT, regs[MGA_TEXREG_HEIGHT] ); - PRIMOUTREG(0x2d00 + 49*4, 0); - - PRIMOUTREG(0x2d00 + 57*4, 0); - PRIMOUTREG(0x2d00 + 53*4, 0); - PRIMOUTREG(0x2d00 + 61*4, 0); - PRIMOUTREG( MGAREG_DMAPAD, 0 ); + + PRIMGETPTR(dev_priv); + + /* This takes a max of 30 dwords */ + + PRIMOUTREG(MGAREG_TEXCTL2, regs[MGA_TEXREG_CTL2]); + PRIMOUTREG(MGAREG_TEXCTL, regs[MGA_TEXREG_CTL]); + PRIMOUTREG(MGAREG_TEXFILTER, regs[MGA_TEXREG_FILTER]); + PRIMOUTREG(MGAREG_TEXBORDERCOL, regs[MGA_TEXREG_BORDERCOL]); + + PRIMOUTREG(MGAREG_TEXORG, regs[MGA_TEXREG_ORG]); + PRIMOUTREG(MGAREG_TEXORG1, regs[MGA_TEXREG_ORG1]); + PRIMOUTREG(MGAREG_TEXORG2, regs[MGA_TEXREG_ORG2]); + PRIMOUTREG(MGAREG_TEXORG3, regs[MGA_TEXREG_ORG3]); + + PRIMOUTREG(MGAREG_TEXORG4, regs[MGA_TEXREG_ORG4]); + PRIMOUTREG(MGAREG_TEXWIDTH, regs[MGA_TEXREG_WIDTH]); + PRIMOUTREG(MGAREG_TEXHEIGHT, regs[MGA_TEXREG_HEIGHT]); + PRIMOUTREG(0x2d00 + 49 * 4, 0); + + PRIMOUTREG(0x2d00 + 57 * 4, 0); + PRIMOUTREG(0x2d00 + 53 * 4, 0); + PRIMOUTREG(0x2d00 + 61 * 4, 0); + PRIMOUTREG(MGAREG_DMAPAD, 0); if (!multitex) { - PRIMOUTREG(0x2d00 + 52*4, 0x40 ); - PRIMOUTREG(0x2d00 + 60*4, 0x40 ); - PRIMOUTREG( MGAREG_DMAPAD, 0 ); - PRIMOUTREG( MGAREG_DMAPAD, 0 ); - } - - PRIMOUTREG( 0x2d00 + 54*4, regs[MGA_TEXREG_WIDTH] | 0x40 ); - PRIMOUTREG( 0x2d00 + 62*4, regs[MGA_TEXREG_HEIGHT] | 0x40 ); - PRIMOUTREG( MGAREG_TEXTRANS, 0xffff ); - PRIMOUTREG( MGAREG_TEXTRANSHIGH, 0xffff ); - - PRIMADVANCE( dev_priv ); + PRIMOUTREG(0x2d00 + 52 * 4, 0x40); + PRIMOUTREG(0x2d00 + 60 * 4, 0x40); + PRIMOUTREG(MGAREG_DMAPAD, 0); + PRIMOUTREG(MGAREG_DMAPAD, 0); + } + + PRIMOUTREG(0x2d00 + 54 * 4, regs[MGA_TEXREG_WIDTH] | 0x40); + PRIMOUTREG(0x2d00 + 62 * 4, regs[MGA_TEXREG_HEIGHT] | 0x40); + PRIMOUTREG(MGAREG_TEXTRANS, 0xffff); + PRIMOUTREG(MGAREG_TEXTRANSHIGH, 0xffff); + + PRIMADVANCE(dev_priv); } -#define TMC_map1_enable 0x80000000 +#define TMC_map1_enable 0x80000000 -static void mgaG400EmitTex1( drm_mga_private_t *dev_priv ) +static void mgaG400EmitTex1(drm_mga_private_t * dev_priv) { - drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; + drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; unsigned int *regs = sarea_priv->TexState[1]; PRIMLOCALS; DRM_DEBUG("%s\n", __FUNCTION__); - + 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] ); - PRIMOUTREG(MGAREG_TEXBORDERCOL, regs[MGA_TEXREG_BORDERCOL] ); - - PRIMOUTREG(MGAREG_TEXORG, regs[MGA_TEXREG_ORG] ); - PRIMOUTREG(MGAREG_TEXORG1, regs[MGA_TEXREG_ORG1] ); - PRIMOUTREG(MGAREG_TEXORG2, regs[MGA_TEXREG_ORG2] ); - PRIMOUTREG(MGAREG_TEXORG3, regs[MGA_TEXREG_ORG3] ); - - PRIMOUTREG(MGAREG_TEXORG4, regs[MGA_TEXREG_ORG4] ); - PRIMOUTREG(MGAREG_TEXWIDTH, regs[MGA_TEXREG_WIDTH] ); - PRIMOUTREG(MGAREG_TEXHEIGHT, regs[MGA_TEXREG_HEIGHT] ); - PRIMOUTREG(0x2d00 + 49*4, 0); - - PRIMOUTREG(0x2d00 + 57*4, 0); - PRIMOUTREG(0x2d00 + 53*4, 0); - PRIMOUTREG(0x2d00 + 61*4, 0); - PRIMOUTREG(0x2d00 + 52*4, regs[MGA_TEXREG_WIDTH] | 0x40 ); - - PRIMOUTREG(0x2d00 + 60*4, regs[MGA_TEXREG_HEIGHT] | 0x40 ); - PRIMOUTREG( MGAREG_TEXTRANS, 0xffff ); - PRIMOUTREG( MGAREG_TEXTRANSHIGH, 0xffff ); - PRIMOUTREG(MGAREG_TEXCTL2, regs[MGA_TEXREG_CTL2] ); - - PRIMADVANCE( 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]); + PRIMOUTREG(MGAREG_TEXBORDERCOL, regs[MGA_TEXREG_BORDERCOL]); + + PRIMOUTREG(MGAREG_TEXORG, regs[MGA_TEXREG_ORG]); + PRIMOUTREG(MGAREG_TEXORG1, regs[MGA_TEXREG_ORG1]); + PRIMOUTREG(MGAREG_TEXORG2, regs[MGA_TEXREG_ORG2]); + PRIMOUTREG(MGAREG_TEXORG3, regs[MGA_TEXREG_ORG3]); + + PRIMOUTREG(MGAREG_TEXORG4, regs[MGA_TEXREG_ORG4]); + PRIMOUTREG(MGAREG_TEXWIDTH, regs[MGA_TEXREG_WIDTH]); + PRIMOUTREG(MGAREG_TEXHEIGHT, regs[MGA_TEXREG_HEIGHT]); + PRIMOUTREG(0x2d00 + 49 * 4, 0); + + PRIMOUTREG(0x2d00 + 57 * 4, 0); + PRIMOUTREG(0x2d00 + 53 * 4, 0); + PRIMOUTREG(0x2d00 + 61 * 4, 0); + PRIMOUTREG(0x2d00 + 52 * 4, regs[MGA_TEXREG_WIDTH] | 0x40); + + PRIMOUTREG(0x2d00 + 60 * 4, regs[MGA_TEXREG_HEIGHT] | 0x40); + PRIMOUTREG(MGAREG_TEXTRANS, 0xffff); + PRIMOUTREG(MGAREG_TEXTRANSHIGH, 0xffff); + PRIMOUTREG(MGAREG_TEXCTL2, regs[MGA_TEXREG_CTL2]); + + PRIMADVANCE(dev_priv); } -static void mgaG400EmitPipe(drm_mga_private_t *dev_priv ) +#define EMIT_PIPE 50 +static void mgaG400EmitPipe(drm_mga_private_t * dev_priv) { - drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; + drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; unsigned int pipe = sarea_priv->WarpPipe; float fParam = 12800.0f; PRIMLOCALS; DRM_DEBUG("%s\n", __FUNCTION__); - + PRIMGETPTR(dev_priv); - /* This takes 25 dwords */ - + /* This takes 50 dwords */ + /* Establish vertex size. */ + PRIMOUTREG(MGAREG_WIADDR2, WIA_wmode_suspend); + PRIMOUTREG(MGAREG_DMAPAD, 0); + PRIMOUTREG(MGAREG_DMAPAD, 0); + PRIMOUTREG(MGAREG_DMAPAD, 0); + if (pipe & MGA_T2) { PRIMOUTREG(MGAREG_WIADDR2, WIA_wmode_suspend); + PRIMOUTREG(MGAREG_DMAPAD, 0); + PRIMOUTREG(MGAREG_DMAPAD, 0); + PRIMOUTREG(MGAREG_DMAPAD, 0); + + if (!(dev_priv->WarpPipe & MGA_T2)) { + /* Flush the WARP pipe */ + PRIMOUTREG(MGAREG_YDST, 0); + PRIMOUTREG(MGAREG_FXLEFT, 0); + PRIMOUTREG(MGAREG_FXRIGHT, 1); + PRIMOUTREG(MGAREG_DWGCTL, MGA_FLUSH_CMD); + + PRIMOUTREG(MGAREG_LEN + MGAREG_MGA_EXEC, 1); + PRIMOUTREG(MGAREG_DMAPAD, 0); + PRIMOUTREG(MGAREG_DWGSYNC, 0x7000); + PRIMOUTREG(MGAREG_DMAPAD, 0); + + PRIMOUTREG(MGAREG_TEXCTL2, 0); + PRIMOUTREG(MGAREG_LEN + MGAREG_MGA_EXEC, 0); + PRIMOUTREG(MGAREG_TEXCTL2, 0x80); + PRIMOUTREG(MGAREG_LEN + MGAREG_MGA_EXEC, 0); + } + PRIMOUTREG(MGAREG_WVRTXSZ, 0x00001e09); + PRIMOUTREG(MGAREG_DMAPAD, 0); + PRIMOUTREG(MGAREG_DMAPAD, 0); + PRIMOUTREG(MGAREG_DMAPAD, 0); + + PRIMOUTREG(MGAREG_WACCEPTSEQ, 0); + PRIMOUTREG(MGAREG_WACCEPTSEQ, 0); + PRIMOUTREG(MGAREG_WACCEPTSEQ, 0); PRIMOUTREG(MGAREG_WACCEPTSEQ, 0x1e000000); - PRIMOUTREG(MGAREG_WFLAG, 0); } else { PRIMOUTREG(MGAREG_WIADDR2, WIA_wmode_suspend); + PRIMOUTREG(MGAREG_DMAPAD, 0); + PRIMOUTREG(MGAREG_DMAPAD, 0); + PRIMOUTREG(MGAREG_DMAPAD, 0); + PRIMOUTREG(MGAREG_WVRTXSZ, 0x00001807); + PRIMOUTREG(MGAREG_DMAPAD, 0); + PRIMOUTREG(MGAREG_DMAPAD, 0); + PRIMOUTREG(MGAREG_DMAPAD, 0); + + PRIMOUTREG(MGAREG_WACCEPTSEQ, 0); + PRIMOUTREG(MGAREG_WACCEPTSEQ, 0); + PRIMOUTREG(MGAREG_WACCEPTSEQ, 0); PRIMOUTREG(MGAREG_WACCEPTSEQ, 0x18000000); - PRIMOUTREG(MGAREG_WFLAG, 0); - } + } - PRIMOUTREG(MGAREG_WFLAG1, 0); - PRIMOUTREG(0x2d00 + 56*4, *((u32 *)(&fParam))); - PRIMOUTREG(MGAREG_DMAPAD, 0); + PRIMOUTREG(MGAREG_WFLAG, 0); + PRIMOUTREG(MGAREG_WFLAG1, 0); + PRIMOUTREG(0x2d00 + 56 * 4, *((u32 *) (&fParam))); PRIMOUTREG(MGAREG_DMAPAD, 0); - - PRIMOUTREG(0x2d00 + 49*4, 0); /* Tex stage 0 */ - PRIMOUTREG(0x2d00 + 57*4, 0); /* Tex stage 0 */ - PRIMOUTREG(0x2d00 + 53*4, 0); /* Tex stage 1 */ - PRIMOUTREG(0x2d00 + 61*4, 0); /* Tex stage 1 */ - - PRIMOUTREG(0x2d00 + 54*4, 0x40); /* Tex stage 0 : w */ - PRIMOUTREG(0x2d00 + 62*4, 0x40); /* Tex stage 0 : h */ - PRIMOUTREG(0x2d00 + 52*4, 0x40); /* Tex stage 1 : w */ - PRIMOUTREG(0x2d00 + 60*4, 0x40); /* Tex stage 1 : h */ - + + PRIMOUTREG(0x2d00 + 49 * 4, 0); /* Tex stage 0 */ + PRIMOUTREG(0x2d00 + 57 * 4, 0); /* Tex stage 0 */ + PRIMOUTREG(0x2d00 + 53 * 4, 0); /* Tex stage 1 */ + PRIMOUTREG(0x2d00 + 61 * 4, 0); /* Tex stage 1 */ + + PRIMOUTREG(0x2d00 + 54 * 4, 0x40); /* Tex stage 0 : w */ + PRIMOUTREG(0x2d00 + 62 * 4, 0x40); /* Tex stage 0 : h */ + PRIMOUTREG(0x2d00 + 52 * 4, 0x40); /* Tex stage 1 : w */ + PRIMOUTREG(0x2d00 + 60 * 4, 0x40); /* Tex stage 1 : h */ + /* Dma pading required due to hw bug */ PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff); PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff); PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff); - PRIMOUTREG(MGAREG_WIADDR2, (u32)(dev_priv->WarpIndex[pipe].phys_addr | - WIA_wmode_start | WIA_wagp_agp)); + PRIMOUTREG(MGAREG_WIADDR2, + (u32) (dev_priv->WarpIndex[pipe]. + phys_addr | WIA_wmode_start | WIA_wagp_agp)); PRIMADVANCE(dev_priv); } -static void mgaG200EmitPipe( drm_mga_private_t *dev_priv ) +static void mgaG200EmitPipe(drm_mga_private_t * dev_priv) { - drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; + drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; unsigned int pipe = sarea_priv->WarpPipe; PRIMLOCALS; DRM_DEBUG("%s\n", __FUNCTION__); PRIMGETPTR(dev_priv); - - /* This takes 15 dwords */ + + /* This takes 15 dwords */ PRIMOUTREG(MGAREG_WIADDR, WIA_wmode_suspend); PRIMOUTREG(MGAREG_WVRTXSZ, 7); PRIMOUTREG(MGAREG_WFLAG, 0); - PRIMOUTREG(0x2d00 + 24*4, 0); /* tex w/h */ - - PRIMOUTREG(0x2d00 + 25*4, 0x100); - PRIMOUTREG(0x2d00 + 34*4, 0); /* tex w/h */ - PRIMOUTREG(0x2d00 + 42*4, 0xFFFF); - PRIMOUTREG(0x2d00 + 60*4, 0xFFFF); - + PRIMOUTREG(0x2d00 + 24 * 4, 0); /* tex w/h */ + + PRIMOUTREG(0x2d00 + 25 * 4, 0x100); + PRIMOUTREG(0x2d00 + 34 * 4, 0); /* tex w/h */ + PRIMOUTREG(0x2d00 + 42 * 4, 0xFFFF); + PRIMOUTREG(0x2d00 + 60 * 4, 0xFFFF); + /* Dma pading required due to hw bug */ PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff); PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff); PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff); - PRIMOUTREG(MGAREG_WIADDR, (u32)(dev_priv->WarpIndex[pipe].phys_addr | - WIA_wmode_start | WIA_wagp_agp)); + PRIMOUTREG(MGAREG_WIADDR, + (u32) (dev_priv->WarpIndex[pipe]. + phys_addr | WIA_wmode_start | WIA_wagp_agp)); PRIMADVANCE(dev_priv); } -static void mgaEmitState( drm_mga_private_t *dev_priv ) +static void mgaEmitState(drm_mga_private_t * dev_priv) { - drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; + drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; unsigned int dirty = sarea_priv->dirty; DRM_DEBUG("%s\n", __FUNCTION__); - if (dev_priv->chipset == MGA_CARD_TYPE_G400) { + if (dev_priv->chipset == MGA_CARD_TYPE_G400) { int multitex = sarea_priv->WarpPipe & MGA_T2; - if (sarea_priv->WarpPipe != dev_priv->WarpPipe) { - mgaG400EmitPipe( dev_priv ); + if (sarea_priv->WarpPipe != dev_priv->WarpPipe) { + mgaG400EmitPipe(dev_priv); dev_priv->WarpPipe = sarea_priv->WarpPipe; } if (dirty & MGA_UPLOAD_CTX) { - mgaEmitContext( dev_priv ); - sarea_priv->dirty &= ~MGA_UPLOAD_CTX; + mgaEmitContext(dev_priv); + sarea_priv->dirty &= ~MGA_UPLOAD_CTX; } if (dirty & MGA_UPLOAD_TEX0) { - mgaG400EmitTex0( dev_priv ); - sarea_priv->dirty &= ~MGA_UPLOAD_TEX0; + mgaG400EmitTex0(dev_priv); + sarea_priv->dirty &= ~MGA_UPLOAD_TEX0; } if ((dirty & MGA_UPLOAD_TEX1) && multitex) { - mgaG400EmitTex1( dev_priv ); - sarea_priv->dirty &= ~MGA_UPLOAD_TEX1; + mgaG400EmitTex1(dev_priv); + sarea_priv->dirty &= ~MGA_UPLOAD_TEX1; } } else { - if (sarea_priv->WarpPipe != dev_priv->WarpPipe) { - mgaG200EmitPipe( dev_priv ); + if (sarea_priv->WarpPipe != dev_priv->WarpPipe) { + mgaG200EmitPipe(dev_priv); dev_priv->WarpPipe = sarea_priv->WarpPipe; } if (dirty & MGA_UPLOAD_CTX) { - mgaEmitContext( dev_priv ); - sarea_priv->dirty &= ~MGA_UPLOAD_CTX; + mgaEmitContext(dev_priv); + sarea_priv->dirty &= ~MGA_UPLOAD_CTX; } if (dirty & MGA_UPLOAD_TEX0) { - mgaG200EmitTex( dev_priv ); - sarea_priv->dirty &= ~MGA_UPLOAD_TEX0; + mgaG200EmitTex(dev_priv); + sarea_priv->dirty &= ~MGA_UPLOAD_TEX0; } } } @@ -346,19 +401,19 @@ static void mgaEmitState( drm_mga_private_t *dev_priv ) /* Disallow all write destinations except the front and backbuffer. */ -static int mgaVerifyContext(drm_mga_private_t *dev_priv ) +static int mgaVerifyContext(drm_mga_private_t * dev_priv) { drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; unsigned int *regs = sarea_priv->ContextState; - DRM_DEBUG("%s\n", __FUNCTION__); + DRM_DEBUG("%s\n", __FUNCTION__); if (regs[MGA_CTXREG_DSTORG] != dev_priv->frontOffset && regs[MGA_CTXREG_DSTORG] != dev_priv->backOffset) { - 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; + 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; return -1; } @@ -367,211 +422,196 @@ static int mgaVerifyContext(drm_mga_private_t *dev_priv ) /* Disallow texture reads from PCI space. */ -static int mgaVerifyTex(drm_mga_private_t *dev_priv, - int unit) +static int mgaVerifyTex(drm_mga_private_t * dev_priv, int unit) { drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; - DRM_DEBUG("%s\n", __FUNCTION__); + DRM_DEBUG("%s\n", __FUNCTION__); 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); + DRM_DEBUG("BAD TEXREG_ORG: %x, unit %d\n", + sarea_priv->TexState[unit][MGA_TEXREG_ORG], + unit); sarea_priv->TexState[unit][MGA_TEXREG_ORG] = 0; return -1; - } + } return 0; } -static int mgaVerifyState( drm_mga_private_t *dev_priv ) +static int mgaVerifyState(drm_mga_private_t * dev_priv) { drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; unsigned int dirty = sarea_priv->dirty; int rv = 0; - DRM_DEBUG("%s\n", __FUNCTION__); + DRM_DEBUG("%s\n", __FUNCTION__); - if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS) - sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS; + if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS) + sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS; if (dirty & MGA_UPLOAD_CTX) - rv |= mgaVerifyContext( dev_priv ); + rv |= mgaVerifyContext(dev_priv); if (dirty & MGA_UPLOAD_TEX0) - rv |= mgaVerifyTex( dev_priv, 0 ); + rv |= mgaVerifyTex(dev_priv, 0); - if (dev_priv->chipset == MGA_CARD_TYPE_G400) - { + if (dev_priv->chipset == MGA_CARD_TYPE_G400) { if (dirty & MGA_UPLOAD_TEX1) - rv |= mgaVerifyTex( dev_priv, 1 ); - - if (dirty & MGA_UPLOAD_PIPE) - rv |= (sarea_priv->WarpPipe > MGA_MAX_G400_PIPES); - } - else - { - if (dirty & MGA_UPLOAD_PIPE) - rv |= (sarea_priv->WarpPipe > MGA_MAX_G200_PIPES); - } + rv |= mgaVerifyTex(dev_priv, 1); + + if (dirty & MGA_UPLOAD_PIPE) + rv |= (sarea_priv->WarpPipe > MGA_MAX_G400_PIPES); + } else { + if (dirty & MGA_UPLOAD_PIPE) + rv |= (sarea_priv->WarpPipe > MGA_MAX_G200_PIPES); + } return rv == 0; } -static int mgaVerifyIload( drm_mga_private_t *dev_priv, - unsigned long bus_address, - unsigned int dstOrg, int length ) +static int mgaVerifyIload(drm_mga_private_t * dev_priv, + unsigned long bus_address, + unsigned int dstOrg, int length) { - DRM_DEBUG("%s\n", __FUNCTION__); + DRM_DEBUG("%s\n", __FUNCTION__); - if(dstOrg < dev_priv->textureOffset || - dstOrg + length > - (dev_priv->textureOffset + dev_priv->textureSize)) { - return -EINVAL; + if (dstOrg < dev_priv->textureOffset || + dstOrg + length > + (dev_priv->textureOffset + dev_priv->textureSize)) { + return -EINVAL; } - if(length % 64) { - return -EINVAL; + if (length % 64) { + return -EINVAL; } - return 0; + return 0; } /* This copies a 64 byte aligned agp region to the frambuffer * with a standard blit, the ioctl needs to do checking */ -static void mga_dma_dispatch_tex_blit( drm_device_t *dev, - unsigned long bus_address, - int length, - unsigned int destOrg ) +static void mga_dma_dispatch_tex_blit(drm_device_t * dev, + unsigned long bus_address, + int length, unsigned int destOrg) { - drm_mga_private_t *dev_priv = dev->dev_private; - int use_agp = PDEA_pagpxfer_enable | 0x00000001; - u16 y2; - PRIMLOCALS; + drm_mga_private_t *dev_priv = dev->dev_private; + int use_agp = PDEA_pagpxfer_enable | 0x00000001; + u16 y2; + PRIMLOCALS; DRM_DEBUG("%s\n", __FUNCTION__); - - y2 = length / 64; - + + y2 = length / 64; + PRIM_OVERFLOW(dev, dev_priv, 30); - PRIMGETPTR( dev_priv ); - - PRIMOUTREG( MGAREG_DSTORG, destOrg); - PRIMOUTREG( MGAREG_MACCESS, 0x00000000); - DRM_DEBUG("srcorg : %lx\n", bus_address | use_agp); - PRIMOUTREG( MGAREG_SRCORG, (u32) bus_address | use_agp); - PRIMOUTREG( MGAREG_AR5, 64); - - PRIMOUTREG( MGAREG_PITCH, 64); - PRIMOUTREG( MGAREG_DMAPAD, 0); - PRIMOUTREG( MGAREG_DMAPAD, 0); - PRIMOUTREG( MGAREG_DWGCTL, MGA_COPY_CMD); - - PRIMOUTREG(MGAREG_AR0, 63); - PRIMOUTREG(MGAREG_AR3, 0); - PRIMOUTREG(MGAREG_FXBNDRY, (63 << 16)); - PRIMOUTREG(MGAREG_YDSTLEN+MGAREG_MGA_EXEC, y2); - - PRIMOUTREG( MGAREG_SRCORG, 0); - PRIMOUTREG( MGAREG_PITCH, dev_priv->stride / dev_priv->cpp); - PRIMOUTREG( MGAREG_DMAPAD, 0); - PRIMOUTREG( MGAREG_DMAPAD, 0); - PRIMADVANCE(dev_priv); + PRIMGETPTR(dev_priv); + + PRIMOUTREG(MGAREG_DSTORG, destOrg); + PRIMOUTREG(MGAREG_MACCESS, 0x00000000); + DRM_DEBUG("srcorg : %lx\n", bus_address | use_agp); + PRIMOUTREG(MGAREG_SRCORG, (u32) bus_address | use_agp); + PRIMOUTREG(MGAREG_AR5, 64); + + PRIMOUTREG(MGAREG_PITCH, 64); + PRIMOUTREG(MGAREG_DMAPAD, 0); + PRIMOUTREG(MGAREG_DMAPAD, 0); + PRIMOUTREG(MGAREG_DWGCTL, MGA_COPY_CMD); + + PRIMOUTREG(MGAREG_AR0, 63); + PRIMOUTREG(MGAREG_AR3, 0); + PRIMOUTREG(MGAREG_FXBNDRY, (63 << 16)); + PRIMOUTREG(MGAREG_YDSTLEN + MGAREG_MGA_EXEC, y2); + + PRIMOUTREG(MGAREG_SRCORG, 0); + PRIMOUTREG(MGAREG_PITCH, dev_priv->stride / dev_priv->cpp); + PRIMOUTREG(MGAREG_DMAPAD, 0); + PRIMOUTREG(MGAREG_DMAPAD, 0); + PRIMADVANCE(dev_priv); } -static void mga_dma_dispatch_vertex(drm_device_t *dev, - drm_buf_t *buf) +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_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; + 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; - int primary_needed; - PRIMLOCALS; + int primary_needed; + PRIMLOCALS; DRM_DEBUG("%s\n", __FUNCTION__); DRM_DEBUG("dispatch vertex %d addr 0x%lx, " - "length 0x%x nbox %d dirty %x\n", - buf->idx, address, length, + "length 0x%x nbox %d dirty %x\n", + buf->idx, address, length, sarea_priv->nbox, sarea_priv->dirty); DRM_DEBUG("used : %d, total : %d\n", buf->used, buf->total); - if(sarea_priv->WarpPipe & MGA_T2) { - if ((buf->used/4) % 10) - DRM_DEBUG("Multitex Buf is not aligned properly!!!\n"); - } else { - if ((buf->used/4) % 8) - DRM_DEBUG("Buf is not aligned properly!!!\n"); - } if (buf->used) { /* WARNING: if you change any of the state functions verify * these numbers (Overestimating this doesn't hurt). */ buf_priv->dispatched = 1; - primary_needed = (25+15+30+25+ - 10 + - 15 * MGA_NR_SAREA_CLIPRECTS); + primary_needed = (50 + 15 + 15 + 30 + 25 + + 10 + 15 * MGA_NR_SAREA_CLIPRECTS); PRIM_OVERFLOW(dev, dev_priv, primary_needed); - mgaEmitState( dev_priv ); + mgaEmitState(dev_priv); do { if (i < sarea_priv->nbox) { DRM_DEBUG("idx %d Emit box %d/%d:" - "%d,%d - %d,%d\n", + "%d,%d - %d,%d\n", buf->idx, i, sarea_priv->nbox, - sarea_priv->boxes[i].x1, + sarea_priv->boxes[i].x1, sarea_priv->boxes[i].y1, - sarea_priv->boxes[i].x2, + sarea_priv->boxes[i].x2, sarea_priv->boxes[i].y2); - - mgaEmitClipRect( dev_priv, - &sarea_priv->boxes[i] ); + + 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); + 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); } - if (buf_priv->discard) { - if(buf_priv->dispatched == 1) AGEBUF(dev_priv, buf_priv); + if (buf_priv->discard) { + if (buf_priv->dispatched == 1) + AGEBUF(dev_priv, buf_priv); buf_priv->dispatched = 0; - mga_freelist_put(dev, buf); + mga_freelist_put(dev, buf); } } -static void mga_dma_dispatch_indices(drm_device_t *dev, - drm_buf_t *buf, - unsigned int start, - unsigned int end) +static void mga_dma_dispatch_indices(drm_device_t * dev, + drm_buf_t * buf, + unsigned int start, unsigned int end) { - drm_mga_private_t *dev_priv = dev->dev_private; + 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 int address = (unsigned int)buf->bus_address; + drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; + unsigned int address = (unsigned int) buf->bus_address; int use_agp = PDEA_pagpxfer_enable; int i = 0; - int primary_needed; - PRIMLOCALS; + int primary_needed; + PRIMLOCALS; DRM_DEBUG("%s\n", __FUNCTION__); DRM_DEBUG("dispatch indices %d addr 0x%x, " - "start 0x%x end 0x%x nbox %d dirty %x\n", - buf->idx, address, start, end, + "start 0x%x end 0x%x nbox %d dirty %x\n", + buf->idx, address, start, end, sarea_priv->nbox, sarea_priv->dirty); if (start != end) { @@ -579,173 +619,182 @@ static void mga_dma_dispatch_indices(drm_device_t *dev, * these numbers (Overestimating this doesn't hurt). */ buf_priv->dispatched = 1; - primary_needed = (25+15+30+25+ - 10 + - 15 * MGA_NR_SAREA_CLIPRECTS); - PRIM_OVERFLOW(dev, dev_priv, primary_needed); - mgaEmitState( dev_priv ); + primary_needed = (50 + 15 + 15 + 30 + 25 + + 10 + 15 * MGA_NR_SAREA_CLIPRECTS); + PRIM_OVERFLOW(dev, dev_priv, primary_needed); + mgaEmitState(dev_priv); do { if (i < sarea_priv->nbox) { DRM_DEBUG("idx %d Emit box %d/%d:" - "%d,%d - %d,%d\n", + "%d,%d - %d,%d\n", buf->idx, i, sarea_priv->nbox, - sarea_priv->boxes[i].x1, + sarea_priv->boxes[i].x1, sarea_priv->boxes[i].y1, - sarea_priv->boxes[i].x2, + sarea_priv->boxes[i].x2, sarea_priv->boxes[i].y2); - - mgaEmitClipRect( dev_priv, - &sarea_priv->boxes[i] ); + + mgaEmitClipRect(dev_priv, + &sarea_priv->boxes[i]); } - + PRIMGETPTR(dev_priv); - PRIMOUTREG( MGAREG_DMAPAD, 0); - PRIMOUTREG( MGAREG_DMAPAD, 0); - PRIMOUTREG( MGAREG_SETUPADDRESS, - ((address + start) | SETADD_mode_vertlist)); - PRIMOUTREG( MGAREG_SETUPEND, - ((address + end) | use_agp)); - PRIMADVANCE( dev_priv ); - } while (++i < sarea_priv->nbox); + PRIMOUTREG(MGAREG_DMAPAD, 0); + PRIMOUTREG(MGAREG_DMAPAD, 0); + PRIMOUTREG(MGAREG_SETUPADDRESS, + ((address + start) | + SETADD_mode_vertlist)); + PRIMOUTREG(MGAREG_SETUPEND, + ((address + end) | use_agp)); + PRIMADVANCE(dev_priv); + } while (++i < sarea_priv->nbox); } - if (buf_priv->discard) { - if(buf_priv->dispatched == 1) AGEBUF(dev_priv, buf_priv); + if (buf_priv->discard) { + if (buf_priv->dispatched == 1) + AGEBUF(dev_priv, buf_priv); buf_priv->dispatched = 0; - mga_freelist_put(dev, buf); + mga_freelist_put(dev, buf); } } -static void mga_dma_dispatch_clear( drm_device_t *dev, int flags, - unsigned int clear_color, - unsigned int clear_zval ) +static 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; + drm_mga_private_t *dev_priv = dev->dev_private; + drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; unsigned int *regs = sarea_priv->ContextState; int nbox = sarea_priv->nbox; drm_clip_rect_t *pbox = sarea_priv->boxes; unsigned int cmd; int i; - int primary_needed; - PRIMLOCALS; + int primary_needed; + PRIMLOCALS; DRM_DEBUG("%s\n", __FUNCTION__); - if ( dev_priv->sgram ) + if (dev_priv->sgram) cmd = MGA_CLEAR_CMD | DC_atype_blk; else cmd = MGA_CLEAR_CMD | DC_atype_rstr; - - primary_needed = nbox * 70; - if(primary_needed == 0) primary_needed = 70; + + primary_needed = nbox * 70; + if (primary_needed == 0) + primary_needed = 70; PRIM_OVERFLOW(dev, dev_priv, primary_needed); - PRIMGETPTR( dev_priv ); - - for (i = 0 ; i < nbox ; i++) { + PRIMGETPTR(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, + 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_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); + if (flags & MGA_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_DMAPAD, 0); PRIMOUTREG(MGAREG_FCOL, clear_color); PRIMOUTREG(MGAREG_DSTORG, dev_priv->frontOffset); - PRIMOUTREG(MGAREG_DWGCTL+MGAREG_MGA_EXEC, cmd ); + PRIMOUTREG(MGAREG_DWGCTL + MGAREG_MGA_EXEC, cmd); } - if ( flags & MGA_BACK ) { + if (flags & MGA_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_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 ); + PRIMOUTREG(MGAREG_DWGCTL + MGAREG_MGA_EXEC, cmd); } - if ( flags & MGA_DEPTH ) { + if (flags & MGA_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_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_DWGCTL + MGAREG_MGA_EXEC, cmd); } } /* Force reset of DWGCTL */ - PRIMOUTREG( MGAREG_DMAPAD, 0); - PRIMOUTREG( MGAREG_DMAPAD, 0); - PRIMOUTREG( MGAREG_DMAPAD, 0); - PRIMOUTREG( MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL] ); + PRIMOUTREG(MGAREG_DMAPAD, 0); + PRIMOUTREG(MGAREG_DMAPAD, 0); + PRIMOUTREG(MGAREG_DMAPAD, 0); + PRIMOUTREG(MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL]); PRIMADVANCE(dev_priv); } -static void mga_dma_dispatch_swap( drm_device_t *dev ) +static 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; + drm_mga_private_t *dev_priv = dev->dev_private; + drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; unsigned int *regs = sarea_priv->ContextState; int nbox = sarea_priv->nbox; drm_clip_rect_t *pbox = sarea_priv->boxes; int i; - int primary_needed; - PRIMLOCALS; + int primary_needed; + PRIMLOCALS; DRM_DEBUG("%s\n", __FUNCTION__); - primary_needed = nbox * 5; - primary_needed += 60; + primary_needed = nbox * 5; + primary_needed += 60; PRIM_OVERFLOW(dev, dev_priv, primary_needed); - PRIMGETPTR( dev_priv ); - + PRIMGETPTR(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++) { + 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); + 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_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); } - /* Force reset of DWGCTL */ - PRIMOUTREG( MGAREG_DMAPAD, 0); - PRIMOUTREG( MGAREG_DMAPAD, 0); - PRIMOUTREG( MGAREG_SRCORG, 0); - PRIMOUTREG( MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL] ); + /* Force reset of DWGCTL */ + PRIMOUTREG(MGAREG_DMAPAD, 0); + PRIMOUTREG(MGAREG_DMAPAD, 0); + PRIMOUTREG(MGAREG_SRCORG, 0); + PRIMOUTREG(MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL]); - PRIMADVANCE(dev_priv); + PRIMADVANCE(dev_priv); } int mga_clear_bufs(struct inode *inode, struct file *filp, @@ -753,32 +802,32 @@ int mga_clear_bufs(struct inode *inode, struct file *filp, { 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; + drm_mga_private_t *dev_priv = + (drm_mga_private_t *) dev->dev_private; + drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_mga_clear_t clear; - copy_from_user_ret(&clear, (drm_mga_clear_t *)arg, sizeof(clear), + copy_from_user_ret(&clear, (drm_mga_clear_t *) arg, sizeof(clear), -EFAULT); DRM_DEBUG("%s\n", __FUNCTION__); - if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { + if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { DRM_ERROR("mga_clear_bufs called without lock held\n"); return -EINVAL; } - - if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS) - sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS; + + 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_dispatch_clear(dev, clear.flags, + clear.clear_color, clear.clear_depth); + PRIMUPDATE(dev_priv); mga_flush_write_combine(); mga_dma_schedule(dev, 1); - return 0; + return 0; } int mga_swap_bufs(struct inode *inode, struct file *filp, @@ -786,76 +835,77 @@ int mga_swap_bufs(struct inode *inode, struct file *filp, { 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; + drm_mga_private_t *dev_priv = + (drm_mga_private_t *) dev->dev_private; + drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; DRM_DEBUG("%s\n", __FUNCTION__); - - if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { + + if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { DRM_ERROR("mga_swap_bufs called without lock held\n"); return -EINVAL; } - if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS) - sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS; + 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); - set_bit(MGA_BUF_SWAP_PENDING, &dev_priv->current_prim->buffer_status); + mga_dma_dispatch_swap(dev); + PRIMUPDATE(dev_priv); + set_bit(MGA_BUF_SWAP_PENDING, + &dev_priv->current_prim->buffer_status); mga_flush_write_combine(); mga_dma_schedule(dev, 1); - return 0; + return 0; } int mga_iload(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) + 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; - drm_buf_t *buf; - drm_mga_buf_priv_t *buf_priv; - drm_mga_iload_t iload; + 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; + drm_buf_t *buf; + drm_mga_buf_priv_t *buf_priv; + drm_mga_iload_t iload; unsigned long bus_address; DRM_DEBUG("%s\n", __FUNCTION__); - - DRM_DEBUG("Starting Iload\n"); - copy_from_user_ret(&iload, (drm_mga_iload_t *)arg, sizeof(iload), - -EFAULT); - if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { + DRM_DEBUG("Starting Iload\n"); + copy_from_user_ret(&iload, (drm_mga_iload_t *) arg, sizeof(iload), + -EFAULT); + + if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { DRM_ERROR("mga_iload called without lock held\n"); return -EINVAL; } - buf = dma->buflist[ iload.idx ]; + buf = dma->buflist[iload.idx]; buf_priv = buf->dev_private; - bus_address = buf->bus_address; - DRM_DEBUG("bus_address %lx, length %d, destorg : %x\n", - bus_address, iload.length, iload.destOrg); - - if(mgaVerifyIload(dev_priv, - bus_address, - iload.destOrg, - iload.length)) { - mga_freelist_put(dev, buf); - return -EINVAL; + bus_address = buf->bus_address; + DRM_DEBUG("bus_address %lx, length %d, destorg : %x\n", + bus_address, iload.length, iload.destOrg); + + if (mgaVerifyIload(dev_priv, + bus_address, iload.destOrg, iload.length)) { + mga_freelist_put(dev, buf); + return -EINVAL; } - - sarea_priv->dirty |= MGA_UPLOAD_CTX; - mga_dma_dispatch_tex_blit(dev, bus_address, iload.length, + sarea_priv->dirty |= MGA_UPLOAD_CTX; + + mga_dma_dispatch_tex_blit(dev, bus_address, iload.length, iload.destOrg); AGEBUF(dev_priv, buf_priv); buf_priv->discard = 1; - mga_freelist_put(dev, buf); + mga_freelist_put(dev, buf); mga_flush_write_combine(); mga_dma_schedule(dev, 1); - return 0; + return 0; } int mga_vertex(struct inode *inode, struct file *filp, @@ -863,45 +913,47 @@ int mga_vertex(struct inode *inode, struct file *filp, { 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_device_dma_t *dma = dev->dma; + drm_mga_private_t *dev_priv = + (drm_mga_private_t *) dev->dev_private; + drm_device_dma_t *dma = dev->dma; drm_buf_t *buf; - drm_mga_buf_priv_t *buf_priv; + drm_mga_buf_priv_t *buf_priv; drm_mga_vertex_t vertex; DRM_DEBUG("%s\n", __FUNCTION__); - copy_from_user_ret(&vertex, (drm_mga_vertex_t *)arg, sizeof(vertex), - -EFAULT); - - if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { + copy_from_user_ret(&vertex, (drm_mga_vertex_t *) arg, + sizeof(vertex), -EFAULT); + + if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { DRM_ERROR("mga_vertex called without lock held\n"); return -EINVAL; } DRM_DEBUG("mga_vertex\n"); - buf = dma->buflist[ vertex.idx ]; - buf_priv = buf->dev_private; + buf = dma->buflist[vertex.idx]; + buf_priv = buf->dev_private; buf->used = vertex.used; buf_priv->discard = vertex.discard; - + if (!mgaVerifyState(dev_priv)) { - if (vertex.discard) { - if(buf_priv->dispatched == 1) AGEBUF(dev_priv, buf_priv); - buf_priv->dispatched = 0; - mga_freelist_put(dev, buf); - } - DRM_DEBUG("bad state\n"); - return -EINVAL; + if (vertex.discard) { + if (buf_priv->dispatched == 1) + AGEBUF(dev_priv, buf_priv); + buf_priv->dispatched = 0; + mga_freelist_put(dev, buf); + } + DRM_DEBUG("bad state\n"); + return -EINVAL; } mga_dma_dispatch_vertex(dev, buf); - PRIMUPDATE(dev_priv); + PRIMUPDATE(dev_priv); mga_flush_write_combine(); mga_dma_schedule(dev, 1); - return 0; + return 0; } @@ -910,48 +962,50 @@ int mga_indices(struct inode *inode, struct file *filp, { 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_device_dma_t *dma = dev->dma; + drm_mga_private_t *dev_priv = + (drm_mga_private_t *) dev->dev_private; + drm_device_dma_t *dma = dev->dma; drm_buf_t *buf; - drm_mga_buf_priv_t *buf_priv; + drm_mga_buf_priv_t *buf_priv; drm_mga_indices_t indices; DRM_DEBUG("%s\n", __FUNCTION__); - copy_from_user_ret(&indices, (drm_mga_indices_t *)arg, sizeof(indices), - -EFAULT); - - if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { + copy_from_user_ret(&indices, (drm_mga_indices_t *) arg, + sizeof(indices), -EFAULT); + + if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { DRM_ERROR("mga_indices called without lock held\n"); return -EINVAL; } DRM_DEBUG("mga_indices\n"); - buf = dma->buflist[ indices.idx ]; - buf_priv = buf->dev_private; + buf = dma->buflist[indices.idx]; + buf_priv = buf->dev_private; buf_priv->discard = indices.discard; - + if (!mgaVerifyState(dev_priv)) { - if (indices.discard) { - if(buf_priv->dispatched == 1) AGEBUF(dev_priv, buf_priv); - buf_priv->dispatched = 0; - mga_freelist_put(dev, buf); - } - return -EINVAL; + if (indices.discard) { + if (buf_priv->dispatched == 1) + AGEBUF(dev_priv, buf_priv); + buf_priv->dispatched = 0; + mga_freelist_put(dev, buf); + } + return -EINVAL; } mga_dma_dispatch_indices(dev, buf, indices.start, indices.end); - PRIMUPDATE(dev_priv); + PRIMUPDATE(dev_priv); mga_flush_write_combine(); mga_dma_schedule(dev, 1); - return 0; + return 0; } -static int mga_dma_get_buffers(drm_device_t *dev, drm_dma_t *d) +static int mga_dma_get_buffers(drm_device_t * dev, drm_dma_t * d) { int i; drm_buf_t *buf; @@ -959,16 +1013,13 @@ static int mga_dma_get_buffers(drm_device_t *dev, drm_dma_t *d) for (i = d->granted_count; i < d->request_count; i++) { buf = mga_freelist_get(dev); - if (!buf) break; + if (!buf) + break; buf->pid = current->pid; copy_to_user_ret(&d->request_indices[i], - &buf->idx, - sizeof(buf->idx), - -EFAULT); + &buf->idx, sizeof(buf->idx), -EFAULT); copy_to_user_ret(&d->request_sizes[i], - &buf->total, - sizeof(buf->total), - -EFAULT); + &buf->total, sizeof(buf->total), -EFAULT); ++d->granted_count; } return 0; @@ -977,18 +1028,18 @@ static int mga_dma_get_buffers(drm_device_t *dev, drm_dma_t *d) 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; - int retcode = 0; - drm_dma_t d; + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_device_dma_t *dma = dev->dma; + int retcode = 0; + drm_dma_t d; DRM_DEBUG("%s\n", __FUNCTION__); - copy_from_user_ret(&d, (drm_dma_t *)arg, sizeof(d), -EFAULT); + 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); - if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { + if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { DRM_ERROR("mga_dma called without lock held\n"); return -EINVAL; } @@ -996,19 +1047,21 @@ int mga_dma(struct inode *inode, struct file *filp, unsigned int cmd, /* 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); + 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); + 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) { @@ -1017,6 +1070,6 @@ int mga_dma(struct inode *inode, struct file *filp, unsigned int cmd, DRM_DEBUG("%d returning, granted = %d\n", current->pid, d.granted_count); - copy_to_user_ret((drm_dma_t *)arg, &d, sizeof(d), -EFAULT); + copy_to_user_ret((drm_dma_t *) arg, &d, sizeof(d), -EFAULT); return retcode; } diff --git a/linux/proc.c b/linux/proc.c index db98fd6a..392abceb 100644 --- a/linux/proc.c +++ b/linux/proc.c @@ -1,8 +1,7 @@ /* proc.c -- /proc support for DRM -*- linux-c -*- * Created: Mon Jan 11 09:48:47 1999 by faith@precisioninsight.com - * Revised: Sun Feb 13 23:41:04 2000 by kevin@precisioninsight.com * - * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a @@ -400,6 +399,7 @@ static int _drm_vma_info(char *buf, char **start, off_t offset, int len, pgprot & _PAGE_GLOBAL ? 'g' : 'l' ); #endif DRM_PROC_PRINT("\n"); +#if 0 for (i = vma->vm_start; i < vma->vm_end; i += PAGE_SIZE) { pgd = pgd_offset(vma->vm_mm, i); pmd = pmd_offset(pgd, i); @@ -420,6 +420,7 @@ static int _drm_vma_info(char *buf, char **start, off_t offset, int len, DRM_PROC_PRINT(" 0x%08lx\n", i); } } +#endif } return len; diff --git a/linux/r128_bufs.c b/linux/r128_bufs.c new file mode 100644 index 00000000..bad6c571 --- /dev/null +++ b/linux/r128_bufs.c @@ -0,0 +1,309 @@ +/* r128_bufs.c -- IOCTLs to manage buffers -*- linux-c -*- + * Created: Wed Apr 12 16:19:08 2000 by kevin@precisioninsight.com + * + * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: Kevin E. Martin <kevin@precisioninsight.com> + * Rickard E. (Rik) Faith <faith@precisioninsight.com> + * Jeff Hartmann <jhartmann@precisioninsight.com> + * + * $XFree86$ + * + */ + +#define __NO_VERSION__ +#include "drmP.h" +#include "r128_drv.h" +#include "linux/un.h" + + +#ifdef DRM_AGP +int r128_addbufs_agp(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_device_dma_t *dma = dev->dma; + drm_buf_desc_t request; + drm_buf_entry_t *entry; + drm_buf_t *buf; + unsigned long offset; + unsigned long agp_offset; + int count; + int order; + int size; + int alignment; + int page_order; + int total; + int byte_count; + int i; + + if (!dma) return -EINVAL; + + copy_from_user_ret(&request, + (drm_buf_desc_t *)arg, + sizeof(request), + -EFAULT); + + count = request.count; + order = drm_order(request.size); + size = 1 << order; + + alignment = (request.flags & _DRM_PAGE_ALIGN) ? PAGE_ALIGN(size):size; + page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0; + total = PAGE_SIZE << page_order; + + byte_count = 0; + agp_offset = dev->agp->base + request.agp_start; + + DRM_DEBUG("count: %d\n", count); + DRM_DEBUG("order: %d\n", order); + DRM_DEBUG("size: %d\n", size); + DRM_DEBUG("agp_offset: %ld\n", agp_offset); + DRM_DEBUG("alignment: %d\n", alignment); + DRM_DEBUG("page_order: %d\n", page_order); + DRM_DEBUG("total: %d\n", total); + + if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) return -EINVAL; + if (dev->queue_count) return -EBUSY; /* Not while in use */ + + spin_lock(&dev->count_lock); + if (dev->buf_use) { + spin_unlock(&dev->count_lock); + return -EBUSY; + } + atomic_inc(&dev->buf_alloc); + spin_unlock(&dev->count_lock); + + down(&dev->struct_sem); + entry = &dma->bufs[order]; + if (entry->buf_count) { + up(&dev->struct_sem); + atomic_dec(&dev->buf_alloc); + return -ENOMEM; /* May only call once for each order */ + } + + entry->buflist = drm_alloc(count * sizeof(*entry->buflist), + DRM_MEM_BUFS); + if (!entry->buflist) { + up(&dev->struct_sem); + atomic_dec(&dev->buf_alloc); + return -ENOMEM; + } + memset(entry->buflist, 0, count * sizeof(*entry->buflist)); + + entry->buf_size = size; + entry->page_order = page_order; + offset = 0; + + for (offset = 0; + entry->buf_count < count; + offset += alignment, ++entry->buf_count) { + buf = &entry->buflist[entry->buf_count]; + buf->idx = dma->buf_count + entry->buf_count; + buf->total = alignment; + buf->order = order; + buf->used = 0; + buf->offset = (dma->byte_count + offset); + buf->address = (void *)(agp_offset + offset); + buf->next = NULL; + buf->waiting = 0; + buf->pending = 0; + init_waitqueue_head(&buf->dma_wait); + buf->pid = 0; + + buf->dev_priv_size = sizeof(drm_r128_buf_priv_t); + buf->dev_private = drm_alloc(sizeof(drm_r128_buf_priv_t), + DRM_MEM_BUFS); + memset(buf->dev_private, 0, buf->dev_priv_size); + +#if DRM_DMA_HISTOGRAM + buf->time_queued = 0; + buf->time_dispatched = 0; + buf->time_completed = 0; + buf->time_freed = 0; +#endif + + byte_count += PAGE_SIZE << page_order; + + DRM_DEBUG("buffer %d @ %p\n", + entry->buf_count, buf->address); + } + + DRM_DEBUG("byte_count: %d\n", byte_count); + + dma->buflist = drm_realloc(dma->buflist, + dma->buf_count * sizeof(*dma->buflist), + (dma->buf_count + entry->buf_count) + * sizeof(*dma->buflist), + DRM_MEM_BUFS); + for (i = dma->buf_count; i < dma->buf_count + entry->buf_count; i++) + dma->buflist[i] = &entry->buflist[i - dma->buf_count]; + + dma->buf_count += entry->buf_count; + dma->byte_count += byte_count; + + drm_freelist_create(&entry->freelist, entry->buf_count); + for (i = 0; i < entry->buf_count; i++) { + drm_freelist_put(dev, &entry->freelist, &entry->buflist[i]); + } + + up(&dev->struct_sem); + + request.count = entry->buf_count; + request.size = size; + + copy_to_user_ret((drm_buf_desc_t *)arg, + &request, + sizeof(request), + -EFAULT); + + dma->flags = _DRM_DMA_USE_AGP; + + atomic_dec(&dev->buf_alloc); + return 0; +} +#endif + +int r128_addbufs(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_r128_private_t *dev_priv = dev->dev_private; + drm_buf_desc_t request; + + if (!dev_priv || dev_priv->is_pci) return -EINVAL; + + copy_from_user_ret(&request, + (drm_buf_desc_t *)arg, + sizeof(request), + -EFAULT); + +#ifdef DRM_AGP + if (request.flags & _DRM_AGP_BUFFER) + return r128_addbufs_agp(inode, filp, cmd, arg); + else +#endif + return -EINVAL; +} + +int r128_mapbufs(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_r128_private_t *dev_priv = dev->dev_private; + drm_device_dma_t *dma = dev->dma; + int retcode = 0; + const int zero = 0; + unsigned long virtual; + unsigned long address; + drm_buf_map_t request; + int i; + + if (!dma || !dev_priv || dev_priv->is_pci) return -EINVAL; + + DRM_DEBUG("\n"); + + spin_lock(&dev->count_lock); + if (atomic_read(&dev->buf_alloc)) { + spin_unlock(&dev->count_lock); + return -EBUSY; + } + ++dev->buf_use; /* Can't allocate more after this call */ + spin_unlock(&dev->count_lock); + + copy_from_user_ret(&request, + (drm_buf_map_t *)arg, + sizeof(request), + -EFAULT); + + if (request.count >= dma->buf_count) { + if (dma->flags & _DRM_DMA_USE_AGP) { + drm_map_t *map; + + map = dev_priv->agp_vertbufs; + if (!map) { + retcode = -EINVAL; + goto done; + } + + down(¤t->mm->mmap_sem); + virtual = do_mmap(filp, 0, map->size, + PROT_READ|PROT_WRITE, + MAP_SHARED, + (unsigned long)map->offset); + up(¤t->mm->mmap_sem); + } else { + down(¤t->mm->mmap_sem); + virtual = do_mmap(filp, 0, dma->byte_count, + PROT_READ|PROT_WRITE, MAP_SHARED, 0); + up(¤t->mm->mmap_sem); + } + if (virtual > -1024UL) { + /* Real error */ + retcode = (signed long)virtual; + goto done; + } + request.virtual = (void *)virtual; + + for (i = 0; i < dma->buf_count; i++) { + if (copy_to_user(&request.list[i].idx, + &dma->buflist[i]->idx, + sizeof(request.list[0].idx))) { + retcode = -EFAULT; + goto done; + } + if (copy_to_user(&request.list[i].total, + &dma->buflist[i]->total, + sizeof(request.list[0].total))) { + retcode = -EFAULT; + goto done; + } + if (copy_to_user(&request.list[i].used, + &zero, + sizeof(zero))) { + retcode = -EFAULT; + goto done; + } + address = virtual + dma->buflist[i]->offset; + if (copy_to_user(&request.list[i].address, + &address, + sizeof(address))) { + retcode = -EFAULT; + goto done; + } + } + } + done: + request.count = dma->buf_count; + DRM_DEBUG("%d buffers, retcode = %d\n", request.count, retcode); + + copy_to_user_ret((drm_buf_map_t *)arg, + &request, + sizeof(request), + -EFAULT); + + return retcode; +} diff --git a/linux/r128_context.c b/linux/r128_context.c new file mode 100644 index 00000000..d288fd28 --- /dev/null +++ b/linux/r128_context.c @@ -0,0 +1,214 @@ +/* r128_context.c -- IOCTLs for r128 contexts -*- linux-c -*- + * Created: Mon Dec 13 09:51:35 1999 by faith@precisioninsight.com + * + * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Author: Rickard E. (Rik) Faith <faith@precisioninsight.com> + * + * $XFree86$ + * + */ + +#include <linux/sched.h> + +#define __NO_VERSION__ +#include "drmP.h" +#include "r128_drv.h" + +extern drm_ctx_t r128_res_ctx; + +static int r128_alloc_queue(drm_device_t *dev) +{ +#if 0 + static int context = 0; +#endif + + return drm_ctxbitmap_next(dev); +} + +int r128_context_switch(drm_device_t *dev, int old, int new) +{ + char buf[64]; + + atomic_inc(&dev->total_ctx); + + if (test_and_set_bit(0, &dev->context_flag)) { + DRM_ERROR("Reentering -- FIXME\n"); + return -EBUSY; + } + +#if DRM_DMA_HISTOGRAM + dev->ctx_start = get_cycles(); +#endif + + DRM_DEBUG("Context switch from %d to %d\n", old, new); + + if (new == dev->last_context) { + clear_bit(0, &dev->context_flag); + return 0; + } + + if (drm_flags & DRM_FLAG_NOCTX) { + r128_context_switch_complete(dev, new); + } else { + sprintf(buf, "C %d %d\n", old, new); + drm_write_string(dev, buf); + } + + return 0; +} + +int r128_context_switch_complete(drm_device_t *dev, int new) +{ + dev->last_context = new; /* PRE/POST: This is the _only_ writer. */ + dev->last_switch = jiffies; + + if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { + DRM_ERROR("Lock isn't held after context switch\n"); + } + + /* If a context switch is ever initiated + when the kernel holds the lock, release + that lock here. */ +#if DRM_DMA_HISTOGRAM + atomic_inc(&dev->histo.ctx[drm_histogram_slot(get_cycles() + - dev->ctx_start)]); + +#endif + clear_bit(0, &dev->context_flag); + wake_up(&dev->context_wait); + + return 0; +} + + +int r128_resctx(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg) +{ + drm_ctx_res_t res; + drm_ctx_t ctx; + int i; + + DRM_DEBUG("%d\n", DRM_RESERVED_CONTEXTS); + copy_from_user_ret(&res, (drm_ctx_res_t *)arg, sizeof(res), -EFAULT); + if (res.count >= DRM_RESERVED_CONTEXTS) { + memset(&ctx, 0, sizeof(ctx)); + for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) { + ctx.handle = i; + copy_to_user_ret(&res.contexts[i], + &i, + sizeof(i), + -EFAULT); + } + } + res.count = DRM_RESERVED_CONTEXTS; + copy_to_user_ret((drm_ctx_res_t *)arg, &res, sizeof(res), -EFAULT); + return 0; +} + + +int r128_addctx(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_ctx_t ctx; + + copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT); + if ((ctx.handle = r128_alloc_queue(dev)) == DRM_KERNEL_CONTEXT) { + /* Skip kernel's context and get a new one. */ + ctx.handle = r128_alloc_queue(dev); + } + DRM_DEBUG("%d\n", ctx.handle); + if (ctx.handle == -1) { + DRM_DEBUG("Not enough free contexts.\n"); + /* Should this return -EBUSY instead? */ + return -ENOMEM; + } + + copy_to_user_ret((drm_ctx_t *)arg, &ctx, sizeof(ctx), -EFAULT); + return 0; +} + +int r128_modctx(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg) +{ + drm_ctx_t ctx; + + copy_from_user_ret(&ctx, (drm_ctx_t*)arg, sizeof(ctx), -EFAULT); + if (ctx.flags==_DRM_CONTEXT_PRESERVED) + r128_res_ctx.handle=ctx.handle; + return 0; +} + +int r128_getctx(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg) +{ + drm_ctx_t ctx; + + copy_from_user_ret(&ctx, (drm_ctx_t*)arg, sizeof(ctx), -EFAULT); + /* This is 0, because we don't hanlde any context flags */ + ctx.flags = 0; + copy_to_user_ret((drm_ctx_t*)arg, &ctx, sizeof(ctx), -EFAULT); + return 0; +} + +int r128_switchctx(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_ctx_t ctx; + + copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT); + DRM_DEBUG("%d\n", ctx.handle); + return r128_context_switch(dev, dev->last_context, ctx.handle); +} + +int r128_newctx(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_ctx_t ctx; + + copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT); + DRM_DEBUG("%d\n", ctx.handle); + r128_context_switch_complete(dev, ctx.handle); + + return 0; +} + +int r128_rmctx(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_ctx_t ctx; + + copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT); + DRM_DEBUG("%d\n", ctx.handle); + drm_ctxbitmap_free(dev, ctx.handle); + + return 0; +} diff --git a/linux/r128_dma.c b/linux/r128_dma.c new file mode 100644 index 00000000..860c4188 --- /dev/null +++ b/linux/r128_dma.c @@ -0,0 +1,908 @@ +/* r128_drv.c -- ATI Rage 128 driver -*- linux-c -*- + * Created: Wed Apr 5 19:24:19 2000 by kevin@precisioninsight.com + * + * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: Kevin E. Martin <kevin@precisioninsight.com> + * + * $XFree86$ + * + */ + +#define __NO_VERSION__ +#include "drmP.h" +#include "r128_drv.h" + +#include <linux/interrupt.h> /* For task queue support */ +#include <linux/delay.h> + + + +#define DO_REMAP(_m) (_m)->handle = drm_ioremap((_m)->offset, (_m)->size) + +#define DO_REMAPFREE(_m) \ + do { \ + if ((_m)->handle && (_m)->size) \ + drm_ioremapfree((_m)->handle, (_m)->size); \ + } while (0) + +#define DO_FIND_MAP(_m, _o) \ + do { \ + int _i; \ + for (_i = 0; _i < dev->map_count; _i++) { \ + if (dev->maplist[_i]->offset == _o) { \ + _m = dev->maplist[_i]; \ + break; \ + } \ + } \ + } while (0) + + +#define R128_MAX_VBUF_AGE 0x10000000 +#define R128_VB_AGE_REG R128_GUI_SCRATCH_REG0 + +int R128_READ_PLL(drm_device_t *dev, int addr) +{ + drm_r128_private_t *dev_priv = dev->dev_private; + + R128_WRITE8(R128_CLOCK_CNTL_INDEX, addr & 0x1f); + return R128_READ(R128_CLOCK_CNTL_DATA); +} + +static void r128_flush_write_combine(void) +{ + int xchangeDummy; + + __asm__ volatile("push %%eax ;" + "xchg %%eax, %0 ;" + "pop %%eax" : : "m" (xchangeDummy)); + __asm__ volatile("push %%eax ;" + "push %%ebx ;" + "push %%ecx ;" + "push %%edx ;" + "movl $0,%%eax ;" + "cpuid ;" + "pop %%edx ;" + "pop %%ecx ;" + "pop %%ebx ;" + "pop %%eax" : /* no outputs */ : /* no inputs */ ); +} + +static int r128_do_cleanup_cce(drm_device_t *dev) +{ + if (dev->dev_private) { + drm_r128_private_t *dev_priv = dev->dev_private; + + if (!dev_priv->is_pci) { + DO_REMAPFREE(dev_priv->agp_ring); + DO_REMAPFREE(dev_priv->agp_read_ptr); + DO_REMAPFREE(dev_priv->agp_vertbufs); + DO_REMAPFREE(dev_priv->agp_indbufs); + DO_REMAPFREE(dev_priv->agp_textures); + } + + drm_free(dev->dev_private, sizeof(drm_r128_private_t), + DRM_MEM_DRIVER); + dev->dev_private = NULL; + } + + return 0; +} + +static int r128_do_init_cce(drm_device_t *dev, drm_r128_init_t *init) +{ + drm_r128_private_t *dev_priv; + int i; + + dev_priv = drm_alloc(sizeof(drm_r128_private_t), DRM_MEM_DRIVER); + if (dev_priv == NULL) return -ENOMEM; + dev->dev_private = (void *)dev_priv; + + memset(dev_priv, 0, sizeof(drm_r128_private_t)); + + dev_priv->is_pci = init->is_pci; + + dev_priv->usec_timeout = init->usec_timeout; + if (dev_priv->usec_timeout < 1 || + dev_priv->usec_timeout > R128_MAX_USEC_TIMEOUT) { + drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER); + dev->dev_private = NULL; + return -EINVAL; + } + + dev_priv->cce_mode = init->cce_mode; + dev_priv->cce_fifo_size = init->cce_fifo_size; + dev_priv->cce_is_bm_mode = + ((init->cce_mode == R128_PM4_192BM) || + (init->cce_mode == R128_PM4_128BM_64INDBM) || + (init->cce_mode == R128_PM4_64BM_128INDBM) || + (init->cce_mode == R128_PM4_64BM_64VCBM_64INDBM)); + dev_priv->cce_secure = init->cce_secure; + + if (dev_priv->cce_is_bm_mode && dev_priv->is_pci) { + drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER); + dev->dev_private = NULL; + return -EINVAL; + } + + for (i = 0; i < dev->map_count; i++) { + if (dev->maplist[i]->type == _DRM_SHM) { + dev_priv->sarea = dev->maplist[i]; + break; + } + } + + DO_FIND_MAP(dev_priv->fb, init->fb_offset); + if (!dev_priv->is_pci) { + DO_FIND_MAP(dev_priv->agp_ring, init->agp_ring_offset); + DO_FIND_MAP(dev_priv->agp_read_ptr, init->agp_read_ptr_offset); + DO_FIND_MAP(dev_priv->agp_vertbufs, init->agp_vertbufs_offset); + DO_FIND_MAP(dev_priv->agp_indbufs, init->agp_indbufs_offset); + DO_FIND_MAP(dev_priv->agp_textures, init->agp_textures_offset); + } + DO_FIND_MAP(dev_priv->mmio, init->mmio_offset); + + dev_priv->sarea_priv = + (drm_r128_sarea_t *)((u8 *)dev_priv->sarea->handle + + init->sarea_priv_offset); + + if (!dev_priv->is_pci) { + DO_REMAP(dev_priv->agp_ring); + DO_REMAP(dev_priv->agp_read_ptr); + DO_REMAP(dev_priv->agp_vertbufs); +#if 0 + DO_REMAP(dev_priv->agp_indirectbufs); + DO_REMAP(dev_priv->agp_textures); +#endif + + dev_priv->ring_size = init->ring_size; + dev_priv->ring_sizel2qw = drm_order(init->ring_size/8); + dev_priv->ring_entries = init->ring_size/sizeof(u32); + dev_priv->ring_read_ptr = ((__volatile__ u32 *) + dev_priv->agp_read_ptr->handle); + dev_priv->ring_start = (u32 *)dev_priv->agp_ring->handle; + dev_priv->ring_end = ((u32 *)dev_priv->agp_ring->handle + + dev_priv->ring_entries); + } + + dev_priv->submit_age = 0; + R128_WRITE(R128_VB_AGE_REG, dev_priv->submit_age); + + return 0; +} + +int r128_init_cce(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_r128_init_t init; + + copy_from_user_ret(&init, (drm_r128_init_t *)arg, sizeof(init), + -EFAULT); + + switch (init.func) { + case R128_INIT_CCE: + return r128_do_init_cce(dev, &init); + case R128_CLEANUP_CCE: + return r128_do_cleanup_cce(dev); + } + + return -EINVAL; +} + +static void r128_mark_vertbufs_done(drm_device_t *dev) +{ + drm_device_dma_t *dma = dev->dma; + int i; + + for (i = 0; i < dma->buf_count; i++) { + drm_buf_t *buf = dma->buflist[i]; + drm_r128_buf_priv_t *buf_priv = buf->dev_private; + buf_priv->age = 0; + } +} + +static int r128_do_pixcache_flush(drm_device_t *dev) +{ + drm_r128_private_t *dev_priv = dev->dev_private; + u32 tmp; + int i; + + tmp = R128_READ(R128_PC_NGUI_CTLSTAT) | R128_PC_FLUSH_ALL; + R128_WRITE(R128_PC_NGUI_CTLSTAT, tmp); + + for (i = 0; i < dev_priv->usec_timeout; i++) { + if (!(R128_READ(R128_PC_NGUI_CTLSTAT) & R128_PC_BUSY)) + return 0; + udelay(1); + } + + return -EBUSY; +} + +static int r128_do_wait_for_fifo(drm_device_t *dev, int entries) +{ + drm_r128_private_t *dev_priv = dev->dev_private; + int i; + + for (i = 0; i < dev_priv->usec_timeout; i++) { + int slots = R128_READ(R128_GUI_STAT) & R128_GUI_FIFOCNT_MASK; + if (slots >= entries) return 0; + udelay(1); + } + return -EBUSY; +} + +static int r128_do_wait_for_idle(drm_device_t *dev) +{ + drm_r128_private_t *dev_priv = dev->dev_private; + int i, ret; + + if (!(ret = r128_do_wait_for_fifo(dev, 64))) return ret; + + for (i = 0; i < dev_priv->usec_timeout; i++) { + if (!(R128_READ(R128_GUI_STAT) & R128_GUI_ACTIVE)) { + (void)r128_do_pixcache_flush(dev); + return 0; + } + udelay(1); + } + return -EBUSY; +} + +int r128_do_engine_reset(drm_device_t *dev) +{ + drm_r128_private_t *dev_priv = dev->dev_private; + u32 clock_cntl_index, mclk_cntl, gen_reset_cntl; + + (void)r128_do_pixcache_flush(dev); + + clock_cntl_index = R128_READ(R128_CLOCK_CNTL_INDEX); + mclk_cntl = R128_READ_PLL(dev, R128_MCLK_CNTL); + + R128_WRITE_PLL(R128_MCLK_CNTL, + mclk_cntl | R128_FORCE_GCP | R128_FORCE_PIPE3D_CPP); + + gen_reset_cntl = R128_READ(R128_GEN_RESET_CNTL); + + R128_WRITE(R128_GEN_RESET_CNTL, gen_reset_cntl | R128_SOFT_RESET_GUI); + (void)R128_READ(R128_GEN_RESET_CNTL); + R128_WRITE(R128_GEN_RESET_CNTL, gen_reset_cntl & ~R128_SOFT_RESET_GUI); + (void)R128_READ(R128_GEN_RESET_CNTL); + + R128_WRITE_PLL(R128_MCLK_CNTL, mclk_cntl); + R128_WRITE(R128_CLOCK_CNTL_INDEX, clock_cntl_index); + R128_WRITE(R128_GEN_RESET_CNTL, gen_reset_cntl); + + /* For CCE ring buffer only */ + if (dev_priv->cce_is_bm_mode) { + R128_WRITE(R128_PM4_BUFFER_DL_WPTR, 0); + R128_WRITE(R128_PM4_BUFFER_DL_RPTR, 0); + *dev_priv->ring_read_ptr = 0; + dev_priv->sarea_priv->ring_write = 0; + } + + /* Reset the CCE mode */ + (void)r128_do_wait_for_idle(dev); + R128_WRITE(R128_PM4_BUFFER_CNTL, + dev_priv->cce_mode | dev_priv->ring_sizel2qw); + (void)R128_READ(R128_PM4_BUFFER_ADDR); /* as per the sample code */ + R128_WRITE(R128_PM4_MICRO_CNTL, R128_PM4_MICRO_FREERUN); + + r128_mark_vertbufs_done(dev); + return 0; +} + +int r128_eng_reset(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; + + if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) || + dev->lock.pid != current->pid) { + DRM_ERROR("r128_eng_reset called without holding the lock\n"); + return -EINVAL; + } + + return r128_do_engine_reset(dev); +} + +static int r128_do_engine_flush(drm_device_t *dev) +{ + drm_r128_private_t *dev_priv = dev->dev_private; + u32 tmp; + + tmp = R128_READ(R128_PM4_BUFFER_DL_WPTR); + R128_WRITE(R128_PM4_BUFFER_DL_WPTR, tmp | R128_PM4_BUFFER_DL_DONE); + + return 0; +} + +int r128_eng_flush(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; + + if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) || + dev->lock.pid != current->pid) { + DRM_ERROR("r128_eng_flush called without holding the lock\n"); + return -EINVAL; + } + + return r128_do_engine_flush(dev); +} + +static int r128_do_cce_wait_for_fifo(drm_device_t *dev, int entries) +{ + drm_r128_private_t *dev_priv = dev->dev_private; + int i; + + for (i = 0; i < dev_priv->usec_timeout; i++) { + int slots = R128_READ(R128_PM4_STAT) & R128_PM4_FIFOCNT_MASK; + if (slots >= entries) return 0; + udelay(1); + } + return -EBUSY; +} + +int r128_do_cce_wait_for_idle(drm_device_t *dev) +{ + drm_r128_private_t *dev_priv = dev->dev_private; + int i; + + if (dev_priv->cce_is_bm_mode) { + for (i = 0; i < dev_priv->usec_timeout; i++) { + if (*dev_priv->ring_read_ptr == dev_priv->sarea_priv->ring_write) { + int pm4stat = R128_READ(R128_PM4_STAT); + if ((pm4stat & R128_PM4_FIFOCNT_MASK) >= dev_priv->cce_fifo_size && + !(pm4stat & (R128_PM4_BUSY | R128_PM4_GUI_ACTIVE))) { + return r128_do_pixcache_flush(dev); + } + } + udelay(1); + } + return -EBUSY; + } else { + int ret = r128_do_cce_wait_for_fifo(dev, dev_priv->cce_fifo_size); + if (ret < 0) return ret; + + for (i = 0; i < dev_priv->usec_timeout; i++) { + int pm4stat = R128_READ(R128_PM4_STAT); + if (!(pm4stat & (R128_PM4_BUSY | R128_PM4_GUI_ACTIVE))) { + return r128_do_pixcache_flush(dev); + } + udelay(1); + } + return -EBUSY; + } +} + +int r128_cce_idle(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; + + if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) || + dev->lock.pid != current->pid) { + DRM_ERROR("r128_wait_idle called without holding the lock\n"); + return -EINVAL; + } + + return r128_do_cce_wait_for_idle(dev); +} + +static int r128_submit_packets_ring_secure(drm_device_t *dev, + u32 *commands, int *count) +{ + drm_r128_private_t *dev_priv = dev->dev_private; + int write = dev_priv->sarea_priv->ring_write; + int *write_ptr = dev_priv->ring_start + write; + int c = *count; + u32 tmp = 0; + int psize = 0; + int writing = 1; + int timeout; + + while (c > 0) { + tmp = *commands++; + if (!psize) { + writing = 1; + + if ((tmp & R128_CCE_PACKET_MASK) == R128_CCE_PACKET0) { + if ((tmp & R128_CCE_PACKET0_REG_MASK) <= (0x1004 >> 2)) { + if ((tmp & R128_CCE_PACKET0_REG_MASK) != + (R128_PM4_VC_FPU_SETUP >> 2)) { + writing = 0; + } + } + psize = ((tmp & R128_CCE_PACKET_COUNT_MASK) >> 16) + 2; + } else if ((tmp & R128_CCE_PACKET_MASK) == R128_CCE_PACKET1) { + if ((tmp & R128_CCE_PACKET1_REG0_MASK) <= (0x1004 >> 2)) { + if ((tmp & R128_CCE_PACKET1_REG0_MASK) != + (R128_PM4_VC_FPU_SETUP >> 2)) { + writing = 0; + } + } else if ((tmp & R128_CCE_PACKET1_REG1_MASK) <= + (0x1004 << 9)) { + if ((tmp & R128_CCE_PACKET1_REG1_MASK) != + (R128_PM4_VC_FPU_SETUP << 9)) { + writing = 0; + } + } + psize = 3; + } else { + psize = ((tmp & R128_CCE_PACKET_COUNT_MASK) >> 16) + 2; + } + } + psize--; + + if (writing) { + write++; + *write_ptr++ = tmp; + } + if (write >= dev_priv->ring_entries) { + write = 0; + write_ptr = dev_priv->ring_start; + } + timeout = 0; + while (write == *dev_priv->ring_read_ptr) { + (void)R128_READ(R128_PM4_BUFFER_DL_RPTR); + if (timeout++ >= dev_priv->usec_timeout) + return -EBUSY; + udelay(1); + } + c--; + } + + if (write < 32) + memcpy(dev_priv->ring_end, + dev_priv->ring_start, + write * sizeof(u32)); + + /* Make sure WC cache has been flushed */ + r128_flush_write_combine(); + + dev_priv->sarea_priv->ring_write = write; + R128_WRITE(R128_PM4_BUFFER_DL_WPTR, write); + + *count = 0; + + return 0; +} + +static int r128_submit_packets_pio_secure(drm_device_t *dev, + u32 *commands, int *count) +{ + drm_r128_private_t *dev_priv = dev->dev_private; + u32 tmp = 0; + int psize = 0; + int writing = 1; + int addr = R128_PM4_FIFO_DATA_EVEN; + int ret; + + while (*count > 0) { + tmp = *commands++; + if (!psize) { + writing = 1; + + if ((tmp & R128_CCE_PACKET_MASK) == R128_CCE_PACKET0) { + if ((tmp & R128_CCE_PACKET0_REG_MASK) <= (0x1004 >> 2)) { + if ((tmp & R128_CCE_PACKET0_REG_MASK) != + (R128_PM4_VC_FPU_SETUP >> 2)) { + writing = 0; + } + } + psize = ((tmp & R128_CCE_PACKET_COUNT_MASK) >> 16) + 2; + } else if ((tmp & R128_CCE_PACKET_MASK) == R128_CCE_PACKET1) { + if ((tmp & R128_CCE_PACKET1_REG0_MASK) <= (0x1004 >> 2)) { + if ((tmp & R128_CCE_PACKET1_REG0_MASK) != + (R128_PM4_VC_FPU_SETUP >> 2)) { + writing = 0; + } + } else if ((tmp & R128_CCE_PACKET1_REG1_MASK) <= + (0x1004 << 9)) { + if ((tmp & R128_CCE_PACKET1_REG1_MASK) != + (R128_PM4_VC_FPU_SETUP << 9)) { + writing = 0; + } + } + psize = 3; + } else { + psize = ((tmp & R128_CCE_PACKET_COUNT_MASK) >> 16) + 2; + } + } + psize--; + + if (writing) { + if ((ret = r128_do_cce_wait_for_fifo(dev, 1)) < 0) + return ret; + R128_WRITE(addr, tmp); + addr ^= 0x0004; + } + + *count -= 1; + } + + if (addr == R128_PM4_FIFO_DATA_ODD) { + if ((ret = r128_do_cce_wait_for_fifo(dev, 1)) < 0) return ret; + R128_WRITE(addr, R128_CCE_PACKET2); + } + + return 0; +} + +static int r128_submit_packets_ring(drm_device_t *dev, + u32 *commands, int *count) +{ + drm_r128_private_t *dev_priv = dev->dev_private; + int write = dev_priv->sarea_priv->ring_write; + int *write_ptr = dev_priv->ring_start + write; + int c = *count; + int timeout; + + while (c > 0) { + write++; + *write_ptr++ = *commands++; + if (write >= dev_priv->ring_entries) { + write = 0; + write_ptr = dev_priv->ring_start; + } + timeout = 0; + while (write == *dev_priv->ring_read_ptr) { + (void)R128_READ(R128_PM4_BUFFER_DL_RPTR); + if (timeout++ >= dev_priv->usec_timeout) + return -EBUSY; + udelay(1); + } + c--; + } + + if (write < 32) + memcpy(dev_priv->ring_end, + dev_priv->ring_start, + write * sizeof(u32)); + + /* Make sure WC cache has been flushed */ + r128_flush_write_combine(); + + dev_priv->sarea_priv->ring_write = write; + R128_WRITE(R128_PM4_BUFFER_DL_WPTR, write); + + *count = 0; + + return 0; +} + +static int r128_submit_packets_pio(drm_device_t *dev, + u32 *commands, int *count) +{ + drm_r128_private_t *dev_priv = dev->dev_private; + int ret; + + while (*count > 1) { + if ((ret = r128_do_cce_wait_for_fifo(dev, 2)) < 0) return ret; + R128_WRITE(R128_PM4_FIFO_DATA_EVEN, *commands++); + R128_WRITE(R128_PM4_FIFO_DATA_ODD, *commands++); + *count -= 2; + } + + if (*count) { + if ((ret = r128_do_cce_wait_for_fifo(dev, 2)) < 0) return ret; + R128_WRITE(R128_PM4_FIFO_DATA_EVEN, *commands++); + R128_WRITE(R128_PM4_FIFO_DATA_ODD, R128_CCE_PACKET2); + *count = 0; + } + + return 0; +} + +static int r128_do_submit_packets(drm_device_t *dev, u32 *buffer, int count) +{ + drm_r128_private_t *dev_priv = dev->dev_private; + int c = count; + int ret; + + if (dev_priv->cce_is_bm_mode) { + int left = 0; + + if (c >= dev_priv->ring_entries) { + c = dev_priv->ring_entries-1; + left = count - c; + } + + /* Since this is only used by the kernel we can use the + insecure ring buffer submit packet routine */ + ret = r128_submit_packets_ring(dev, buffer, &c); + + c += left; + } else { + /* Since this is only used by the kernel we can use the + insecure PIO submit packet routine */ + ret = r128_submit_packets_pio(dev, buffer, &c); + } + + if (ret < 0) return ret; + else return c; +} + +int r128_submit_pkt(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_r128_private_t *dev_priv = dev->dev_private; + drm_r128_packet_t packet; + u32 *buffer; + int c; + int size; + int ret = 0; + + if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) || + dev->lock.pid != current->pid) { + DRM_ERROR("r128_submit_pkt called without holding the lock\n"); + return -EINVAL; + } + + copy_from_user_ret(&packet, (drm_r128_packet_t *)arg, sizeof(packet), + -EFAULT); + + c = packet.count; + size = c * sizeof(*buffer); + + if (dev_priv->cce_is_bm_mode) { + int left = 0; + + if (c >= dev_priv->ring_entries) { + c = dev_priv->ring_entries-1; + size = c * sizeof(*buffer); + left = packet.count - c; + } + + if ((buffer = kmalloc(size, 0)) == NULL) return -ENOMEM; + copy_from_user_ret(buffer, packet.buffer, size, -EFAULT); + + if (dev_priv->cce_secure) + ret = r128_submit_packets_ring_secure(dev, buffer, &c); + else + ret = r128_submit_packets_ring(dev, buffer, &c); + + c += left; + } else { + if ((buffer = kmalloc(size, 0)) == NULL) return -ENOMEM; + copy_from_user_ret(buffer, packet.buffer, size, -EFAULT); + + if (dev_priv->cce_secure) + ret = r128_submit_packets_pio_secure(dev, buffer, &c); + else + ret = r128_submit_packets_pio(dev, buffer, &c); + } + + kfree(buffer); + + packet.count = c; + copy_to_user_ret((drm_r128_packet_t *)arg, &packet, sizeof(packet), + -EFAULT); + + if (ret) return ret; + else if (c > 0) return -EAGAIN; + + return 0; +} + +static int r128_send_vertbufs(drm_device_t *dev, drm_r128_vertex_t *v) +{ + drm_device_dma_t *dma = dev->dma; + drm_r128_private_t *dev_priv = dev->dev_private; + drm_r128_buf_priv_t *buf_priv; + drm_buf_t *buf; + int i, ret; + u32 cce[2]; + + /* Make sure we have valid data */ + for (i = 0; i < v->send_count; i++) { + int idx = v->send_indices[i]; + + if (idx < 0 || idx >= dma->buf_count) { + DRM_ERROR("Index %d (of %d max)\n", + idx, dma->buf_count - 1); + return -EINVAL; + } + buf = dma->buflist[idx]; + if (buf->pid != current->pid) { + DRM_ERROR("Process %d using buffer owned by %d\n", + current->pid, buf->pid); + return -EINVAL; + } + if (buf->pending) { + DRM_ERROR("Sending pending buffer:" + " buffer %d, offset %d\n", + v->send_indices[i], i); + return -EINVAL; + } + } + + /* Wait for idle, if we've wrapped to make sure that all pending + buffers have been processed */ + if (dev_priv->submit_age == R128_MAX_VBUF_AGE) { + if ((ret = r128_do_cce_wait_for_idle(dev)) < 0) return ret; + dev_priv->submit_age = 0; + r128_mark_vertbufs_done(dev); + } + + /* Make sure WC cache has been flushed (if in PIO mode) */ + if (!dev_priv->cce_is_bm_mode) r128_flush_write_combine(); + + /* FIXME: Add support for sending vertex buffer to the CCE here + instead of in client code. The v->prim holds the primitive + type that should be drawn. Loop over the list buffers in + send_indices[] and submit a packet for each VB. + + This will require us to loop over the clip rects here as + well, which implies that we extend the kernel driver to allow + cliprects to be stored here. Note that the cliprects could + possibly come from the X server instead of the client, but + this will require additional changes to the DRI to allow for + this optimization. */ + + /* Submit a CCE packet that writes submit_age to R128_VB_AGE_REG */ + cce[0] = R128CCE0(R128_CCE_PACKET0, R128_VB_AGE_REG, 0); + cce[1] = dev_priv->submit_age; + if ((ret = r128_do_submit_packets(dev, cce, 2)) < 0) { + /* Until we add support for sending VBs to the CCE in + this routine, we can recover from this error. After + we add that support, we won't be able to easily + recover, so we will probably have to implement + another mechanism for handling timeouts from packets + submitted directly by the kernel. */ + return ret; + } + + /* Now that the submit packet request has succeeded, we can mark + the buffers as pending */ + for (i = 0; i < v->send_count; i++) { + buf = dma->buflist[v->send_indices[i]]; + buf->pending = 1; + + buf_priv = buf->dev_private; + buf_priv->age = dev_priv->submit_age; + } + + dev_priv->submit_age++; + + return 0; +} + +static drm_buf_t *r128_freelist_get(drm_device_t *dev) +{ + drm_device_dma_t *dma = dev->dma; + drm_r128_private_t *dev_priv = dev->dev_private; + drm_r128_buf_priv_t *buf_priv; + drm_buf_t *buf; + int i, t; + + /* FIXME: Optimize -- use freelist code */ + + for (i = 0; i < dma->buf_count; i++) { + buf = dma->buflist[i]; + buf_priv = buf->dev_private; + if (buf->pid == 0) return buf; + } + + for (t = 0; t < dev_priv->usec_timeout; t++) { + u32 done_age = R128_READ(R128_VB_AGE_REG); + + for (i = 0; i < dma->buf_count; i++) { + buf = dma->buflist[i]; + buf_priv = buf->dev_private; + if (buf->pending && buf_priv->age <= done_age) { + /* The buffer has been processed, so it + can now be used */ + buf->pending = 0; + return buf; + } + } + udelay(1); + } + + return NULL; +} + + +static int r128_get_vertbufs(drm_device_t *dev, drm_r128_vertex_t *v) +{ + drm_buf_t *buf; + int i; + + for (i = v->granted_count; i < v->request_count; i++) { + buf = r128_freelist_get(dev); + if (!buf) break; + buf->pid = current->pid; + copy_to_user_ret(&v->request_indices[i], + &buf->idx, + sizeof(buf->idx), + -EFAULT); + copy_to_user_ret(&v->request_sizes[i], + &buf->total, + sizeof(buf->total), + -EFAULT); + ++v->granted_count; + } + return 0; +} + +int r128_vertex_buf(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_r128_private_t *dev_priv = dev->dev_private; + drm_device_dma_t *dma = dev->dma; + int retcode = 0; + drm_r128_vertex_t v; + + if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) || + dev->lock.pid != current->pid) { + DRM_ERROR("r128_vertex_buf called without holding the lock\n"); + return -EINVAL; + } + + if (!dev_priv || dev_priv->is_pci) { + DRM_ERROR("r128_vertex_buf called with a PCI card\n"); + return -EINVAL; + } + + copy_from_user_ret(&v, (drm_r128_vertex_t *)arg, sizeof(v), -EFAULT); + DRM_DEBUG("%d: %d send, %d req\n", + current->pid, v.send_count, v.request_count); + + if (v.send_count < 0 || v.send_count > dma->buf_count) { + DRM_ERROR("Process %d trying to send %d buffers (of %d max)\n", + current->pid, v.send_count, dma->buf_count); + return -EINVAL; + } + if (v.request_count < 0 || v.request_count > dma->buf_count) { + DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n", + current->pid, v.request_count, dma->buf_count); + return -EINVAL; + } + + if (v.send_count) { + retcode = r128_send_vertbufs(dev, &v); + } + + v.granted_count = 0; + + if (!retcode && v.request_count) { + retcode = r128_get_vertbufs(dev, &v); + } + + DRM_DEBUG("%d returning, granted = %d\n", + current->pid, v.granted_count); + copy_to_user_ret((drm_r128_vertex_t *)arg, &v, sizeof(v), -EFAULT); + + return retcode; +} diff --git a/linux/r128_drm.h b/linux/r128_drm.h new file mode 100644 index 00000000..fa90d72d --- /dev/null +++ b/linux/r128_drm.h @@ -0,0 +1,111 @@ +/* r128_drm.h -- Public header for the r128 driver -*- linux-c -*- + * Created: Wed Apr 5 19:24:19 2000 by kevin@precisioninsight.com + * + * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: Kevin E. Martin <kevin@precisioninsight.com> + * + * $XFree86$ + */ + +#ifndef _R128_DRM_H_ +#define _R128_DRM_H_ + +/* WARNING: If you change any of these defines, make sure to change the + * defines in the Xserver file (xf86drmR128.h) + */ +typedef struct drm_r128_init { + enum { + R128_INIT_CCE = 0x01, + R128_CLEANUP_CCE = 0x02 + } func; + int sarea_priv_offset; + int is_pci; + int cce_mode; + int cce_fifo_size; + int cce_secure; + int ring_size; + int usec_timeout; + + int fb_offset; + int agp_ring_offset; + int agp_read_ptr_offset; + int agp_vertbufs_offset; + int agp_indbufs_offset; + int agp_textures_offset; + int mmio_offset; +} drm_r128_init_t; + +typedef struct drm_r128_packet { + unsigned long *buffer; + int count; + int flags; +} drm_r128_packet_t; + +typedef enum drm_r128_prim { + _DRM_R128_PRIM_NONE = 0x0001, + _DRM_R128_PRIM_POINT = 0x0002, + _DRM_R128_PRIM_LINE = 0x0004, + _DRM_R128_PRIM_POLY_LINE = 0x0008, + _DRM_R128_PRIM_TRI_LIST = 0x0010, + _DRM_R128_PRIM_TRI_FAN = 0x0020, + _DRM_R128_PRIM_TRI_STRIP = 0x0040, + _DRM_R128_PRIM_TRI_TYPE2 = 0x0080 +} drm_r128_prim_t; + +typedef struct drm_r128_vertex { + /* Indices here refer to the offset into + buflist in drm_buf_get_t. */ + int send_count; /* Number of buffers to send */ + int *send_indices; /* List of handles to buffers */ + int *send_sizes; /* Lengths of data to send */ + drm_r128_prim_t prim; /* Primitive type */ + int request_count; /* Number of buffers requested */ + int *request_indices; /* Buffer information */ + int *request_sizes; + int granted_count; /* Number of buffers granted */ +} drm_r128_vertex_t; + +/* WARNING: If you change any of these defines, make sure to change the + * defines in the Xserver file (r128_sarea.h) + */ +#define R128_LOCAL_TEX_HEAP 0 +#define R128_AGP_TEX_HEAP 1 +#define R128_NR_TEX_HEAPS 2 +#define R128_NR_TEX_REGIONS 64 +#define R128_LOG_TEX_GRANULARITY 16 + +typedef struct drm_tex_region { + unsigned char next, prev; + unsigned char in_use; + int age; +} drm_tex_region_t; + +typedef struct drm_r128_sarea { + drm_tex_region_t tex_list[R128_NR_TEX_HEAPS][R128_NR_TEX_REGIONS+1]; + int tex_age[R128_NR_TEX_HEAPS]; + int ctx_owner; + int ring_write; +} drm_r128_sarea_t; + +#endif diff --git a/linux/r128_drv.c b/linux/r128_drv.c new file mode 100644 index 00000000..45ade1de --- /dev/null +++ b/linux/r128_drv.c @@ -0,0 +1,737 @@ +/* r128_drv.c -- ATI Rage 128 driver -*- linux-c -*- + * Created: Mon Dec 13 09:47:27 1999 by faith@precisioninsight.com + * + * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: Rickard E. (Rik) Faith <faith@precisioninsight.com> + * Kevin E. Martin <kevin@precisioninsight.com> + * + * $XFree86$ + * + */ + +#define EXPORT_SYMTAB +#include "drmP.h" +#include "r128_drv.h" +EXPORT_SYMBOL(r128_init); +EXPORT_SYMBOL(r128_cleanup); + +#define R128_NAME "r128" +#define R128_DESC "r128" +#define R128_DATE "20000422" +#define R128_MAJOR 0 +#define R128_MINOR 0 +#define R128_PATCHLEVEL 5 + +static drm_device_t r128_device; +drm_ctx_t r128_res_ctx; + +static struct file_operations r128_fops = { + open: r128_open, + flush: drm_flush, + release: r128_release, + ioctl: r128_ioctl, + mmap: drm_mmap, + read: drm_read, + fasync: drm_fasync, + poll: drm_poll, +}; + +static struct miscdevice r128_misc = { + minor: MISC_DYNAMIC_MINOR, + name: R128_NAME, + fops: &r128_fops, +}; + +static drm_ioctl_desc_t r128_ioctls[] = { + [DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = { r128_version, 0, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = { drm_getunique, 0, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] = { drm_getmagic, 0, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = { drm_irq_busid, 0, 1 }, + + [DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)] = { drm_setunique, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_BLOCK)] = { drm_block, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)] = { drm_unblock, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)] = { drm_authmagic, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] = { drm_addmap, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] = { r128_addbufs, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] = { drm_markbufs, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] = { drm_infobufs, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] = { r128_mapbufs, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] = { drm_freebufs, 1, 0 }, + + [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = { r128_addctx, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = { r128_rmctx, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = { r128_modctx, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = { r128_getctx, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = { r128_switchctx, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)] = { r128_newctx, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)] = { r128_resctx, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)] = { drm_adddraw, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)] = { drm_rmdraw, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_LOCK)] = { r128_lock, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)] = { r128_unlock, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_FINISH)] = { drm_finish, 1, 0 }, + +#ifdef DRM_AGP + [DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] = { drm_agp_acquire, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] = { drm_agp_release, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)] = { drm_agp_enable, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)] = { drm_agp_info, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)] = { drm_agp_alloc, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = { drm_agp_free, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = { drm_agp_bind, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { drm_agp_unbind, 1, 1 }, +#endif + + [DRM_IOCTL_NR(DRM_IOCTL_R128_INIT)] = { r128_init_cce, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_RESET)] = { r128_eng_reset, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_FLUSH)] = { r128_eng_flush, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_PACKET)] = { r128_submit_pkt, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_CCEIDL)] = { r128_cce_idle, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_VERTEX)] = { r128_vertex_buf, 1, 0 }, +}; +#define R128_IOCTL_COUNT DRM_ARRAY_SIZE(r128_ioctls) + +#ifdef MODULE +int init_module(void); +void cleanup_module(void); +static char *r128 = NULL; + +MODULE_AUTHOR("Precision Insight, Inc., Cedar Park, Texas."); +MODULE_DESCRIPTION("r128"); +MODULE_PARM(r128, "s"); + +/* init_module is called when insmod is used to load the module */ + +int init_module(void) +{ + return r128_init(); +} + +/* cleanup_module is called when rmmod is used to unload the module */ + +void cleanup_module(void) +{ + r128_cleanup(); +} +#endif + +#ifndef MODULE +/* r128_setup is called by the kernel to parse command-line options passed + * via the boot-loader (e.g., LILO). It calls the insmod option routine, + * drm_parse_drm. + * + * This is not currently supported, since it requires changes to + * linux/init/main.c. */ + + +void __init r128_setup(char *str, int *ints) +{ + if (ints[0] != 0) { + DRM_ERROR("Illegal command line format, ignored\n"); + return; + } + drm_parse_options(str); +} +#endif + +static int r128_setup(drm_device_t *dev) +{ + int i; + + atomic_set(&dev->ioctl_count, 0); + atomic_set(&dev->vma_count, 0); + dev->buf_use = 0; + atomic_set(&dev->buf_alloc, 0); + + drm_dma_setup(dev); + + atomic_set(&dev->total_open, 0); + atomic_set(&dev->total_close, 0); + atomic_set(&dev->total_ioctl, 0); + atomic_set(&dev->total_irq, 0); + atomic_set(&dev->total_ctx, 0); + atomic_set(&dev->total_locks, 0); + atomic_set(&dev->total_unlocks, 0); + atomic_set(&dev->total_contends, 0); + atomic_set(&dev->total_sleeps, 0); + + for (i = 0; i < DRM_HASH_SIZE; i++) { + dev->magiclist[i].head = NULL; + dev->magiclist[i].tail = NULL; + } + dev->maplist = NULL; + dev->map_count = 0; + dev->vmalist = NULL; + dev->lock.hw_lock = NULL; + init_waitqueue_head(&dev->lock.lock_queue); + dev->queue_count = 0; + dev->queue_reserved = 0; + dev->queue_slots = 0; + dev->queuelist = NULL; + dev->irq = 0; + dev->context_flag = 0; + dev->interrupt_flag = 0; + dev->dma_flag = 0; + dev->last_context = 0; + dev->last_switch = 0; + dev->last_checked = 0; + init_timer(&dev->timer); + init_waitqueue_head(&dev->context_wait); + + dev->ctx_start = 0; + dev->lck_start = 0; + + dev->buf_rp = dev->buf; + dev->buf_wp = dev->buf; + dev->buf_end = dev->buf + DRM_BSZ; + dev->buf_async = NULL; + init_waitqueue_head(&dev->buf_readers); + init_waitqueue_head(&dev->buf_writers); + + r128_res_ctx.handle=-1; + + DRM_DEBUG("\n"); + + /* The kernel's context could be created here, but is now created + in drm_dma_enqueue. This is more resource-efficient for + hardware that does not do DMA, but may mean that + drm_select_queue fails between the time the interrupt is + initialized and the time the queues are initialized. */ + + return 0; +} + + +static int r128_takedown(drm_device_t *dev) +{ + int i; + drm_magic_entry_t *pt, *next; + drm_map_t *map; + drm_vma_entry_t *vma, *vma_next; + + DRM_DEBUG("\n"); + + down(&dev->struct_sem); + del_timer(&dev->timer); + + if (dev->devname) { + drm_free(dev->devname, strlen(dev->devname)+1, DRM_MEM_DRIVER); + dev->devname = NULL; + } + + if (dev->unique) { + drm_free(dev->unique, strlen(dev->unique)+1, DRM_MEM_DRIVER); + dev->unique = NULL; + dev->unique_len = 0; + } + /* Clear pid list */ + for (i = 0; i < DRM_HASH_SIZE; i++) { + for (pt = dev->magiclist[i].head; pt; pt = next) { + next = pt->next; + drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC); + } + dev->magiclist[i].head = dev->magiclist[i].tail = NULL; + } + +#ifdef DRM_AGP + /* Clear AGP information */ + if (dev->agp) { + drm_agp_mem_t *entry; + drm_agp_mem_t *nexte; + + /* Remove AGP resources, but leave dev->agp + intact until r128_cleanup is called. */ + for (entry = dev->agp->memory; entry; entry = nexte) { + nexte = entry->next; + if (entry->bound) drm_unbind_agp(entry->memory); + drm_free_agp(entry->memory, entry->pages); + drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS); + } + dev->agp->memory = NULL; + + if (dev->agp->acquired && drm_agp.release) + (*drm_agp.release)(); + + dev->agp->acquired = 0; + dev->agp->enabled = 0; + } +#endif + + /* Clear vma list (only built for debugging) */ + if (dev->vmalist) { + for (vma = dev->vmalist; vma; vma = vma_next) { + vma_next = vma->next; + drm_free(vma, sizeof(*vma), DRM_MEM_VMAS); + } + dev->vmalist = NULL; + } + + /* Clear map area and mtrr information */ + if (dev->maplist) { + for (i = 0; i < dev->map_count; i++) { + map = dev->maplist[i]; + switch (map->type) { + case _DRM_REGISTERS: + case _DRM_FRAME_BUFFER: +#ifdef CONFIG_MTRR + if (map->mtrr >= 0) { + int retcode; + retcode = mtrr_del(map->mtrr, + map->offset, + map->size); + DRM_DEBUG("mtrr_del = %d\n", retcode); + } +#endif + drm_ioremapfree(map->handle, map->size); + break; + case _DRM_SHM: + drm_free_pages((unsigned long)map->handle, + drm_order(map->size) + - PAGE_SHIFT, + DRM_MEM_SAREA); + break; + case _DRM_AGP: + /* Do nothing here, because this is all + handled in the AGP/GART driver. */ + break; + } + drm_free(map, sizeof(*map), DRM_MEM_MAPS); + } + drm_free(dev->maplist, + dev->map_count * sizeof(*dev->maplist), + DRM_MEM_MAPS); + dev->maplist = NULL; + dev->map_count = 0; + } + + drm_dma_takedown(dev); + + dev->queue_count = 0; + if (dev->lock.hw_lock) { + dev->lock.hw_lock = NULL; /* SHM removed */ + dev->lock.pid = 0; + wake_up_interruptible(&dev->lock.lock_queue); + } + up(&dev->struct_sem); + + return 0; +} + +/* r128_init is called via init_module at module load time, or via + * linux/init/main.c (this is not currently supported). */ + +int r128_init(void) +{ + int retcode; + drm_device_t *dev = &r128_device; + + DRM_DEBUG("\n"); + + memset((void *)dev, 0, sizeof(*dev)); + dev->count_lock = SPIN_LOCK_UNLOCKED; + sema_init(&dev->struct_sem, 1); + +#ifdef MODULE + drm_parse_options(r128); +#endif + + if ((retcode = misc_register(&r128_misc))) { + DRM_ERROR("Cannot register \"%s\"\n", R128_NAME); + return retcode; + } + dev->device = MKDEV(MISC_MAJOR, r128_misc.minor); + dev->name = R128_NAME; + + drm_mem_init(); + drm_proc_init(dev); + +#ifdef DRM_AGP + dev->agp = drm_agp_init(); + +#ifdef CONFIG_MTRR + dev->agp->agp_mtrr = mtrr_add(dev->agp->agp_info.aper_base, + dev->agp->agp_info.aper_size*1024*1024, + MTRR_TYPE_WRCOMB, + 1); +#endif +#endif + + if((retcode = drm_ctxbitmap_init(dev))) { + DRM_ERROR("Cannot allocate memory for context bitmap.\n"); + drm_proc_cleanup(); + misc_deregister(&r128_misc); + r128_takedown(dev); + return retcode; + } + + DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", + R128_NAME, + R128_MAJOR, + R128_MINOR, + R128_PATCHLEVEL, + R128_DATE, + r128_misc.minor); + + return 0; +} + +/* r128_cleanup is called via cleanup_module at module unload time. */ + +void r128_cleanup(void) +{ + drm_device_t *dev = &r128_device; + + DRM_DEBUG("\n"); + + drm_proc_cleanup(); + if (misc_deregister(&r128_misc)) { + DRM_ERROR("Cannot unload module\n"); + } else { + DRM_INFO("Module unloaded\n"); + } + drm_ctxbitmap_cleanup(dev); + r128_takedown(dev); +#ifdef DRM_AGP + if (dev->agp) { + /* FIXME -- free other information, too */ + drm_free(dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS); + dev->agp = NULL; + } +#endif +} + +int r128_version(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg) +{ + drm_version_t version; + int len; + + copy_from_user_ret(&version, + (drm_version_t *)arg, + sizeof(version), + -EFAULT); + +#define DRM_COPY(name,value) \ + len = strlen(value); \ + if (len > name##_len) len = name##_len; \ + name##_len = strlen(value); \ + if (len && name) { \ + copy_to_user_ret(name, value, len, -EFAULT); \ + } + + version.version_major = R128_MAJOR; + version.version_minor = R128_MINOR; + version.version_patchlevel = R128_PATCHLEVEL; + + DRM_COPY(version.name, R128_NAME); + DRM_COPY(version.date, R128_DATE); + DRM_COPY(version.desc, R128_DESC); + + copy_to_user_ret((drm_version_t *)arg, + &version, + sizeof(version), + -EFAULT); + return 0; +} + +int r128_open(struct inode *inode, struct file *filp) +{ + drm_device_t *dev = &r128_device; + int retcode = 0; + + DRM_DEBUG("open_count = %d\n", dev->open_count); + if (!(retcode = drm_open_helper(inode, filp, dev))) { + MOD_INC_USE_COUNT; + atomic_inc(&dev->total_open); + spin_lock(&dev->count_lock); + if (!dev->open_count++) { + spin_unlock(&dev->count_lock); + return r128_setup(dev); + } + spin_unlock(&dev->count_lock); + } + return retcode; +} + +int r128_release(struct inode *inode, struct file *filp) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + int retcode = 0; + + DRM_DEBUG("open_count = %d\n", dev->open_count); + if (!(retcode = drm_release(inode, filp))) { + MOD_DEC_USE_COUNT; + atomic_inc(&dev->total_close); + spin_lock(&dev->count_lock); + if (!--dev->open_count) { + if (atomic_read(&dev->ioctl_count) || dev->blocked) { + DRM_ERROR("Device busy: %d %d\n", + atomic_read(&dev->ioctl_count), + dev->blocked); + spin_unlock(&dev->count_lock); + return -EBUSY; + } + spin_unlock(&dev->count_lock); + return r128_takedown(dev); + } + spin_unlock(&dev->count_lock); + } + return retcode; +} + +/* r128_ioctl is called whenever a process performs an ioctl on /dev/drm. */ + +int r128_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg) +{ + int nr = DRM_IOCTL_NR(cmd); + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + int retcode = 0; + drm_ioctl_desc_t *ioctl; + drm_ioctl_t *func; + + atomic_inc(&dev->ioctl_count); + atomic_inc(&dev->total_ioctl); + ++priv->ioctl_count; + + DRM_DEBUG("pid = %d, cmd = 0x%02x, nr = 0x%02x, dev 0x%x, auth = %d\n", + current->pid, cmd, nr, dev->device, priv->authenticated); + + if (nr >= R128_IOCTL_COUNT) { + retcode = -EINVAL; + } else { + ioctl = &r128_ioctls[nr]; + func = ioctl->func; + + if (!func) { + DRM_DEBUG("no function\n"); + retcode = -EINVAL; + } else if ((ioctl->root_only && !capable(CAP_SYS_ADMIN)) + || (ioctl->auth_needed && !priv->authenticated)) { + retcode = -EACCES; + } else { + retcode = (func)(inode, filp, cmd, arg); + } + } + + atomic_dec(&dev->ioctl_count); + return retcode; +} + +int r128_lock(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; + DECLARE_WAITQUEUE(entry, current); + int ret = 0; + drm_lock_t lock; +#if DRM_DMA_HISTOGRAM + cycles_t start; + + dev->lck_start = start = get_cycles(); +#endif + + copy_from_user_ret(&lock, (drm_lock_t *)arg, sizeof(lock), -EFAULT); + + if (lock.context == DRM_KERNEL_CONTEXT) { + DRM_ERROR("Process %d using kernel context %d\n", + current->pid, lock.context); + return -EINVAL; + } + + DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n", + lock.context, current->pid, dev->lock.hw_lock->lock, + lock.flags); + +#if 0 + /* dev->queue_count == 0 right now for + r128. FIXME? */ + if (lock.context < 0 || lock.context >= dev->queue_count) + return -EINVAL; +#endif + + if (!ret) { +#if 0 + if (_DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock) + != lock.context) { + long j = jiffies - dev->lock.lock_time; + + if (lock.context == r128_res_ctx.handle && + j >= 0 && j < DRM_LOCK_SLICE) { + /* Can't take lock if we just had it and + there is contention. */ + DRM_DEBUG("%d (pid %d) delayed j=%d dev=%d jiffies=%d\n", + lock.context, current->pid, j, + dev->lock.lock_time, jiffies); + current->state = TASK_INTERRUPTIBLE; + current->policy |= SCHED_YIELD; + schedule_timeout(DRM_LOCK_SLICE-j); + DRM_DEBUG("jiffies=%d\n", jiffies); + } + } +#endif + add_wait_queue(&dev->lock.lock_queue, &entry); + for (;;) { + if (!dev->lock.hw_lock) { + /* Device has been unregistered */ + ret = -EINTR; + break; + } + if (drm_lock_take(&dev->lock.hw_lock->lock, + lock.context)) { + dev->lock.pid = current->pid; + dev->lock.lock_time = jiffies; + atomic_inc(&dev->total_locks); + break; /* Got lock */ + } + + /* Contention */ + atomic_inc(&dev->total_sleeps); + current->state = TASK_INTERRUPTIBLE; +#if 1 + current->policy |= SCHED_YIELD; +#endif + schedule(); + if (signal_pending(current)) { + ret = -ERESTARTSYS; + break; + } + } + current->state = TASK_RUNNING; + remove_wait_queue(&dev->lock.lock_queue, &entry); + } + +#if 0 + if (!ret && dev->last_context != lock.context && + lock.context != r128_res_ctx.handle && + dev->last_context != r128_res_ctx.handle) { + add_wait_queue(&dev->context_wait, &entry); + current->state = TASK_INTERRUPTIBLE; + /* PRE: dev->last_context != lock.context */ + r128_context_switch(dev, dev->last_context, lock.context); + /* POST: we will wait for the context + switch and will dispatch on a later call + when dev->last_context == lock.context + NOTE WE HOLD THE LOCK THROUGHOUT THIS + TIME! */ + current->policy |= SCHED_YIELD; + schedule(); + current->state = TASK_RUNNING; + remove_wait_queue(&dev->context_wait, &entry); + if (signal_pending(current)) { + ret = -EINTR; + } else if (dev->last_context != lock.context) { + DRM_ERROR("Context mismatch: %d %d\n", + dev->last_context, lock.context); + } + } +#endif + + if (!ret) { + if (lock.flags & _DRM_LOCK_READY) { + /* Wait for space in DMA/FIFO */ + } + if (lock.flags & _DRM_LOCK_QUIESCENT) { + /* Make hardware quiescent */ +#if 0 + r128_quiescent(dev); +#endif + } + } + +#if 0 + DRM_ERROR("pid = %5d, old counter = %5ld\n", + current->pid, current->counter); +#endif + if (lock.context != r128_res_ctx.handle) { + current->counter = 5; + current->priority = DEF_PRIORITY/4; + } +#if 0 + while (current->counter > 25) + current->counter >>= 1; /* decrease time slice */ + DRM_ERROR("pid = %5d, new counter = %5ld\n", + current->pid, current->counter); +#endif + DRM_DEBUG("%d %s\n", lock.context, ret ? "interrupted" : "has lock"); + +#if DRM_DMA_HISTOGRAM + atomic_inc(&dev->histo.lacq[drm_histogram_slot(get_cycles() - start)]); +#endif + + return ret; +} + + +int r128_unlock(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_lock_t lock; + + copy_from_user_ret(&lock, (drm_lock_t *)arg, sizeof(lock), -EFAULT); + + if (lock.context == DRM_KERNEL_CONTEXT) { + DRM_ERROR("Process %d using kernel context %d\n", + current->pid, lock.context); + return -EINVAL; + } + + DRM_DEBUG("%d frees lock (%d holds)\n", + lock.context, + _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)); + atomic_inc(&dev->total_unlocks); + if (_DRM_LOCK_IS_CONT(dev->lock.hw_lock->lock)) + atomic_inc(&dev->total_contends); + drm_lock_transfer(dev, &dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT); + /* FIXME: Try to send data to card here */ + if (!dev->context_flag) { + if (drm_lock_free(dev, &dev->lock.hw_lock->lock, + DRM_KERNEL_CONTEXT)) { + DRM_ERROR("\n"); + } + } + +#if 0 + current->policy |= SCHED_YIELD; + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(1000); +#endif + + if (lock.context != r128_res_ctx.handle) { + current->counter = 5; + current->priority = DEF_PRIORITY; + } +#if 0 + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(10); +#endif + + return 0; +} diff --git a/linux/r128_drv.h b/linux/r128_drv.h new file mode 100644 index 00000000..3b888c49 --- /dev/null +++ b/linux/r128_drv.h @@ -0,0 +1,226 @@ +/* r128_drv.h -- Private header for r128 driver -*- linux-c -*- + * Created: Mon Dec 13 09:51:11 1999 by faith@precisioninsight.com + * + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: Rickard E. (Rik) Faith <faith@precisioninsight.com> + * Kevin E. Martin <kevin@precisioninsight.com> + * + * $XFree86$ + * + */ + +#ifndef _R128_DRV_H_ +#define _R128_DRV_H_ + +typedef struct drm_r128_private { + int is_pci; + + int cce_mode; + int cce_fifo_size; + int cce_is_bm_mode; + int cce_secure; + + drm_r128_sarea_t *sarea_priv; + + __volatile__ u32 *ring_read_ptr; + + u32 *ring_start; + u32 *ring_end; + int ring_size; + int ring_sizel2qw; + int ring_entries; + + int submit_age; + + int usec_timeout; + + drm_map_t *sarea; + drm_map_t *fb; + drm_map_t *agp_ring; + drm_map_t *agp_read_ptr; + drm_map_t *agp_vertbufs; + drm_map_t *agp_indbufs; + drm_map_t *agp_textures; + drm_map_t *mmio; +} drm_r128_private_t; + +typedef struct drm_r128_buf_priv { + u32 age; +} drm_r128_buf_priv_t; + + /* r128_drv.c */ +extern int r128_init(void); +extern void r128_cleanup(void); +extern int r128_version(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern int r128_open(struct inode *inode, struct file *filp); +extern int r128_release(struct inode *inode, struct file *filp); +extern int r128_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern int r128_lock(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern int r128_unlock(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); + + /* r128_dma.c */ +extern int r128_init_cce(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern int r128_eng_reset(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern int r128_eng_flush(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern int r128_submit_pkt(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern int r128_cce_idle(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern int r128_vertex_buf(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); + + /* r128_bufs.c */ +extern int r128_addbufs(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern int r128_mapbufs(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); + + /* r128_context.c */ +extern int r128_resctx(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern int r128_addctx(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern int r128_modctx(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern int r128_getctx(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern int r128_switchctx(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern int r128_newctx(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern int r128_rmctx(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); + +extern int r128_context_switch(drm_device_t *dev, int old, int new); +extern int r128_context_switch_complete(drm_device_t *dev, int new); + + +/* Register definitions, register access macros and drmAddMap constants + * for Rage 128 kernel driver. + */ + +#define R128_PC_NGUI_CTLSTAT 0x0184 +# define R128_PC_FLUSH_ALL 0x00ff +# define R128_PC_BUSY (1 << 31) + +#define R128_CLOCK_CNTL_INDEX 0x0008 +#define R128_CLOCK_CNTL_DATA 0x000c +# define R128_PLL_WR_EN (1 << 7) + +#define R128_MCLK_CNTL 0x000f +# define R128_FORCE_GCP (1 << 16) +# define R128_FORCE_PIPE3D_CPP (1 << 17) + +#define R128_GEN_RESET_CNTL 0x00f0 +# define R128_SOFT_RESET_GUI (1 << 0) + +#define R128_PM4_BUFFER_CNTL 0x0704 +# define R128_PM4_NONPM4 (0 << 28) +# define R128_PM4_192PIO (1 << 28) +# define R128_PM4_192BM (2 << 28) +# define R128_PM4_128PIO_64INDBM (3 << 28) +# define R128_PM4_128BM_64INDBM (4 << 28) +# define R128_PM4_64PIO_128INDBM (5 << 28) +# define R128_PM4_64BM_128INDBM (6 << 28) +# define R128_PM4_64PIO_64VCBM_64INDBM (7 << 28) +# define R128_PM4_64BM_64VCBM_64INDBM (8 << 28) +# define R128_PM4_64PIO_64VCPIO_64INDPIO (15 << 28) + + +#define R128_PM4_BUFFER_DL_RPTR 0x0710 +#define R128_PM4_BUFFER_DL_WPTR 0x0714 +# define R128_PM4_BUFFER_DL_DONE (1 << 31) + +#define R128_PM4_VC_FPU_SETUP 0x071c + +#define R128_PM4_STAT 0x07b8 +# define R128_PM4_FIFOCNT_MASK 0x0fff +# define R128_PM4_BUSY (1 << 16) +# define R128_PM4_GUI_ACTIVE (1 << 31) + +#define R128_PM4_BUFFER_ADDR 0x07f0 +#define R128_PM4_MICRO_CNTL 0x07fc +# define R128_PM4_MICRO_FREERUN (1 << 30) + +#define R128_PM4_FIFO_DATA_EVEN 0x1000 +#define R128_PM4_FIFO_DATA_ODD 0x1004 + +#define R128_GUI_SCRATCH_REG0 0x15e0 +#define R128_GUI_SCRATCH_REG1 0x15e4 +#define R128_GUI_SCRATCH_REG2 0x15e8 +#define R128_GUI_SCRATCH_REG3 0x15ec +#define R128_GUI_SCRATCH_REG4 0x15f0 +#define R128_GUI_SCRATCH_REG5 0x15f4 + +#define R128_GUI_STAT 0x1740 +# define R128_GUI_FIFOCNT_MASK 0x0fff +# define R128_GUI_ACTIVE (1 << 31) + + +/* CCE command packets */ +#define R128_CCE_PACKET0 0x00000000 +#define R128_CCE_PACKET1 0x40000000 +#define R128_CCE_PACKET2 0x80000000 +# define R128_CCE_PACKET_MASK 0xC0000000 +# define R128_CCE_PACKET_COUNT_MASK 0x3fff0000 +# define R128_CCE_PACKET0_REG_MASK 0x000007ff +# define R128_CCE_PACKET1_REG0_MASK 0x000007ff +# define R128_CCE_PACKET1_REG1_MASK 0x003ff800 + + +#define R128_MAX_USEC_TIMEOUT 100000 /* 100 ms */ + + +#define R128_BASE(reg) ((u32)(dev_priv->mmio->handle)) +#define R128_ADDR(reg) (R128_BASE(reg) + reg) + +#define R128_DEREF(reg) *(__volatile__ int *)R128_ADDR(reg) +#define R128_READ(reg) R128_DEREF(reg) +#define R128_WRITE(reg,val) do { R128_DEREF(reg) = val; } while (0) + +#define R128_DEREF8(reg) *(__volatile__ char *)R128_ADDR(reg) +#define R128_READ8(reg) R128_DEREF8(reg) +#define R128_WRITE8(reg,val) do { R128_DEREF8(reg) = val; } while (0) + +#define R128_WRITE_PLL(addr,val) \ +do { \ + R128_WRITE8(R128_CLOCK_CNTL_INDEX, ((addr) & 0x1f) | R128_PLL_WR_EN); \ + R128_WRITE(R128_CLOCK_CNTL_DATA, (val)); \ +} while (0) + +extern int R128_READ_PLL(drm_device_t *dev, int addr); + +#define R128CCE0(p,r,n) ((p) | ((n) << 16) | ((r) >> 2)) +#define R128CCE1(p,r1,r2) ((p) | (((r2) >> 2) << 11) | ((r1) >> 2)) +#define R128CCE2(p) ((p)) +#define R128CCE3(p,n) ((p) | ((n) << 16)) + +#endif @@ -1,8 +1,7 @@ /* vm.c -- Memory mapping for DRM -*- linux-c -*- * Created: Mon Jan 4 08:58:31 1999 by faith@precisioninsight.com - * Revised: Mon Feb 14 00:16:45 2000 by kevin@precisioninsight.com * - * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a @@ -246,6 +245,18 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma) /* Check for valid size. */ if (map->size != vma->vm_end - vma->vm_start) return -EINVAL; + if (!capable(CAP_SYS_ADMIN) && (map->flags & _DRM_READ_ONLY)) { + vma->vm_flags &= VM_MAYWRITE; +#if defined(__i386__) + pgprot_val(vma->vm_page_prot) &= ~_PAGE_RW; +#else + /* Ye gads this is ugly. With more thought + we could move this up higher and use + `protection_map' instead. */ + vma->vm_page_prot = __pgprot(pte_val(pte_wrprotect( + __pte(pgprot_val(vma->vm_page_prot))))); +#endif + } switch (map->type) { case _DRM_FRAME_BUFFER: @@ -265,6 +276,10 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma) vma->vm_end - vma->vm_start, vma->vm_page_prot)) return -EAGAIN; + DRM_DEBUG(" Type = %d; start = 0x%lx, end = 0x%lx," + " offset = 0x%lx\n", + map->type, + vma->vm_start, vma->vm_end, VM_OFFSET(vma)); vma->vm_ops = &drm_vm_ops; break; case _DRM_SHM: @@ -277,19 +292,7 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma) return -EINVAL; /* This should never happen. */ } vma->vm_flags |= VM_LOCKED | VM_SHM; /* Don't swap */ - if (map->flags & _DRM_READ_ONLY) { -#if defined(__i386__) - pgprot_val(vma->vm_page_prot) &= ~_PAGE_RW; -#else - /* Ye gads this is ugly. With more thought - we could move this up higher and use - `protection_map' instead. */ - vma->vm_page_prot = __pgprot(pte_val(pte_wrprotect( - __pte(pgprot_val(vma->vm_page_prot))))); -#endif - } - #if LINUX_VERSION_CODE < 0x020203 /* KERNEL_VERSION(2,2,3) */ /* In Linux 2.2.3 and above, this is handled in do_mmap() in mm/mmap.c. */ |