summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorfaith <faith>2000-01-09 17:12:27 +0000
committerfaith <faith>2000-01-09 17:12:27 +0000
commitb782d3c6ebe3bf5564f688a8fcbd4760aeada4f5 (patch)
tree0790e01e02d28cccf539dead5639edc79b6fe247
parent8ba7897413c97980ded22d4bf5276fcab8c07b56 (diff)
Get client-side CCE packets working via PIO
Bus mastering is still not working yet
-rw-r--r--xc/programs/Xserver/hw/xfree86/drivers/r128/r128_dri.c2
-rw-r--r--xc/programs/Xserver/hw/xfree86/drivers/r128/r128_reg.h67
-rw-r--r--xc/programs/Xserver/hw/xfree86/drivers/r128/testdri.c721
3 files changed, 635 insertions, 155 deletions
diff --git a/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_dri.c b/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_dri.c
index 0950b5503..3da419d25 100644
--- a/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_dri.c
+++ b/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_dri.c
@@ -244,7 +244,7 @@ static Bool R128DRIAgpInit(R128InfoPtr pR128, ScreenPtr pScreen)
return FALSE;
}
- pR128->agpSize = 64 * 1024; /* FIXME -- arbitrary */
+ pR128->agpSize = 16 * 1024; /* FIXME -- arbitrary */
if ((ret = drmAgpAlloc(pR128->drmFD,
pR128->agpSize, &pR128->agpMemHandle)) < 0) {
xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Out of memory (%d)\n", ret);
diff --git a/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_reg.h b/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_reg.h
index e5b7889b2..28b92e1c2 100644
--- a/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_reg.h
+++ b/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_reg.h
@@ -635,4 +635,71 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
#define R128_SCALE_3D_CNTL 0x1a00
+ /* Registers for CCE and Microcode Engine */
+#define R128_PM4_MICROCODE_ADDR 0x07d4
+#define R128_PM4_MICROCODE_RADDR 0x07d8
+#define R128_PM4_MICROCODE_DATAH 0x07dc
+#define R128_PM4_MICROCODE_DATAL 0x07e0
+
+#define R128_PM4_BUFFER_OFFSET 0x0700
+#define R128_PM4_BUFFER_CNTL 0x0704
+# define R128_PM4_NONPM4 (0 << 28)
+# define R128_PM4_192_DWORD_CCE_BM (2 << 28)
+#define R128_PM4_BUFFER_WM_CNTL 0x0708
+# define R128_WMA_SHIFT 0
+# define R128_WMB_SHIFT 8
+# define R128_WMC_SHIFT 16
+# define R128_WB_WM_SHIFT 24
+#define R128_PM4_BUFFER_DL_RPTR_ADDR 0x070c
+#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_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
+
+ /* CCE packet types */
+#define R128_CCE_PACKET1 0x40000000
+#define R128_CCE_PACKET2 0x80000000
+#define R128_CCE_PACKET3_NOP 0xC0001000
+#define R128_CCE_PACKET3_PAINT 0xC0001100
+#define R128_CCE_PACKET3_BITBLT 0xC0001200
+#define R128_CCE_PACKET3_SMALLTEXT 0xC0001300
+#define R128_CCE_PACKET3_HOSTDATA_BLT 0xC0001400
+#define R128_CCE_PACKET3_POLYLINE 0xC0001500
+#define R128_CCE_PACKET3_SCALING 0xC0001600
+#define R128_CCE_PACKET3_TRANS_SCALING 0xC0001700
+#define R128_CCE_PACKET3_POLYSCANLINES 0xC0001800
+#define R128_CCE_PACKET3_NEXT_CHAR 0xC0001900
+#define R128_CCE_PACKET3_PAINT_MULTI 0xC0001A00
+#define R128_CCE_PACKET3_BITBLT_MULTI 0xC0001B00
+#define R128_CCE_PACKET3_PLY_NEXTSCAN 0xC0001D00
+#define R128_CCE_PACKET3_SET_SCISSORS 0xC0001E00
+#define R128_CCE_PACKET3_SET_MODE24BPP 0xC0001F00
+#define R128_CCE_PACKET3_CNTL_PAINT 0xC0009100
+#define R128_CCE_PACKET3_CNTL_BITBLT 0xC0009200
+#define R128_CCE_PACKET3_CNTL_SMALLTEXT 0xC0009300
+#define R128_CCE_PACKET3_CNTL_HOSTDATA_BLT 0xC0009400
+#define R128_CCE_PACKET3_CNTL_POLYLINE 0xC0009500
+#define R128_CCE_PACKET3_CNTL_SCALING 0xC0009600
+#define R128_CCE_PACKET3_CNTL_TRANS_SCALING 0xC0009700
+#define R128_CCE_PACKET3_CNTL_POLYSCANLINES 0xC0009800
+#define R128_CCE_PACKET3_CNTL_NEXT_CHAR 0xC0009900
+#define R128_CCE_PACKET3_CNTL_PAINT_MULTI 0xC0009A00
+#define R128_CCE_PACKET3_CNTL_BITBLT_MULTI 0xC0009B00
+#define R128_CCE_PACKET3_CNTL_TRANS_BITBLT 0xC0009C00
+#define R128_CCE_PACKET3_3D_SAVE_CONTEXT 0xC0002000
+#define R128_CCE_PACKET3_3D_PLAY_CONTEXT 0xC0002100
+#define R128_CCE_PACKET3_3D_RNDR_GEN_INDX_PRIM 0xC0002300
+#define R128_CCE_PACKET3_3D_RNDR_GEN_PRIM 0xC0002500
+#define R128_CCE_PACKET3_LOAD_PALETTE 0xC0002C00
+#define R128_CCE_PACKET3_PURGE 0xC0002D00
+#define R128_CCE_PACKET3_NEXT_VERTEX_BUNDLE 0xC0002E00
+
#endif
diff --git a/xc/programs/Xserver/hw/xfree86/drivers/r128/testdri.c b/xc/programs/Xserver/hw/xfree86/drivers/r128/testdri.c
index f9037ef7a..6dd7319d9 100644
--- a/xc/programs/Xserver/hw/xfree86/drivers/r128/testdri.c
+++ b/xc/programs/Xserver/hw/xfree86/drivers/r128/testdri.c
@@ -41,6 +41,51 @@
#include <xf86dri.h>
#include <sarea.h>
#include "r128_dri.h"
+#include "r128_reg.h"
+
+#define R128_TIMEOUT 2000000
+#if 0
+#define R128_WATERMARK_L 16
+#define R128_WATERMARK_M 8
+#define R128_WATERMARK_N 8
+#define R128_WATERMARK_K 128
+#else
+#define R128_WATERMARK_L 2
+#define R128_WATERMARK_M 1
+#define R128_WATERMARK_N 1
+#define R128_WATERMARK_K 1
+#endif
+
+#define R128TRACE(x) printf x
+
+static int attrib[] = { GLX_RGBA,
+ GLX_RED_SIZE, 1,
+ GLX_GREEN_SIZE, 1,
+ GLX_BLUE_SIZE, 1,
+ GLX_DOUBLEBUFFER,
+ None };
+
+static struct {
+ int rop;
+ int pattern;
+} R128_ROP[] = {
+ { R128_ROP3_ZERO, R128_ROP3_ZERO }, /* GXclear */
+ { R128_ROP3_DSa, R128_ROP3_DPa }, /* Gxand */
+ { R128_ROP3_SDna, R128_ROP3_PDna }, /* GXandReverse */
+ { R128_ROP3_S, R128_ROP3_P }, /* GXcopy */
+ { R128_ROP3_DSna, R128_ROP3_DPna }, /* GXandInverted */
+ { R128_ROP3_D, R128_ROP3_D }, /* GXnoop */
+ { R128_ROP3_DSx, R128_ROP3_DPx }, /* GXxor */
+ { R128_ROP3_DSo, R128_ROP3_DPo }, /* GXor */
+ { R128_ROP3_DSon, R128_ROP3_DPon }, /* GXnor */
+ { R128_ROP3_DSxn, R128_ROP3_PDxn }, /* GXequiv */
+ { R128_ROP3_Dn, R128_ROP3_Dn }, /* GXinvert */
+ { R128_ROP3_SDno, R128_ROP3_PDno }, /* GXorReverse */
+ { R128_ROP3_Sn, R128_ROP3_Pn }, /* GXcopyInverted */
+ { R128_ROP3_DSno, R128_ROP3_DPno }, /* GXorInverted */
+ { R128_ROP3_DSan, R128_ROP3_DPan }, /* GXnand */
+ { R128_ROP3_ONE, R128_ROP3_ONE } /* GXset */
+};
static void usage(void)
{
@@ -66,6 +111,9 @@ typedef struct R128Client {
int privSize;
R128DRIPtr priv;
drmMagic magic;
+ unsigned long agpStart;
+ unsigned long ringSize;
+ int cceFifoSize;
/* Local information */
int fd;
@@ -73,6 +121,13 @@ typedef struct R128Client {
unsigned char *FB;
unsigned char *SAREA;
unsigned char *AGP;
+ Drawable drawable;
+ drmDrawable hHWDrawable;
+ XID context;
+ drmContext hHWContext;
+ int fifoSlots;
+ int cceFifoSlots;
+ int written; /* Write pointer -- needs to be in SAREA! */
} R128ClientRec, *R128ClientPtr;
static void cv(long retval, long failure, const char *message)
@@ -111,29 +166,502 @@ static void R128MapAllRegions(R128ClientPtr cr)
R128MapRegion(cr->fd, p->agpHandle, p->agpSize, &cr->AGP);
}
-int main(int argc, char **argv)
+/* Flush all dirty data in the Pixel Cache to memory. */
+static void R128EngineFlush(R128ClientPtr ct)
+{
+ unsigned char *R128MMIO = ct->REG;
+ int i;
+
+ R128TRACE((" R128EngineFlush\n"));
+ OUTREGP(R128_PC_NGUI_CTLSTAT, R128_PC_FLUSH_ALL, ~R128_PC_FLUSH_ALL);
+ for (i = 0; i < R128_TIMEOUT; i++) {
+ if (!(INREG(R128_PC_NGUI_CTLSTAT) & R128_PC_BUSY)) break;
+ }
+}
+
+static int INPLL(R128ClientPtr ct, int addr)
+{
+ unsigned char *R128MMIO = ct->REG;
+
+ OUTREG8(R128_CLOCK_CNTL_INDEX, addr & 0x1f);
+ return INREG(R128_CLOCK_CNTL_DATA);
+}
+
+/* Reset graphics card to known state. */
+static void R128EngineReset(R128ClientPtr cr)
+{
+ unsigned char *R128MMIO = cr->REG;
+ CARD32 clock_cntl_index;
+ CARD32 mclk_cntl;
+ CARD32 gen_reset_cntl;
+
+ R128TRACE((" R128EngineReset\n"));
+ R128EngineFlush(cr);
+
+ clock_cntl_index = INREG(R128_CLOCK_CNTL_INDEX);
+ mclk_cntl = INPLL(cr, R128_MCLK_CNTL);
+
+ OUTPLL(R128_MCLK_CNTL, mclk_cntl | R128_FORCE_GCP | R128_FORCE_PIPE3D_CPP);
+
+ gen_reset_cntl = INREG(R128_GEN_RESET_CNTL);
+
+ OUTREG(R128_GEN_RESET_CNTL, gen_reset_cntl | R128_SOFT_RESET_GUI);
+ INREG(R128_GEN_RESET_CNTL);
+ OUTREG(R128_GEN_RESET_CNTL, gen_reset_cntl & ~R128_SOFT_RESET_GUI);
+ INREG(R128_GEN_RESET_CNTL);
+
+ OUTPLL(R128_MCLK_CNTL, mclk_cntl);
+ OUTREG(R128_CLOCK_CNTL_INDEX, clock_cntl_index);
+ OUTREG(R128_GEN_RESET_CNTL, gen_reset_cntl);
+}
+
+#define R128WaitForFifo(cr, entries) \
+do { \
+ if (cr->fifoSlots < entries) R128WaitForFifoFunction(cr, entries); \
+ cr->fifoSlots -= entries; \
+} while (0)
+
+/* The FIFO has 64 slots. This routines waits until at least `entries' of
+ these slots are empty. */
+static void R128WaitForFifoFunction(R128ClientPtr cr, int entries)
+{
+ unsigned char *R128MMIO = cr->REG;
+ int i;
+
+ R128TRACE((" R128WaitForFifoFunction(%d)\n", entries));
+ for (;;) {
+ for (i = 0; i < R128_TIMEOUT; i++) {
+ cr->fifoSlots = INREG(R128_GUI_STAT) & R128_GUI_FIFOCNT_MASK;
+ if (cr->fifoSlots >= entries) return;
+ }
+ R128TRACE(("FIFO time out: %ld entries, stat=0x%08lx, probe=0x%08lx\n",
+ INREG(R128_GUI_STAT) & R128_GUI_FIFOCNT_MASK,
+ INREG(R128_GUI_STAT),
+ INREG(R128_GUI_PROBE)));
+ R128EngineReset(cr);
+ }
+}
+
+#define R128CCEWaitForFifo(cr, entries) \
+do { \
+ if (cr->cceFifoSlots < entries) R128WaitForFifoFunction(cr, entries); \
+ cr->cceFifoSlots -= entries; \
+} while (0)
+
+/* The FIFO has 64 slots. This routines waits until at least `entries' of
+ these slots are empty. */
+static void R128CCEWaitForFifoFunction(R128ClientPtr cr, int entries)
+{
+ unsigned char *R128MMIO = cr->REG;
+ int i;
+
+ R128TRACE((" R128CCEWaitForFifoFunction(%d)\n",entries));
+ for (;;) {
+ for (i = 0; i < R128_TIMEOUT; i++) {
+ cr->cceFifoSlots = INREG(R128_PM4_STAT) & R128_GUI_FIFOCNT_MASK;
+ if (cr->cceFifoSlots >= entries) return;
+ }
+ R128TRACE(("CCE FIFO time out: %ld entries, stat=0x%08lx\n",
+ INREG(R128_PM4_STAT) & R128_PM4_FIFOCNT_MASK,
+ INREG(R128_PM4_STAT)));
+ R128EngineReset(cr);
+ }
+}
+
+/* Wait for the graphics engine to be completely idle: the FIFO has
+ drained, the Pixel Cache is flushed, and the engine is idle. This is a
+ standard "sync" function that will make the hardware "quiescent". */
+static void R128WaitForIdle(R128ClientPtr cr)
+{
+ unsigned char *R128MMIO = cr->REG;
+ int i;
+
+ R128TRACE((" R128WaitForIdle\n"));
+ R128WaitForFifoFunction(cr, 64);
+
+ for (;;) {
+ for (i = 0; i < R128_TIMEOUT; i++) {
+ if (!(INREG(R128_GUI_STAT) & R128_GUI_ACTIVE)) {
+ R128EngineFlush(cr);
+ return;
+ }
+ }
+ R128TRACE(("Idle time out: %ld entries, stat=0x%08lx, probe=0x%08lx\n",
+ INREG(R128_GUI_STAT) & R128_GUI_FIFOCNT_MASK,
+ INREG(R128_GUI_STAT),
+ INREG(R128_GUI_PROBE)));
+ R128EngineReset(cr);
+ }
+}
+
+static void R128CCEWaitForIdle(R128ClientPtr cr)
+{
+ unsigned char *R128MMIO = cr->REG;
+ int i;
+
+ R128TRACE((" R128CCEWaitForIdle\n"));
+
+ R128CCEWaitForFifoFunction(cr, cr->cceFifoSize);
+
+ for (;;) {
+ for (i = 0; i < R128_TIMEOUT; i++) {
+ if (!(INREG(R128_PM4_STAT)
+ & (R128_PM4_BUSY | R128_PM4_GUI_ACTIVE))) {
+ R128EngineFlush(cr);
+ return;
+ }
+ }
+ R128TRACE(("CCE Idle time out: %ld entries, stat=0x%08lx\n",
+ INREG(R128_PM4_STAT) & R128_PM4_FIFOCNT_MASK,
+ INREG(R128_PM4_STAT)));
+ R128EngineReset(cr);
+ }
+}
+
+static void R128MicroLoad(R128ClientPtr cr)
+{
+ unsigned char *R128MMIO = cr->REG;
+ int i;
+ /* This microcode is from the
+ cce/inc/cceutil.h file included in the
+ September 1999 R128ddk1_tar.Z that ATI
+ released to the public. */
+ unsigned long R128Microcode[] = {
+ /* Tedz Special Microcode */
+ 0, 276838400, 0, 268449792, 2, 142, 2, 145, 0, 1076765731, 0, 1617039951,
+ 0, 774592877, 0, 1987540286, 0, 2307490946U, 0, 599558925, 0, 589505315, 0,
+ 596487092, 0, 589505315, 1, 11544576, 1, 206848, 1, 311296, 1, 198656, 2,
+ 912273422, 11, 262144, 0, 0, 1, 33559837, 1, 7438, 1, 14809, 1, 6615, 12,
+ 28, 1, 6614, 12, 28, 2, 23, 11, 18874368, 0, 16790922, 1, 409600, 9, 30, 1,
+ 147854772, 16, 420483072, 3, 8192, 0, 10240, 1, 198656, 1, 15630, 1, 51200,
+ 10, 34858, 9, 42, 1, 33559823, 2, 10276, 1, 15717, 1, 15718, 2, 43, 1,
+ 15936948, 1, 570480831, 1, 14715071, 12, 322123831, 1, 33953125, 12, 55, 1,
+ 33559908, 1, 15718, 2, 46, 4, 2099258, 1, 526336, 1, 442623, 4, 4194365, 1,
+ 509952, 1, 459007, 3, 0, 12, 92, 2, 46, 12, 176, 1, 15734, 1, 206848, 1,
+ 18432, 1, 133120, 1, 100670734, 1, 149504, 1, 165888, 1, 15975928, 1,
+ 1048576, 6, 3145806, 1, 15715, 16, 2150645232U, 2, 268449859, 2, 10307, 12,
+ 176, 1, 15734, 1, 15735, 1, 15630, 1, 15631, 1, 5253120, 6, 3145810, 16,
+ 2150645232U, 1, 15864, 2, 82, 1, 343310, 1, 1064207, 2, 3145813, 1, 15728,
+ 1, 7817, 1, 15729, 3, 15730, 12, 92, 2, 98, 1, 16168, 1, 16167, 1, 16002,
+ 1, 16008, 1, 15974, 1, 15975, 1, 15990, 1, 15976, 1, 15977, 1, 15980, 0,
+ 15981, 1, 10240, 1, 5253120, 1, 15720, 1, 198656, 6, 110, 1, 180224, 1,
+ 103824738, 2, 112, 2, 3145839, 0, 536885440, 1, 114880, 14, 125, 12,
+ 206975, 1, 33559995, 12, 198784, 0, 33570236, 1, 15803, 0, 15804, 3,
+ 294912, 1, 294912, 3, 442370, 1, 11544576, 0, 811612160, 1, 12593152, 1,
+ 11536384, 1, 14024704, 7, 310382726, 0, 10240, 1, 14796, 1, 14797, 1,
+ 14793, 1, 14794, 0, 14795, 1, 268679168, 1, 9437184, 1, 268449792, 1,
+ 198656, 1, 9452827, 1, 1075854602, 1, 1075854603, 1, 557056, 1, 114880, 14,
+ 159, 12, 198784, 1, 1109409213, 12, 198783, 1, 1107312059, 12, 198784, 1,
+ 1109409212, 2, 162, 1, 1075854781, 1, 1073757627, 1, 1075854780, 1, 540672,
+ 1, 10485760, 6, 3145894, 16, 274741248, 9, 168, 3, 4194304, 3, 4209949, 0,
+ 0, 0, 256, 14, 174, 1, 114857, 1, 33560007, 12, 176, 0, 10240, 1, 114858,
+ 1, 33560018, 1, 114857, 3, 33560007, 1, 16008, 1, 114874, 1, 33560360, 1,
+ 114875, 1, 33560154, 0, 15963, 0, 256, 0, 4096, 1, 409611, 9, 188, 0,
+ 10240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0
+ };
+
+ R128TRACE(("R128MicroLoad\n"));
+ R128WaitForIdle(cr);
+
+ OUTREG(R128_PM4_MICROCODE_ADDR, 0);
+ for (i = 0; i < 256; i += 1) {
+ OUTREG(R128_PM4_MICROCODE_DATAH, R128Microcode[i*2]);
+ OUTREG(R128_PM4_MICROCODE_DATAL, R128Microcode[i*2 + 1]);
+ }
+}
+
+/* Compute log base 2 of val. */
+static int R128Lg(int val)
+{
+ int bits;
+
+ if (!val) return 1;
+ for (bits = 0; val >>= 1;) ++bits;
+ return bits;
+}
+
+static void R128MicroInit(R128ClientPtr cr)
+{
+ unsigned char *R128MMIO = cr->REG;
+ volatile unsigned long addr;
+
+ R128TRACE(("R128MicroInit\n"));
+ /* The manual (p. 2) says this address is
+ in VM space. I hope that means
+ "virtual" with respect to the AGP
+ aperture. */
+ OUTREG(R128_PM4_BUFFER_OFFSET, cr->agpStart); /* address */
+ OUTREG(R128_PM4_BUFFER_DL_WPTR, 0); /* index */
+ OUTREG(R128_PM4_BUFFER_DL_RPTR, 0); /* index */
+ /* It seems like DL_RPTR_ADDR should be an
+ address that is not in the ring buffer?
+ This should probably be in the SAREA,
+ and we should pass a physical address
+ here. */
+ *(volatile long unsigned *)(cr->AGP + cr->agpStart + 8192) = 0;
+ OUTREG(R128_PM4_BUFFER_DL_RPTR_ADDR, cr->agpStart+8192); /* address */
+
+ /* Set watermark control */
+ OUTREG(R128_PM4_BUFFER_WM_CNTL,
+ ((R128_WATERMARK_L/4) << R128_WMA_SHIFT)
+ | ((R128_WATERMARK_M/4) << R128_WMB_SHIFT)
+ | ((R128_WATERMARK_N/4) << R128_WMC_SHIFT)
+ | ((R128_WATERMARK_K/64) << R128_WB_WM_SHIFT));
+
+ addr = INREG(R128_PM4_BUFFER_ADDR); /* Force read. Why? Because it's
+ in the manual... */
+ R128TRACE((" BUFFER_ADDR = 0x%08lx\n", addr));
+
+ R128CCEWaitForIdle(cr);
+ R128TRACE((" Idle\n"));
+}
+
+static void R128MicroStartBM(R128ClientPtr cr)
+{
+ unsigned char *R128MMIO = cr->REG;
+ volatile unsigned long addr;
+
+ R128TRACE(("R128MicroStartBM\n"));
+
+ R128WaitForIdle(cr); /* Wait for PIO FIFO to flush */
+
+ /* Set size of ring buffer */
+ R128TRACE((" %ld QWORDS => %d bits\n",
+ cr->ringSize/8, R128Lg(cr->ringSize/8)));
+ OUTREG(R128_PM4_BUFFER_CNTL, (R128Lg(cr->ringSize/8)
+ | R128_PM4_192_DWORD_CCE_BM));
+ addr = INREG(R128_PM4_BUFFER_ADDR); /* Force read. Why? Because it's
+ in the manual... */
+ R128TRACE((" BUFFER_ADDR = 0x%08lx\n", addr));
+
+ OUTREG(R128_PM4_MICRO_CNTL, R128_PM4_MICRO_FREERUN);
+}
+
+static void R128MicroStopBM(R128ClientPtr cr)
{
- int c;
- int verbose_flag = 0;
- R128ClientRec cr;
- int eventBase;
- int errorBase;
- int majorVersion;
- int minorVersion;
- int patchVersion;
- char *clientDriverName;
- int ret;
- Bool isDirect;
+ unsigned char *R128MMIO = cr->REG;
+
+ R128TRACE(("R128MicroStopBM\n"));
+
+ OUTREGP(R128_PM4_BUFFER_DL_WPTR,
+ R128_PM4_BUFFER_DL_DONE, ~R128_PM4_BUFFER_DL_DONE);
+ R128CCEWaitForIdle(cr); /* Wait for CCE FIFO to flush */
+ OUTREG(R128_PM4_MICRO_CNTL, 0);
+ OUTREG(R128_PM4_BUFFER_CNTL, R128_PM4_NONPM4);
+}
+
+static void do_prim(R128ClientPtr cr, int loops, int wait, int method,
+ int x, int y, int width, int height)
+{
+ unsigned char *R128MMIO = cr->REG;
+ unsigned long *area = (unsigned long *)(cr->AGP + cr->written);
+ Display *display = cr->display;
+ Window w;
+ int drawing = 1;
+ int expose = 0;
+ GC gc;
+ GC gc2;
+ XEvent e;
+ KeySym sym;
+ int i;
+ XVisualInfo *visinfo;
+ int ret;
+
+ if (!width || !height) {
+ printf("Illegal parameters: x = %d, y = %d, width = %d, height = %d\n",
+ x, y, width, height);
+ return;
+ }
+
+ w = XCreateSimpleWindow(display,
+ DefaultRootWindow(display),
+ x, y,
+ width, height,
+ 0,
+ WhitePixel(display, DefaultScreen(display)),
+ WhitePixel(display, DefaultScreen(display)));
+
+ gc = XCreateGC(display, w, 0, NULL);
+ XSetBackground(display, gc, BlackPixel(display, DefaultScreen(display)));
+ XSetForeground(display, gc, WhitePixel(display, DefaultScreen(display)));
+ XSetLineAttributes(display, gc, 1, LineSolid, CapRound, JoinRound);
+
+ gc2 = XCreateGC(display, w, 0, NULL);
+ XSetBackground(display, gc2, WhitePixel(display, DefaultScreen(display)));
+ XSetForeground(display, gc2, BlackPixel(display, DefaultScreen(display)));
+ XSetLineAttributes(display, gc2, 1, LineSolid, CapRound, JoinRound);
+
+ /* Initialize GL */
+ if (!(visinfo = glXChooseVisual(cr->display, cr->screen, attrib))) {
+ printf("Error: couldn't get an RGB, Double-buffered visual\n");
+ exit(1);
+ }
+ ret = XF86DRICreateDrawable(cr->display, cr->screen, (Drawable)w,
+ &cr->hHWDrawable);
+ printf("XF86DRICreateDrawable [%d]: %d\n",
+ ret, cr->hHWDrawable);
+
+ ret = XF86DRICreateContext(cr->display,
+ cr->screen,
+ visinfo->visual,
+ &cr->context,
+ &cr->hHWContext);
+ printf("XF86DRICreateContext [%d]: %d\n",
+ ret, cr->hHWContext);
+
+ /* Bring up window */
+ XSelectInput(display, w, ExposureMask|KeyPressMask);
+ XMapWindow(display, w);
+ XSync(display, False);
+ fflush(stdout);
- while ((c = getopt(argc, argv, "v" )) != EOF)
+ for (i = 0; !loops || i < loops; i++) {
+ if (XEventsQueued(display, QueuedAfterFlush)) {
+ XNextEvent(display, &e);
+ switch (e.type) {
+ case KeyPress:
+ sym = XKeycodeToKeysym(display, e.xkey.keycode, 0);
+ printf("Got `%c'\n", (char)sym);
+ switch (sym) {
+ case 'q': return;
+ case 'f': XFlush(display); break;
+ case 'd':
+ if (drawing) drawing = 0;
+ else ++drawing;
+ break;
+ }
+ break;
+ case Expose:
+ printf("Got expose\n"); /* so we can kill with xrefresh */
+ if (++expose > 1) return;
+ break;
+ default:
+ printf("Got event\n");
+ break;
+ }
+ }
+ if (drawing) {
+ int rect_x, rect_y, rect_w, rect_h;
+ int color;
+
+ rect_x = (random() / (double)RAND_MAX) * width;
+ rect_y = (random() / (double)RAND_MAX) * height;
+ rect_w = (random() / (double)RAND_MAX) * width/2;
+ rect_h = (random() / (double)RAND_MAX) * height/2;
+ if (rect_x+rect_w > width) rect_w = width - rect_x;
+ if (rect_y+rect_h > height) rect_y = height - rect_y;
+ color = (random() / (double)RAND_MAX) * 16777216;
+
+ switch (method) {
+ case 0:
+ XSetForeground(display, gc, color);
+ XFillRectangle(display, w, gc, rect_x, rect_y, rect_w, rect_h);
+ XFlush(display);
+ break;
+ case 1:
+ /* Make coordinates relative to origin */
+ rect_x += x;
+ rect_y += y;
+
+ DRM_LIGHT_LOCK(cr->fd, cr->SAREA, cr->hHWContext);
+ R128MicroStartBM(cr);
+
+ /* Set first byte to type and size. This
+ packet has 4 words following the header,
+ so set the size to 3.*/
+ *area++ = R128_CCE_PACKET3_CNTL_PAINT | (3 << 16);
+ *area++ = (R128_GMC_BRUSH_SOLID_COLOR
+ | R128_GMC_SRC_DATATYPE_COLOR
+ | (6 << 8) /* GMC_DST_DATATYPE (6=32bpp) */
+ | R128_ROP[3].pattern);
+ *area++ = color;
+ *area++ = rect_x | (rect_y << 16);
+ *area++ = (rect_x + rect_w) | ((rect_y + rect_h) << 16);
+ cr->written += 5 * 4; /* in bytes */
+ OUTREG(R128_PM4_BUFFER_DL_WPTR, cr->written / 4);
+
+ OUTREGP(R128_PM4_BUFFER_DL_WPTR,
+ R128_PM4_BUFFER_DL_DONE, ~R128_PM4_BUFFER_DL_DONE);
+ {
+ int i;
+
+ for (i = 0; i < 10; i++) {
+ R128TRACE((" %lx %ld %ld %ld\n",
+ INREG(R128_PM4_BUFFER_DL_RPTR_ADDR),
+ *(volatile long unsigned *)(cr->AGP
+ + cr->agpStart
+ + 8192),
+ INREG(R128_PM4_BUFFER_DL_RPTR),
+ INREG(R128_PM4_BUFFER_DL_WPTR) & 0xffff));
+ }
+
+ for (i = 0; i < 6; i++) {
+ R128TRACE((" %d 0x%08lx\n",
+ i,
+ *(volatile long unsigned *)(cr->AGP
+ + i * 4)));
+ }
+
+ for (i = 0; i < 10; i++) {
+ R128TRACE((" %lx %ld %ld %ld\n",
+ INREG(R128_PM4_BUFFER_DL_RPTR_ADDR),
+ *(volatile long unsigned *)(cr->AGP
+ + cr->agpStart
+ + 8192),
+ INREG(R128_PM4_BUFFER_DL_RPTR),
+ INREG(R128_PM4_BUFFER_DL_WPTR) & 0xffff));
+ }
+ }
+ /* Bah, that's not working. try PIO */
+ {
+ unsigned long *pt = (long unsigned *)cr->AGP;
+
+ OUTREG(R128_PM4_FIFO_DATA_EVEN, *pt++);
+ OUTREG(R128_PM4_FIFO_DATA_ODD, *pt++);
+ OUTREG(R128_PM4_FIFO_DATA_EVEN, *pt++);
+ OUTREG(R128_PM4_FIFO_DATA_ODD, *pt++);
+ OUTREG(R128_PM4_FIFO_DATA_EVEN, *pt++);
+ OUTREG(R128_PM4_FIFO_DATA_ODD, R128_CCE_PACKET2);
+ }
+ R128MicroStopBM(cr);
+ DRM_UNLOCK(cr->fd, cr->SAREA, cr->hHWContext);
+ break;
+ }
+ }
+ if (wait) sleep(wait);
+ }
+}
+
+int main(int argc, char **argv)
+{
+ int c;
+ int verbose_flag = 0;
+ R128ClientRec cr;
+ int eventBase;
+ int errorBase;
+ int majorVersion;
+ int minorVersion;
+ int patchVersion;
+ char *clientDriverName;
+ int ret;
+ Bool isDirect;
+ int loops = 1;
+ int wait = 10;
+ int method = 0;
+
+ while ((c = getopt(argc, argv, "vl:w:m" )) != EOF)
switch (c) {
- case 'v':
- ++verbose_flag;
- break;
- default:
- usage();
- break;
+ case 'v': ++verbose_flag; break;
+ case 'l': loops = atoi(optarg); break;
+ case 'w': wait = atoi(optarg); break;
+ case 'm': ++method; break;
+ default: usage(); break;
}
cr.display = XOpenDisplay(NULL);
@@ -205,142 +733,27 @@ int main(int argc, char **argv)
R128MapAllRegions(&cr);
-#if 0
- glintMapAllRegions(&XXXPrivate);
-
- if (primitive) {
- do_prim(&XXXPrivate, primitive,
- rect_x, rect_y, rect_width, rect_height,
- delay_flag, verbose_flag, loops,
- use_mx_flag, use_gamma_flag,
- term_flag, init_flag, startup_delay,
- dump_flag, dma_flags);
- } else {
- root = RootWindow( XXXPrivate.dpy, XXXPrivate.screen);
- visinfo = glXChooseVisual( XXXPrivate.dpy, XXXPrivate.screen, attrib);
- if (!visinfo) {
- printf("Error: couldn't get an RGB, Double-buffered visual\n");
- exit(1);
- }
-
- /* window attributes */
- attr.background_pixel = 0;
- attr.border_pixel = 0;
- attr.colormap = XCreateColormap( XXXPrivate.dpy, root,
- visinfo->visual, AllocNone);
- attr.event_mask = StructureNotifyMask | ExposureMask;
- mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
-
- win = XCreateWindow( XXXPrivate.dpy, root, 0, 0, 70, 70,
- 0, visinfo->depth, InputOutput,
- visinfo->visual, mask, &attr );
- XXXPrivate.drawable = (Drawable)win;
- return_val = XF86DRICreateDrawable(XXXPrivate.dpy, XXXPrivate.screen,
- (Drawable)win,
- &(XXXPrivate.hHWDrawable));
- printf("CreateDrawable: return_val=%d, hHWDrawable=%x\n",
- return_val, XXXPrivate.hHWDrawable);
-
- ctx = glXCreateContext( XXXPrivate.dpy, visinfo, NULL, True );
- return_val = XF86DRICreateContext(XXXPrivate.dpy, XXXPrivate.screen,
- visinfo->visual,
- &(XXXPrivate.context),
- &(XXXPrivate.hHWContext));
- printf("CreateContext: return_val=%d, hHWContext=%x\n",
- return_val, XXXPrivate.hHWContext);
-
- XMapWindow( XXXPrivate.dpy, win );
- XSync(XXXPrivate.dpy, 1);
- XXXPrivate.pClipRects = 0;
- DRM_LIGHT_LOCK(XXXPrivate.fd,XXXPrivate.pSAREA,XXXPrivate.hHWContext);
-#ifdef NOT_DONE
- /* This references
- *pXXXPriv->pDrawableEntry, which is
- currently uninitialized. */
- XXX_VALIDATE_DRAWABLE_INFO(&XXXPrivate);
-#else
- /* Perhaps this is better? */
- XXXUpdateDrawableInfo(&XXXPrivate);
-#endif
- DRM_UNLOCK(XXXPrivate.fd,XXXPrivate.pSAREA,XXXPrivate.hHWContext);
- XSync(XXXPrivate.dpy, 1);
-
-
- XSelectInput(XXXPrivate.dpy, win, ExposureMask|KeyPressMask);
-
- do {
- XNextEvent( XXXPrivate.dpy, &event );
-
- switch (event.type) {
- case Expose:
- /* Here's what a typical software fall back would do */
- {
- unsigned char *pFB = XXXPrivate.pFB;
- int fbStride = XXXPrivate.fbStride;
- XXXPrivPtr pXXXPriv = &XXXPrivate;
- int numClipRects;
- XF86DRIClipRectPtr pRect;
- unsigned int *pPixel;
- int winX, winY;
-
-
- DRM_LIGHT_LOCK(pXXXPriv->fd,pXXXPriv->pSAREA,pXXXPriv->hHWContext);
- XXX_VALIDATE_DRAWABLE_INFO(pXXXPriv);
-
- winX = pXXXPriv->X; winY=pXXXPriv->Y;
- numClipRects = pXXXPriv->numClipRects;
- printf("SWFallBack: numClipRects=%d\n", numClipRects);
- pRect = pXXXPriv->pClipRects;
- if (numClipRects) do {
-
- printf("SWFallBack: pRect: x1=%d, y1=%d, x2=%d, y2=%d\n",
- pRect->x1, pRect->y1, pRect->x2, pRect->y2);
- printf("\t winY=%d, winX=%d\n", winY, winX);
-
- /* do primitive
- * we'll just touch inside corners of clip region
- *
- * Assume depth 32
- */
- pPixel = (unsigned int *)(pFB +
- (pRect->y1)*fbStride + (pRect->x1)*4);
- *pPixel = 0xffffff;
- pPixel = (unsigned int *)(pFB +
- (pRect->y1)*fbStride + (pRect->x2-1)*4);
- *pPixel = 0xffffff;
- pPixel = (unsigned int *)(pFB +
- (pRect->y2-1)*fbStride + (pRect->x1)*4);
- *pPixel = 0xffffff;
- pPixel = (unsigned int *)(pFB +
- (pRect->y2-1)*fbStride + (pRect->x2-1)*4);
- *pPixel = 0xffffff;
-
- pRect++;
- } while(--numClipRects);
-
- DRM_UNLOCK(pXXXPriv->fd,pXXXPriv->pSAREA,pXXXPriv->hHWContext);
- }
- break;
- default: break;
- }
- } while (event.type != KeyPress);
-
- return_val = XF86DRIDestroyContext(XXXPrivate.dpy,
- XXXPrivate.screen,
- XXXPrivate.context);
- printf("DestroyContext: return_val=%d\n", return_val);
- glXDestroyContext( XXXPrivate.dpy, ctx);
-
- return_val = XF86DRIDestroyDrawable(XXXPrivate.dpy,
- XXXPrivate.screen,
- XXXPrivate.drawable);
- printf("DestroyDrawable: return_val=%d\n", return_val);
- XDestroyWindow( XXXPrivate.dpy, win);
- }
+ /* FIXME: we'll hardcode 0 for everything
+ for now, but the server should pass the
+ offsets to the client. */
+ cr.agpStart = 0;
+ cr.ringSize = 8 * 1024;
+ cr.cceFifoSize = 192;
+ cr.written = 0;
+
+ DRM_LIGHT_LOCK(cr.fd, cr.SAREA, cr.hHWContext);
+ cr.fifoSlots = 0; /* Reset when we get lock */
+ cr.cceFifoSlots = 0;
+ R128MicroLoad(&cr);
+ R128EngineReset(&cr);
+ R128MicroInit(&cr);
+ DRM_UNLOCK(cr.fd, cr.SAREA, cr.hHWContext);
+
+ do_prim(&cr, loops, wait, method, 200, 200, 200, 200);
- drmReturn = drmCloseSub(fd);
- printf("drmClose(generic): drmReturn=%d\n", drmReturn);
-#endif
+ /* Cleanup */
+ ret = drmClose(cr.fd);
+ printf("drmClose [%d]\n", ret);
ret = XF86DRICloseConnection(cr.display, cr.screen);
printf("XF86DRICloseConnection [%d]\n", ret);