fix GL_LINE_LOOP with drivers using own render pipeline stage (#12410, #13527)
[mesa.git] / src / mesa / drivers / dri / mga / mgaioctl.c
index fc53912af4c3d32fb2f7938b22211ad4ecd253e8..ff26b9475b9e9271aa1445c190062a2505e0331c 100644 (file)
  * 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.
+ */
+
+/**
+ * \file mgaioctl.c
+ * MGA IOCTL related wrapper functions.
  *
- * Authors:
- *    Keith Whitwell <keith@tungstengraphics.com>
- *    Gareth Hughes <gareth@valinux.com>
+ * \author Keith Whitwell <keith@tungstengraphics.com>
+ * \author Gareth Hughes <gareth@valinux.com>
  */
-/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgaioctl.c,v 1.16 2002/12/16 16:18:52 dawes Exp $ */
-#include <errno.h>
-#include <sched.h>
 
+#include <errno.h>
 #include "mtypes.h"
 #include "macros.h"
 #include "dd.h"
 #include "swrast/swrast.h"
 
 #include "mm.h"
+#include "drm.h"
+#include "mga_drm.h"
 #include "mgacontext.h"
 #include "mgadd.h"
 #include "mgastate.h"
 #include "mgavb.h"
 #include "mgaioctl.h"
 #include "mgatris.h"
-#include "mga_common.h"
 
 #include "vblank.h"
 
 
+static int
+mgaSetFence( mgaContextPtr mmesa, uint32_t * fence )
+{
+    int ret = ENOSYS;
+
+    if ( mmesa->driScreen->drm_version.minor >= 2 ) {
+       ret = drmCommandWriteRead( mmesa->driScreen->fd, DRM_MGA_SET_FENCE,
+                                  fence, sizeof( uint32_t ));
+       if (ret) {
+           fprintf(stderr, "drmMgaSetFence: %d\n", ret);
+           exit(1);
+       }
+    }
+
+    return ret;
+}
+
+
+static int
+mgaWaitFence( mgaContextPtr mmesa, uint32_t fence, uint32_t * curr_fence )
+{
+    int ret = ENOSYS;
+
+    if ( mmesa->driScreen->drm_version.minor >= 2 ) {
+       uint32_t temp = fence;
+       
+       ret = drmCommandWriteRead( mmesa->driScreen->fd,
+                                  DRM_MGA_WAIT_FENCE,
+                                  & temp, sizeof( uint32_t ));
+       if (ret) {
+          fprintf(stderr, "drmMgaSetFence: %d\n", ret);
+           exit(1);
+       }
+
+       if ( curr_fence ) {
+           *curr_fence = temp;
+       }
+    }
+
+    return ret;
+}
+
+
 static void mga_iload_dma_ioctl(mgaContextPtr mmesa,
                                unsigned long dest,
                                int length)
 {
    drmBufPtr buf = mmesa->iload_buffer;
-   drmMGAIload iload;
+   drm_mga_iload_t iload;
    int ret, i;
 
    if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL)
@@ -73,7 +119,7 @@ static void mga_iload_dma_ioctl(mgaContextPtr mmesa,
    i = 0;
    do {
       ret = drmCommandWrite( mmesa->driFd, DRM_MGA_ILOAD, 
-                             &iload, sizeof(drmMGAIload) );
+                             &iload, sizeof(iload) );
    } while ( ret == -EBUSY && i++ < DRM_MGA_IDLE_RETRY );
 
    if ( ret < 0 ) {
@@ -158,8 +204,7 @@ drmBufPtr mga_get_buffer_ioctl( mgaContextPtr mmesa )
 
 
 static void
-mgaDDClear( GLcontext *ctx, GLbitfield mask, GLboolean all,
-            GLint cx, GLint cy, GLint cw, GLint ch )
+mgaClear( GLcontext *ctx, GLbitfield mask )
 {
    mgaContextPtr mmesa = MGA_CONTEXT(ctx);
    __DRIdrawablePrivate *dPriv = mmesa->driDrawable;
@@ -171,39 +216,46 @@ mgaDDClear( GLcontext *ctx, GLbitfield mask, GLboolean all,
    int ret;
    int i;
    static int nrclears;
-   drmMGAClearRec clear;
+   drm_mga_clear_t clear;
+   GLint cx, cy, cw, ch;
 
    FLUSH_BATCH( mmesa );
 
-   if ( mask & DD_FRONT_LEFT_BIT ) {
+   if ( mask & BUFFER_BIT_FRONT_LEFT ) {
       flags |= MGA_FRONT;
       color_mask = mmesa->setup.plnwt;
-      mask &= ~DD_FRONT_LEFT_BIT;
+      mask &= ~BUFFER_BIT_FRONT_LEFT;
    }
 
-   if ( mask & DD_BACK_LEFT_BIT ) {
+   if ( mask & BUFFER_BIT_BACK_LEFT ) {
       flags |= MGA_BACK;
       color_mask = mmesa->setup.plnwt;
-      mask &= ~DD_BACK_LEFT_BIT;
+      mask &= ~BUFFER_BIT_BACK_LEFT;
    }
 
-   if ( (mask & DD_DEPTH_BIT) && ctx->Depth.Mask ) {
+   if ( (mask & BUFFER_BIT_DEPTH) && ctx->Depth.Mask ) {
       flags |= MGA_DEPTH;
       clear_depth = (mmesa->ClearDepth & mmesa->depth_clear_mask);
       depth_mask |= mmesa->depth_clear_mask;
-      mask &= ~DD_DEPTH_BIT;
+      mask &= ~BUFFER_BIT_DEPTH;
    }
 
-   if ( (mask & DD_STENCIL_BIT) && mmesa->hw_stencil ) {
+   if ( (mask & BUFFER_BIT_STENCIL) && mmesa->hw_stencil ) {
       flags |= MGA_DEPTH;
       clear_depth |= (ctx->Stencil.Clear & mmesa->stencil_clear_mask);
       depth_mask |= mmesa->stencil_clear_mask;
-      mask &= ~DD_STENCIL_BIT;
+      mask &= ~BUFFER_BIT_STENCIL;
    }
 
    if ( flags ) {
       LOCK_HARDWARE( mmesa );
 
+      /* compute region after locking: */
+      cx = ctx->DrawBuffer->_Xmin;
+      cy = ctx->DrawBuffer->_Ymin;
+      cw = ctx->DrawBuffer->_Xmax - cx;
+      ch = ctx->DrawBuffer->_Ymax - cy;
+
       if ( mmesa->dirty_cliprects )
         mgaUpdateRects( mmesa, (MGA_FRONT | MGA_BACK) );
 
@@ -219,11 +271,12 @@ mgaDDClear( GLcontext *ctx, GLbitfield mask, GLboolean all,
       for (i = 0 ; i < mmesa->numClipRects ; )
       {
         int nr = MIN2(i + MGA_NR_SAREA_CLIPRECTS, mmesa->numClipRects);
-        XF86DRIClipRectPtr box = mmesa->pClipRects;
-        XF86DRIClipRectPtr b = mmesa->sarea->boxes;
+        drm_clip_rect_t *box = mmesa->pClipRects;
+        drm_clip_rect_t *b = mmesa->sarea->boxes;
         int n = 0;
 
-        if (!all) {
+        if (cw != dPriv->w || ch != dPriv->h) {
+            /* clear subregion */
            for ( ; i < nr ; i++) {
               GLint x = box[i].x1;
               GLint y = box[i].y1;
@@ -245,8 +298,9 @@ mgaDDClear( GLcontext *ctx, GLbitfield mask, GLboolean all,
               n++;
            }
         } else {
+            /* clear whole window */
            for ( ; i < nr ; i++) {
-              *b++ = *(XF86DRIClipRectPtr)&box[i];
+              *b++ = box[i];
               n++;
            }
         }
@@ -265,7 +319,7 @@ mgaDDClear( GLcontext *ctx, GLbitfield mask, GLboolean all,
          clear.color_mask = color_mask;
          clear.depth_mask = depth_mask;
          ret = drmCommandWrite( mmesa->driFd, DRM_MGA_CLEAR,
-                                 &clear, sizeof(drmMGAClearRec));
+                                 &clear, sizeof(clear));
         if ( ret ) {
            fprintf( stderr, "send clear retcode = %d\n", ret );
            exit( 1 );
@@ -279,54 +333,86 @@ mgaDDClear( GLcontext *ctx, GLbitfield mask, GLboolean all,
    }
 
    if (mask) 
-      _swrast_Clear( ctx, mask, all, cx, cy, cw, ch );
+      _swrast_Clear( ctx, mask );
 }
 
 
+/**
+ * Wait for the previous frame of rendering has completed.
+ * 
+ * \param mmesa  Hardware context pointer.
+ *
+ * \bug
+ * The loop in this function should have some sort of a timeout mechanism.
+ *
+ * \warning
+ * This routine used to assume that the hardware lock was held on entry.  It
+ * now assumes that the lock is \b not held on entry.
+ */
+
 static void mgaWaitForFrameCompletion( mgaContextPtr mmesa )
 {
-   unsigned wait = 0;
-   GLuint last_frame, last_wrap;
-
-
-   last_frame = mmesa->sarea->last_frame.head;
-   last_wrap = mmesa->sarea->last_frame.wrap;
+    if ( mgaWaitFence( mmesa, mmesa->last_frame_fence, NULL ) == ENOSYS ) {
+       unsigned wait = 0;
+       GLuint last_frame;
+       GLuint last_wrap;
+
+
+       LOCK_HARDWARE( mmesa );
+       last_frame = mmesa->sarea->last_frame.head;
+       last_wrap = mmesa->sarea->last_frame.wrap;
+
+       /* The DMA routines in the kernel track a couple values in the SAREA
+        * that we use here.  The number of times that the primary DMA buffer
+        * has "wrapped" around is tracked in last_wrap.  In addition, the
+        * wrap count and the buffer position at the end of the last frame are
+        * stored in last_frame.wrap and last_frame.head.
+        * 
+        * By comparing the wrap counts and the current DMA pointer value
+        * (read directly from the hardware) to last_frame.head, we can
+        * determine when the graphics processor has processed all of the
+        * commands for the last frame.
+        * 
+        * In this case "last frame" means the frame of the *previous* swap-
+        * buffers call.  This is done to prevent queuing a second buffer swap
+        * before the previous swap is executed.
+        */
+       while ( 1 ) {
+           if ( last_wrap < mmesa->sarea->last_wrap ||
+                ( last_wrap == mmesa->sarea->last_wrap &&
+                  last_frame <= (MGA_READ( MGAREG_PRIMADDRESS ) -
+                                 mmesa->primary_offset) ) ) {
+               break;
+           }
+           if ( 0 ) {
+               wait++;
+               fprintf( stderr, "   last: head=0x%06x wrap=%d\n",
+                        last_frame, last_wrap );
+               fprintf( stderr, "   head: head=0x%06lx wrap=%d\n",
+                        (long)(MGA_READ( MGAREG_PRIMADDRESS ) - mmesa->primary_offset),
+                        mmesa->sarea->last_wrap );
+           }
+           UPDATE_LOCK( mmesa, DRM_LOCK_FLUSH );
 
-   /* FIXME: Add a timeout to this loop...
-    */
-   while ( 1 ) {
-      if ( last_wrap < mmesa->sarea->last_wrap ||
-          ( last_wrap == mmesa->sarea->last_wrap &&
-            last_frame <= (MGA_READ( MGAREG_PRIMADDRESS ) -
-                           mmesa->primary_offset) ) ) {
-        break;
-      }
-      if ( 0 ) {
-        wait++;
-        fprintf( stderr, "   last: head=0x%06x wrap=%d\n",
-                 last_frame, last_wrap );
-        fprintf( stderr, "   head: head=0x%06lx wrap=%d\n",
-                 (long)(MGA_READ( MGAREG_PRIMADDRESS ) - mmesa->primary_offset),
-                 mmesa->sarea->last_wrap );
-      }
-      UPDATE_LOCK( mmesa, DRM_LOCK_FLUSH );
+           UNLOCK_HARDWARE( mmesa );
+           DO_USLEEP( 1 );
+           LOCK_HARDWARE( mmesa );
+       }
+       if ( wait )
+         fprintf( stderr, "\n" );
 
-      UNLOCK_HARDWARE( mmesa );
-      DO_USLEEP( 1 );
-      LOCK_HARDWARE( mmesa );
-   }
-   if ( wait )
-      fprintf( stderr, "\n" );
+       UNLOCK_HARDWARE( mmesa );
+    }
 }
 
 
 /*
  * Copy the back buffer to the front buffer.
  */
-void mgaSwapBuffers( __DRIdrawablePrivate *dPriv )
+void mgaCopyBuffer( __DRIdrawablePrivate *dPriv )
 {
    mgaContextPtr mmesa;
-   XF86DRIClipRectPtr pbox;
+   drm_clip_rect_t *pbox;
    GLint nbox;
    GLint ret;
    GLint i;
@@ -341,14 +427,11 @@ void mgaSwapBuffers( __DRIdrawablePrivate *dPriv )
 
    FLUSH_BATCH( mmesa );
 
-   LOCK_HARDWARE( mmesa );
    mgaWaitForFrameCompletion( mmesa );
-   UNLOCK_HARDWARE( mmesa );
-   driWaitForVBlank( dPriv, & mmesa->vbl_seq, mmesa->vblank_flags,
-                    & missed_target );
+   driWaitForVBlank( dPriv, & missed_target );
    if ( missed_target ) {
       mmesa->swap_missed_count++;
-      (void) (*mmesa->get_ust)( & mmesa->swap_missed_ust );
+      (void) (*dri_interface->getUST)( & mmesa->swap_missed_ust );
    }
    LOCK_HARDWARE( mmesa );
 
@@ -364,7 +447,7 @@ void mgaSwapBuffers( __DRIdrawablePrivate *dPriv )
    for (i = 0 ; i < nbox ; )
    {
       int nr = MIN2(i + MGA_NR_SAREA_CLIPRECTS, dPriv->numClipRects);
-      XF86DRIClipRectPtr b = mmesa->sarea->boxes;
+      drm_clip_rect_t *b = mmesa->sarea->boxes;
 
       mmesa->sarea->nbox = nr - i;
 
@@ -381,34 +464,62 @@ void mgaSwapBuffers( __DRIdrawablePrivate *dPriv )
       }
    }
 
+   (void) mgaSetFence( mmesa, & mmesa->last_frame_fence );
    UNLOCK_HARDWARE( mmesa );
 
    mmesa->dirty |= MGA_UPLOAD_CLIPRECTS;
    mmesa->swap_count++;
-   (void) (*mmesa->get_ust)( & mmesa->swap_ust );
+   (void) (*dri_interface->getUST)( & mmesa->swap_ust );
 }
 
 
-/* This is overkill
+/**
+ * Implement the hardware-specific portion of \c glFinish.
+ *
+ * Flushes all pending commands to the hardware and wait for them to finish.
+ * 
+ * \param ctx  Context where the \c glFinish command was issued.
+ *
+ * \sa glFinish, mgaFlush, mgaFlushDMA
  */
-void mgaDDFinish( GLcontext *ctx  )
+static void mgaFinish( GLcontext *ctx  )
 {
-   mgaContextPtr mmesa = MGA_CONTEXT(ctx);
-
-   FLUSH_BATCH( mmesa );
-
-   if (1/*mmesa->sarea->last_quiescent != mmesa->sarea->last_enqueue*/) {
-      if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL)
-        fprintf(stderr, "mgaRegetLockQuiescent\n");
-
-      LOCK_HARDWARE( mmesa );
-      UPDATE_LOCK( mmesa, DRM_LOCK_QUIESCENT | DRM_LOCK_FLUSH );
-      UNLOCK_HARDWARE( mmesa );
-
-      mmesa->sarea->last_quiescent = mmesa->sarea->last_enqueue;
-   }
+    mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+    uint32_t  fence;
+
+
+    LOCK_HARDWARE( mmesa );
+    if ( mmesa->vertex_dma_buffer != NULL ) {
+       mgaFlushVerticesLocked( mmesa );
+    }
+
+    if ( mgaSetFence( mmesa, & fence ) == 0 ) {
+       UNLOCK_HARDWARE( mmesa );
+       (void) mgaWaitFence( mmesa, fence, NULL );
+    }
+    else {
+       if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL) {
+           fprintf(stderr, "mgaRegetLockQuiescent\n");
+       }
+
+       UPDATE_LOCK( mmesa, DRM_LOCK_QUIESCENT | DRM_LOCK_FLUSH );
+       UNLOCK_HARDWARE( mmesa );
+    }
 }
 
+
+/**
+ * Flush all commands upto at least a certain point to the hardware.
+ *
+ * \note
+ * The term "wait" in the name of this function is misleading.  It doesn't
+ * actually wait for anything.  It just makes sure that the commands have
+ * been flushed to the hardware.
+ *
+ * \warning
+ * As the name implies, this function assumes that the hardware lock is
+ * held on entry.
+ */
 void mgaWaitAgeLocked( mgaContextPtr mmesa, int age  )
 {
    if (GET_DISPATCH_AGE(mmesa) < age) {
@@ -417,21 +528,9 @@ void mgaWaitAgeLocked( mgaContextPtr mmesa, int age  )
 }
 
 
-void mgaWaitAge( mgaContextPtr mmesa, int age  )
-{
-   if (GET_DISPATCH_AGE(mmesa) < age) {
-      LOCK_HARDWARE(mmesa);
-      if (GET_DISPATCH_AGE(mmesa) < age) {
-        UPDATE_LOCK( mmesa, DRM_LOCK_FLUSH );
-      }
-      UNLOCK_HARDWARE(mmesa);
-   }
-}
-
-
-static GLboolean intersect_rect( XF86DRIClipRectPtr out,
-                                const XF86DRIClipRectPtr a,
-                                const XF86DRIClipRectPtr b )
+static GLboolean intersect_rect( drm_clip_rect_t *out,
+                                const drm_clip_rect_t *a,
+                                const drm_clip_rect_t *b )
 {
    *out = *a;
    if (b->x1 > out->x1) out->x1 = b->x1;
@@ -451,16 +550,13 @@ static void age_mmesa( mgaContextPtr mmesa, int age )
    if (mmesa->CurrentTexObj[1]) mmesa->CurrentTexObj[1]->age = age;
 }
 
-#ifdef __i386__
-static int __break_vertex = 0;
-#endif
 
 void mgaFlushVerticesLocked( mgaContextPtr mmesa )
 {
-   XF86DRIClipRectPtr pbox = mmesa->pClipRects;
+   drm_clip_rect_t *pbox = mmesa->pClipRects;
    int nbox = mmesa->numClipRects;
    drmBufPtr buffer = mmesa->vertex_dma_buffer;
-   drmMGAVertex vertex;
+   drm_mga_vertex_t vertex;
    int i;
 
    mmesa->vertex_dma_buffer = 0;
@@ -509,7 +605,7 @@ void mgaFlushVerticesLocked( mgaContextPtr mmesa )
       for (i = 0 ; i < nbox ; )
       {
         int nr = MIN2(i + MGA_NR_SAREA_CLIPRECTS, nbox);
-        XF86DRIClipRectPtr b = mmesa->sarea->boxes;
+        drm_clip_rect_t *b = mmesa->sarea->boxes;
         int discard = 0;
 
         if (mmesa->scissor) {
@@ -546,19 +642,12 @@ void mgaFlushVerticesLocked( mgaContextPtr mmesa )
          vertex.used = buffer->used;
          vertex.discard = discard;
          drmCommandWrite( mmesa->driFd, DRM_MGA_VERTEX,
-                          &vertex, sizeof(drmMGAVertex) );
+                          &vertex, sizeof(vertex) );
 
         age_mmesa(mmesa, mmesa->sarea->last_enqueue);
       }
    }
 
-   /* Do we really need to do this ? */
-#ifdef __i386__
-   if ( __break_vertex ) {
-      __asm__ __volatile__ ( "int $3" );
-   }
-#endif
-
    mmesa->dirty &= ~MGA_UPLOAD_CLIPRECTS;
 }
 
@@ -589,64 +678,46 @@ void mgaGetILoadBufferLocked( mgaContextPtr mmesa )
 {
    if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL)
       fprintf(stderr, "mgaGetIloadBuffer (buffer now %p)\n",
-          mmesa->iload_buffer);
+              (void *) mmesa->iload_buffer);
 
    mmesa->iload_buffer = mga_get_buffer_ioctl( mmesa );
 }
 
-drmBufPtr mgaGetBufferLocked( mgaContextPtr mmesa )
-{
-   return mga_get_buffer_ioctl( mmesa );
-}
-
-
 
-void mgaDDFlush( GLcontext *ctx )
+/**
+ * Implement the hardware-specific portion of \c glFlush.
+ *
+ * \param ctx  Context to be flushed.
+ *
+ * \sa glFlush, mgaFinish, mgaFlushDMA
+ */
+static void mgaFlush( GLcontext *ctx )
 {
-   mgaContextPtr mmesa = MGA_CONTEXT( ctx );
+    mgaContextPtr mmesa = MGA_CONTEXT( ctx );
 
 
-   FLUSH_BATCH( mmesa );
+    LOCK_HARDWARE( mmesa );
+    if ( mmesa->vertex_dma_buffer != NULL ) {
+       mgaFlushVerticesLocked( mmesa );
+    }
 
-   /* This may be called redundantly - dispatch_age may trail what
-    * has actually been sent and processed by the hardware.
-    */
-   if (1 || GET_DISPATCH_AGE( mmesa ) < mmesa->sarea->last_enqueue) {
-      LOCK_HARDWARE( mmesa );
-      UPDATE_LOCK( mmesa, DRM_LOCK_FLUSH );
-      UNLOCK_HARDWARE( mmesa );
-   }
+    UPDATE_LOCK( mmesa, DRM_LOCK_FLUSH );
+    UNLOCK_HARDWARE( mmesa );
 }
 
 
-
-
-void mgaReleaseBufLocked( mgaContextPtr mmesa, drmBufPtr buffer )
-{
-   drmMGAVertex vertex;
-
-   if (!buffer) return;
-
-   vertex.idx = buffer->idx;
-   vertex.used = 0;
-   vertex.discard = 1;
-   drmCommandWrite( mmesa->driFd, DRM_MGA_VERTEX, 
-                    &vertex, sizeof(drmMGAVertex) );
-}
-
 int mgaFlushDMA( int fd, drmLockFlags flags )
 {
-   drmMGALock lock;
+   drm_lock_t lock;
    int ret, i = 0;
 
-   memset( &lock, 0, sizeof(drmMGALock) );
+   memset( &lock, 0, sizeof(lock) );
 
-   if ( flags & DRM_LOCK_QUIESCENT )    lock.flags |= DRM_LOCK_QUIESCENT;
-   if ( flags & DRM_LOCK_FLUSH )        lock.flags |= DRM_LOCK_FLUSH;
-   if ( flags & DRM_LOCK_FLUSH_ALL )    lock.flags |= DRM_LOCK_FLUSH_ALL;
+   lock.flags = flags & (DRM_LOCK_QUIESCENT | DRM_LOCK_FLUSH 
+                        | DRM_LOCK_FLUSH_ALL);
 
    do {
-      ret = drmCommandWrite( fd, DRM_MGA_FLUSH, &lock, sizeof(drmMGALock) );
+      ret = drmCommandWrite( fd, DRM_MGA_FLUSH, &lock, sizeof(lock) );
    } while ( ret && errno == EBUSY && i++ < DRM_MGA_IDLE_RETRY );
 
    if ( ret == 0 )
@@ -660,7 +731,7 @@ int mgaFlushDMA( int fd, drmLockFlags flags )
       lock.flags &= ~(DRM_LOCK_FLUSH | DRM_LOCK_FLUSH_ALL);
 
       do {
-         ret = drmCommandWrite( fd, DRM_MGA_FLUSH, &lock, sizeof(drmMGALock) );
+         ret = drmCommandWrite( fd, DRM_MGA_FLUSH, &lock, sizeof(lock) );
       } while ( ret && errno == EBUSY && i++ < DRM_MGA_IDLE_RETRY );
    }
 
@@ -671,9 +742,9 @@ int mgaFlushDMA( int fd, drmLockFlags flags )
    }
 }
 
-void mgaDDInitIoctlFuncs( GLcontext *ctx )
+void mgaInitIoctlFuncs( struct dd_function_table *functions )
 {
-   ctx->Driver.Clear = mgaDDClear;
-   ctx->Driver.Flush = mgaDDFlush;
-   ctx->Driver.Finish = mgaDDFinish;
+   functions->Clear = mgaClear;
+   functions->Flush = mgaFlush;
+   functions->Finish = mgaFinish;
 }