summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Skeggs <[email protected]>2006-12-26 20:59:49 +1100
committerBen Skeggs <[email protected]>2006-12-26 21:36:15 +1100
commitc0a63d8e5e33b7fe3057e32f04c22969ac2adc1d (patch)
treea047c596952c18e1675a63dac0243c8afc8bf2c9
parentb8769f318ff9c2e4a74fbb1d4b058eb521e36dda (diff)
nouveau: Add notifier support functions
-rw-r--r--src/mesa/drivers/dri/nouveau/Makefile1
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_context.c1
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_context.h4
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_object.c14
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_object.h16
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_sync.c115
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_sync.h36
7 files changed, 179 insertions, 8 deletions
diff --git a/src/mesa/drivers/dri/nouveau/Makefile b/src/mesa/drivers/dri/nouveau/Makefile
index 1a76169156a..962978dc7fa 100644
--- a/src/mesa/drivers/dri/nouveau/Makefile
+++ b/src/mesa/drivers/dri/nouveau/Makefile
@@ -24,6 +24,7 @@ DRIVER_SOURCES = \
nouveau_shader_2.c \
nouveau_tex.c \
nouveau_swtcl.c \
+ nouveau_sync.c \
nv10_swtcl.c \
nv10_state.c \
nv20_state.c \
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_context.c b/src/mesa/drivers/dri/nouveau/nouveau_context.c
index ac940ac595f..7aca31d0d3e 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_context.c
+++ b/src/mesa/drivers/dri/nouveau/nouveau_context.c
@@ -222,6 +222,7 @@ GLboolean nouveauCreateContext( const __GLcontextModes *glVisual,
break;
}
+ nouveauSyncInitFuncs(ctx);
nmesa->hw_func.InitCard(nmesa);
nouveauInitState(ctx);
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_context.h b/src/mesa/drivers/dri/nouveau/nouveau_context.h
index ea28506b742..f54ac9a7c8d 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_context.h
+++ b/src/mesa/drivers/dri/nouveau/nouveau_context.h
@@ -40,6 +40,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "nouveau_state_cache.h"
#include "nouveau_buffers.h"
#include "nouveau_shader.h"
+#include "nouveau_sync.h"
#include "xmlconfig.h"
@@ -101,6 +102,9 @@ typedef struct nouveau_context {
uint64_t vram_phys;
uint64_t agp_phys;
+ /* Channel synchronisation */
+ nouveau_notifier *syncNotifier;
+
/* Additional hw-specific functions */
nouveau_hw_func hw_func;
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_object.c b/src/mesa/drivers/dri/nouveau/nouveau_object.c
index dda547c916e..cf7284d2d54 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_object.c
+++ b/src/mesa/drivers/dri/nouveau/nouveau_object.c
@@ -4,7 +4,7 @@
#include "nouveau_reg.h"
-static GLboolean nouveauCreateContextObject(nouveauContextPtr nmesa, int handle, int class, uint32_t flags, uint32_t dma_in, uint32_t dma_out, uint32_t dma_notifier)
+GLboolean nouveauCreateContextObject(nouveauContextPtr nmesa, int handle, int class, uint32_t flags, uint32_t dma_in, uint32_t dma_out, uint32_t dma_notifier)
{
drm_nouveau_object_init_t cto;
int ret;
@@ -20,12 +20,12 @@ static GLboolean nouveauCreateContextObject(nouveauContextPtr nmesa, int handle,
return ret == 0;
}
-static GLboolean nouveauCreateDmaObject(nouveauContextPtr nmesa,
- uint32_t handle,
- uint32_t offset,
- uint32_t size,
- int target,
- int access)
+GLboolean nouveauCreateDmaObject(nouveauContextPtr nmesa,
+ uint32_t handle,
+ uint32_t offset,
+ uint32_t size,
+ int target,
+ int access)
{
drm_nouveau_dma_object_init_t dma;
int ret;
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_object.h b/src/mesa/drivers/dri/nouveau/nouveau_object.h
index a49a39719ba..87f2dc9ae75 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_object.h
+++ b/src/mesa/drivers/dri/nouveau/nouveau_object.h
@@ -12,7 +12,8 @@ enum DMAObjects {
NvCtxSurf2D = 0x80000020,
NvImageBlit = 0x80000021,
NvDmaFB = 0xD0FB0001,
- NvDmaAGP = 0xD0AA0001
+ NvDmaAGP = 0xD0AA0001,
+ NvSyncNotify = 0xD0000001
};
enum DMASubchannel {
@@ -22,4 +23,17 @@ enum DMASubchannel {
};
extern void nouveauObjectOnSubchannel(nouveauContextPtr nmesa, int subchannel, int handle);
+
+extern GLboolean nouveauCreateContextObject(nouveauContextPtr nmesa,
+ int handle, int class,
+ uint32_t flags,
+ uint32_t dma_in,
+ uint32_t dma_out,
+ uint32_t dma_notifier);
+extern GLboolean nouveauCreateDmaObject(nouveauContextPtr nmesa,
+ uint32_t handle,
+ uint32_t offset,
+ uint32_t size,
+ int target,
+ int access);
#endif
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_sync.c b/src/mesa/drivers/dri/nouveau/nouveau_sync.c
new file mode 100644
index 00000000000..698f778c4bd
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nouveau_sync.c
@@ -0,0 +1,115 @@
+#include "vblank.h" /* for DO_USLEEP */
+
+#include "nouveau_context.h"
+#include "nouveau_buffers.h"
+#include "nouveau_object.h"
+#include "nouveau_fifo.h"
+#include "nouveau_reg.h"
+#include "nouveau_msg.h"
+#include "nouveau_sync.h"
+
+nouveau_notifier *
+nouveau_notifier_new(GLcontext *ctx, GLuint handle)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ nouveau_notifier *notifier;
+
+ notifier = CALLOC_STRUCT(nouveau_notifier_t);
+ if (!notifier)
+ return NULL;
+
+ notifier->mem = nouveau_mem_alloc(ctx, NOUVEAU_MEM_FB, 32, 0);
+ if (!notifier->mem) {
+ FREE(notifier);
+ return NULL;
+ }
+
+ if (!nouveauCreateDmaObject(nmesa, handle, notifier->mem->offset,
+ notifier->mem->size,
+ 0 /* NV_DMA_TARGET_FB */,
+ 0 /* NV_DMA_ACCESS_RW */)) {
+ nouveau_mem_free(ctx, notifier->mem);
+ FREE(notifier);
+ return NULL;
+ }
+
+ notifier->handle = handle;
+ return notifier;
+}
+
+void
+nouveau_notifier_destroy(GLcontext *ctx, nouveau_notifier *notifier)
+{
+ /*XXX: free DMA object.. */
+ nouveau_mem_free(ctx, notifier->mem);
+ FREE(notifier);
+}
+
+void
+nouveau_notifier_reset(nouveau_notifier *notifier)
+{
+ volatile GLuint *n = notifier->mem->map;
+
+ n[NV_NOTIFY_TIME_0 /4] = 0x00000000;
+ n[NV_NOTIFY_TIME_1 /4] = 0x00000000;
+ n[NV_NOTIFY_RETURN_VALUE/4] = 0x00000000;
+ n[NV_NOTIFY_STATE /4] = (NV_NOTIFY_STATE_STATUS_IN_PROCESS <<
+ NV_NOTIFY_STATE_STATUS_SHIFT);
+}
+
+GLboolean
+nouveau_notifier_wait_status(nouveau_notifier *notifier, GLuint status,
+ GLuint timeout)
+{
+ volatile GLuint *n = notifier->mem->map;
+ unsigned int time = 0;
+
+ while (time <= timeout) {
+ if (n[NV_NOTIFY_STATE] & NV_NOTIFY_STATE_ERROR_CODE_MASK) {
+ MESSAGE("Notifier returned error: 0x%04x\n",
+ n[NV_NOTIFY_STATE] &
+ NV_NOTIFY_STATE_ERROR_CODE_MASK);
+ return GL_FALSE;
+ }
+
+ if (((n[NV_NOTIFY_STATE] & NV_NOTIFY_STATE_STATUS_MASK) >>
+ NV_NOTIFY_STATE_STATUS_SHIFT) == status)
+ return GL_TRUE;
+
+ if (timeout) {
+ DO_USLEEP(1);
+ time++;
+ }
+ }
+
+ MESSAGE("Notifier timed out\n");
+ return GL_FALSE;
+}
+
+void
+nouveau_notifier_wait_nop(GLcontext *ctx, nouveau_notifier *notifier,
+ GLuint subc)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ GLboolean ret;
+
+ nouveau_notifier_reset(notifier);
+
+ BEGIN_RING_SIZE(subc, NV_NOTIFY, 1);
+ OUT_RING (NV_NOTIFY_STYLE_WRITE_ONLY);
+ BEGIN_RING_SIZE(subc, NV_NOP, 1);
+ OUT_RING (0);
+
+ ret = nouveau_notifier_wait_status(notifier,
+ NV_NOTIFY_STATE_STATUS_COMPLETED,
+ 0 /* no timeout */);
+ if (ret) MESSAGE("wait on notifier failed\n");
+}
+
+void nouveauSyncInitFuncs(GLcontext *ctx)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+
+ nmesa->syncNotifier = nouveau_notifier_new(ctx, NvSyncNotify);
+}
+
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_sync.h b/src/mesa/drivers/dri/nouveau/nouveau_sync.h
new file mode 100644
index 00000000000..b20c2565ca7
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nouveau_sync.h
@@ -0,0 +1,36 @@
+#ifndef __NOUVEAU_SYNC_H__
+#define __NOUVEAU_SYNC_H__
+
+#include "nouveau_buffers.h"
+
+#define NV_NOTIFY_TIME_0 0x00000000
+#define NV_NOTIFY_TIME_1 0x00000004
+#define NV_NOTIFY_RETURN_VALUE 0x00000008
+#define NV_NOTIFY_STATE 0x0000000C
+#define NV_NOTIFY_STATE_STATUS_MASK 0xFF000000
+#define NV_NOTIFY_STATE_STATUS_SHIFT 24
+#define NV_NOTIFY_STATE_STATUS_COMPLETED 0x00
+#define NV_NOTIFY_STATE_STATUS_IN_PROCESS 0x01
+#define NV_NOTIFY_STATE_ERROR_CODE_MASK 0x0000FFFF
+#define NV_NOTIFY_STATE_ERROR_CODE_SHIFT 0
+
+/* Methods that (hopefully) all objects have */
+#define NV_NOP 0x00000100
+#define NV_NOTIFY 0x00000104
+#define NV_NOTIFY_STYLE_WRITE_ONLY 0
+
+typedef struct nouveau_notifier_t {
+ GLuint handle;
+ nouveau_mem *mem;
+} nouveau_notifier;
+
+extern nouveau_notifier *nouveau_notifier_new(GLcontext *, GLuint handle);
+extern void nouveau_notifier_destroy(GLcontext *, nouveau_notifier *);
+extern void nouveau_notifier_reset(nouveau_notifier *);
+extern GLboolean nouveau_notifier_wait_status(nouveau_notifier *r,
+ GLuint status, GLuint timeout);
+extern void nouveau_notifier_wait_nop(GLcontext *ctx,
+ nouveau_notifier *, GLuint subc);
+
+extern void nouveauSyncInitFuncs(GLcontext *ctx);
+#endif