nouveau: Add notifier support functions
authorBen Skeggs <darktama@iinet.net.au>
Tue, 26 Dec 2006 09:59:49 +0000 (20:59 +1100)
committerBen Skeggs <darktama@iinet.net.au>
Tue, 26 Dec 2006 10:36:15 +0000 (21:36 +1100)
src/mesa/drivers/dri/nouveau/Makefile
src/mesa/drivers/dri/nouveau/nouveau_context.c
src/mesa/drivers/dri/nouveau/nouveau_context.h
src/mesa/drivers/dri/nouveau/nouveau_object.c
src/mesa/drivers/dri/nouveau/nouveau_object.h
src/mesa/drivers/dri/nouveau/nouveau_sync.c [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nouveau_sync.h [new file with mode: 0644]

index 1a76169..962978d 100644 (file)
@@ -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             \
index ac940ac..7aca31d 100644 (file)
@@ -222,6 +222,7 @@ GLboolean nouveauCreateContext( const __GLcontextModes *glVisual,
                        break;
        }
 
+       nouveauSyncInitFuncs(ctx);
        nmesa->hw_func.InitCard(nmesa);
         nouveauInitState(ctx);
 
index ea28506..f54ac9a 100644 (file)
@@ -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;
 
index dda547c..cf7284d 100644 (file)
@@ -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;
index a49a397..87f2dc9 100644 (file)
@@ -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 (file)
index 0000000..698f778
--- /dev/null
@@ -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 (file)
index 0000000..b20c256
--- /dev/null
@@ -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