<commit_before>/**
 * \file server/radeon_dri.c
 * \brief File to perform the device-specific initialization tasks typically
 * done in the X server.
 *
 * Here they are converted to run in the client (or perhaps a standalone
 * process), and to work with the frame buffer device rather than the X
 * server infrastructure.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>

#include "driver.h"
#include "drm.h"
#include "memops.h"

#include "radeon.h"
#include "radeon_dri.h"
#include "radeon_macros.h"
#include "radeon_reg.h"
#include "drm_sarea.h"

static size_t radeon_drm_page_size;

/**
 * \brief Wait for free FIFO entries.
 *
 * \param ctx display handle.
 * \param entries number of free entries to wait.
 *
 * It polls the free entries from the chip until it reaches the requested value
 * or a timeout (3000 tries) occurs. Aborts the program if the FIFO times out.
 */
static void RADEONWaitForFifo( const DRIDriverContext *ctx,
			       int entries )
{
   unsigned char *RADEONMMIO = ctx->MMIOAddress;
   int i;

   for (i = 0; i < 3000; i++) {
      int fifo_slots =
	 INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK;
      if (fifo_slots >= entries) return;
   }

   /* There are recoveries possible, but I haven't seen them work
    * in practice:
    */
   fprintf(stderr, "FIFO timed out: %d entries, stat=0x%08x\n",
	   INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK,
	   INREG(RADEON_RBBM_STATUS));
   exit(1);
}

/**
 * \brief Read a PLL register.
 *
 * \param ctx display handle.
 * \param addr PLL register index.
 *
 * \return value of the PLL register.
 */
static unsigned int RADEONINPLL( const DRIDriverContext *ctx, int addr)
{
    unsigned char *RADEONMMIO = ctx->MMIOAddress;
    unsigned int data;

    OUTREG8(RADEON_CLOCK_CNTL_INDEX, addr & 0x3f);
    data = INREG(RADEON_CLOCK_CNTL_DATA);

    return data;
}

/**
 * \brief Reset graphics card to known state.
 *
 * \param ctx display handle.
 *
 * Resets the values of several Radeon registers.
 */
static void RADEONEngineReset( const DRIDriverContext *ctx )
{
   unsigned char *RADEONMMIO = ctx->MMIOAddress;
   unsigned int clock_cntl_index;
   unsigned int mclk_cntl;
   unsigned int rbbm_soft_reset;
   unsigned int host_path_cntl;
   int i;

   OUTREGP(RADEON_RB2D_DSTCACHE_CTLSTAT,
	   RADEON_RB2D_DC_FLUSH_ALL,
	   ~RADEON_RB2D_DC_FLUSH_ALL);
   for (i = 0; i < 512; i++) {
      if (!(INREG(RADEON_RB2D_DSTCACHE_CTLSTAT) & RADEON_RB2D_DC_BUSY))
	 break;
   }

   clock_cntl_index = INREG(RADEON_CLOCK_CNTL_INDEX);

   mclk_cntl = INPLL(ctx, RADEON_MCLK_CNTL);
   OUTPLL(RADEON_MCLK_CNTL, (mclk_cntl |
			     RADEON_FORCEON_MCLKA |
			     RADEON_FORCEON_MCLKB |
			     RADEON_FORCEON_YCLKA |
			     RADEON_FORCEON_YCLKB |
			     RADEON_FORCEON_MC |
			     RADEON_FORCEON_AIC));

   /* Soft resetting HDP thru RBBM_SOFT_RESET register can cause some
    * unexpected behaviour on some machines.  Here we use
    * RADEON_HOST_PATH_CNTL to reset it.
    */
   host_path_cntl = INREG(RADEON_HOST_PATH_CNTL);
   rbbm_soft_reset = INREG(RADEON_RBBM_SOFT_RESET);

   OUTREG(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset |
				   RADEON_SOFT_RESET_CP |
				   RADEON_SOFT_RESET_HI |
				   RADEON_SOFT_RESET_SE |
				   RADEON_SOFT_RESET_RE |
				   RADEON_SOFT_RESET_PP |
				   RADEON_SOFT_RESET_E2 |
				   RADEON_SOFT_RESET_RB));
   INREG(RADEON_RBBM_SOFT_RESET);
   OUTREG(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset & 
				   (unsigned int) ~(RADEON_SOFT_RESET_CP |
						    RADEON_SOFT_RESET_HI |
						    RADEON_SOFT_RESET_SE |
						    RADEON_SOFT_RESET_RE |
						    RADEON_SOFT_RESET_PP |
						    RADEON_SOFT_RESET_E2 |
						    RADEON_SOFT_RESET_RB)));
   INREG(RADEON_RBBM_SOFT_RESET);

   OUTREG(RADEON_HOST_PATH_CNTL, host_path_cntl | RADEON_HDP_SOFT_RESET);
   INREG(RADEON_HOST_PATH_CNTL);
   OUTREG(RADEON_HOST_PATH_CNTL, host_path_cntl);

   OUTREG(RADEON_RBBM_SOFT_RESET, rbbm_soft_reset);

   OUTREG(RADEON_CLOCK_CNTL_INDEX, clock_cntl_index);
   OUTPLL(RADEON_MCLK_CNTL, mclk_cntl);
}

/**
 * \brief Restore the drawing engine.
 *
 * \param ctx display handle
 *
 * Resets the graphics card and sets initial values for several registers of
 * the card's drawing engine.
 *
 * Turns on the radeon command processor engine (i.e., the ringbuffer).
 */
static int RADEONEngineRestore( const DRIDriverContext *ctx )
{
   RADEONInfoPtr info = ctx->driverPrivate;
   unsigned char *RADEONMMIO = ctx->MMIOAddress;
   int pitch64, datatype, dp_gui_master_cntl, err;

   fprintf(stderr, "%s\n", __FUNCTION__);

   OUTREG(RADEON_RB3D_CNTL, 0);
   RADEONEngineReset( ctx );

   switch (ctx->bpp) {
   case 16: datatype = 4; break;
   case 32: datatype = 6; break;
   default: return 0;
   }

   dp_gui_master_cntl =
      ((datatype << RADEON_GMC_DST_DATATYPE_SHIFT)
       | RADEON_GMC_CLR_CMP_CNTL_DIS);

   pitch64 = ((ctx->shared.virtualWidth * (ctx->bpp / 8) + 0x3f)) >> 6;

   RADEONWaitForFifo(ctx, 1);
   OUTREG(RADEON_DEFAULT_OFFSET, ((INREG(RADEON_DEFAULT_OFFSET) & 0xC0000000)
				  | (pitch64 << 22)));

   RADEONWaitForFifo(ctx, 1);
   OUTREG(RADEON_SURFACE_CNTL, RADEON_SURF_TRANSLATION_DIS); 

   RADEONWaitForFifo(ctx, 1);
   OUTREG(RADEON_DEFAULT_SC_BOTTOM_RIGHT, (RADEON_DEFAULT_SC_RIGHT_MAX
					   | RADEON_DEFAULT_SC_BOTTOM_MAX));

   RADEONWaitForFifo(ctx, 1);
   OUTREG(RADEON_DP_GUI_MASTER_CNTL, (dp_gui_master_cntl
				      | RADEON_GMC_BRUSH_SOLID_COLOR
				      | RADEON_GMC_SRC_DATATYPE_COLOR));

   RADEONWaitForFifo(ctx, 7);
   OUTREG(RADEON_DST_LINE_START,    0);
   OUTREG(RADEON_DST_LINE_END,      0);
   OUTREG(RADEON_DP_BRUSH_FRGD_CLR, 0xffffffff);
   OUTREG(RADEON_DP_BRUSH_BKGD_CLR, 0);
   OUTREG(RADEON_DP_SRC_FRGD_CLR,   0xffffffff);
   OUTREG(RADEON_DP_SRC_BKGD_CLR,   0);
   OUTREG(RADEON_DP_WRITE_MASK,     0xffffffff);
   OUTREG(RADEON_AUX_SC_CNTL,       0);

/*    RADEONWaitForIdleMMIO(ctx); */
   usleep(100); 


   OUTREG(RADEON_GEN_INT_CNTL, info->gen_int_cntl);
   OUTREG(RADEON_CRTC_OFFSET_CNTL, info->crtc_offset_cntl);

   /* Initialize and start the CP if required */
   if ((err = drmCommandNone(ctx->drmFD, DRM_RADEON_CP_START)) != 0) {
      fprintf(stderr, "%s: CP start %d\n", __FUNCTION__, err);
      return 0;
   }

   return 1;
}


/**
 * \brief Shutdown the drawing engine.
 *
 * \param ctx display handle
 *
 * Turns off the command processor engine & restores the graphics card
 * to a state that fbdev understands.
 */
static int RADEONEngineShutdown( const DRIDriverContext *ctx )
{
   drm_radeon_cp_stop_t  stop;
   int              ret, i;

   stop.flush = 1;
   stop.idle  = 1;

   ret = drmCommandWrite(ctx->drmFD, DRM_RADEON_CP_STOP, &stop, 
			 sizeof(drm_radeon_cp_stop_t));

   if (ret == 0) {
      return 0;
   } else if (errno != EBUSY) {
      return -errno;
   }

   stop.flush = 0;
 
   i = 0;
   do {
      ret = drmCommandWrite(ctx->drmFD, DRM_RADEON_CP_STOP, &stop, 
			    sizeof(drm_radeon_cp_stop_t));
   } while (ret && errno == EBUSY && i++ < 10);

   if (ret == 0) {
      return 0;
   } else if (errno != EBUSY) {
      return -errno;
   }

   stop.idle = 0;

   if (drmCommandWrite(ctx->drmFD, DRM_RADEON_CP_STOP,
		       &stop, sizeof(drm_radeon_cp_stop_t))) {
      return -errno;
   } else {
      return 0;
   }
}

/**
 * \brief Compute base 2 logarithm.
 *
 * \param val value.
 * 
 * \return base 2 logarithm of \p val.
 */
static int RADEONMinBits(int val)
{
   int  bits;

   if (!val) return 1;
   for (bits = 0; val; val >>= 1, ++bits);
   return bits;
}

/**
 * \brief Initialize the AGP state
 *
 * \param ctx display handle.
 * \param info driver private data.
 *
 * \return one on success, or zero on failure.
 * 
 * Acquires and enables the AGP device. Reserves memory in the AGP space for
 * the ring buffer, vertex buffers and textures. Initialize the Radeon
 * registers to point to that memory and add client mappings.
 */
static int RADEONDRIAgpInit( const DRIDriverContext *ctx, RADEONInfoPtr info)
{
   unsigned char *RADEONMMIO = ctx->MMIOAddress;
   unsigned long  mode;
   int            ret;
   int            s, l;

   if (drmAgpAcquire(ctx->drmFD) < 0) {
      fprintf(stderr, "[gart] AGP not available\n");
      return 0;
   }
    
   /* Modify the mode if the default mode is not appropriate for this
    * particular combination of graphics card and AGP chipset.
    */
   mode   = drmAgpGetMode(ctx->drmFD);	/* Default mode */

   /* Disable fast write entirely - too many lockups.
    */
   mode &= ~RADEON_AGP_MODE_MASK;
   switch (ctx->agpmode) {
   case 4:          mode |= RADEON_AGP_4X_MODE;
   case 2:          mode |= RADEON_AGP_2X_MODE;
   case 1: default: mode |= RADEON_AGP_1X_MODE;
   }

   if (drmAgpEnable(ctx->drmFD, mode) < 0) {
      fprintf(stderr, "[gart] AGP not enabled\n");
      drmAgpRelease(ctx->drmFD);
      return 0;
   }
   else
     fprintf(stderr, "[gart] AGP enabled at %dx\n", ctx->agpmode);

   /* Workaround for some hardware bugs */
   if (info->ChipFamily < CHIP_FAMILY_R200)
      OUTREG(RADEON_AGP_CNTL, INREG(RADEON_AGP_CNTL) | 0x000e0000);

   info->gartOffset = 0;

   if ((ret = drmAgpAlloc(ctx->drmFD, info->gartSize*1024*1024, 0, NULL,
			  &info->gartMemHandle)) < 0) {
      fprintf(stderr, "[gart] Out of memory (%d)\n", ret);
      drmAgpRelease(ctx->drmFD);
      return 0;
   }
   fprintf(stderr,
	   "[gart] %d kB allocated with handle 0x%08x\n",
	   info->gartSize*1024, (unsigned)info->gartMemHandle);
    
   if (drmAgpBind(ctx->drmFD,
		  info->gartMemHandle, info->gartOffset) < 0) {
      fprintf(stderr, "[gart] Could not bind\n");
      drmAgpFree(ctx->drmFD, info->gartMemHandle);
      drmAgpRelease(ctx->drmFD);
      return 0;
   }

   /* Initialize the CP ring buffer data */
   info->ringStart       = info->gartOffset;
   info->ringMapSize     = info->ringSize*1024*1024 + radeon_drm_page_size;

   info->ringReadOffset  = info->ringStart + info->ringMapSize;
   info->ringReadMapSize = radeon_drm_page_size;

   /* Reserve space for vertex/indirect buffers */
   info->bufStart        = info->ringReadOffset + info->ringReadMapSize;
   info->bufMapSize      = info->bufSize*1024*1024;

   /* Reserve the rest for AGP textures */
   info->gartTexStart     = info->bufStart + info->bufMapSize;
   s = (info->gartSize*1024*1024 - info->gartTexStart);
   l = RADEONMinBits((s-1) / RADEON_NR_TEX_REGIONS);
   if (l < RADEON_LOG_TEX_GRANULARITY) l = RADEON_LOG_TEX_GRANULARITY;
   info->gartTexMapSize   = (s >> l) << l;
   info->log2GARTTexGran  = l;

   if (drmAddMap(ctx->drmFD, info->ringStart, info->ringMapSize,
		 DRM_AGP, DRM_READ_ONLY, &info->ringHandle) < 0) {
      fprintf(stderr, "[gart] Could not add ring mapping\n");
      return 0;
   }
   fprintf(stderr, "[gart] ring handle = 0x%08lx\n", info->ringHandle);
    

   if (drmAddMap(ctx->drmFD, info->ringReadOffset, info->ringReadMapSize,
		 DRM_AGP, DRM_READ_ONLY, &info->ringReadPtrHandle) < 0) {
      fprintf(stderr,
	      "[gart] Could not add ring read ptr mapping\n");
      return 0;
   }
    
   fprintf(stderr,
	   "[gart] ring read ptr handle = 0x%08lx\n",
	   info->ringReadPtrHandle);
    
   if (drmAddMap(ctx->drmFD, info->bufStart, info->bufMapSize,
		 DRM_AGP, 0, &info->bufHandle) < 0) {
      fprintf(stderr,
	      "[gart] Could not add vertex/indirect buffers mapping\n");
      return 0;
   }
   fprintf(stderr,
	   "[gart] vertex/indirect buffers handle = 0x%08lx\n",
	   info->bufHandle);

   if (drmAddMap(ctx->drmFD, info->gartTexStart, info->gartTexMapSize,
		 DRM_AGP, 0, &info->gartTexHandle) < 0) {
      fprintf(stderr,
	      "[gart] Could not add AGP texture map mapping\n");
      return 0;
   }
   fprintf(stderr,
	   "[gart] AGP texture map handle = 0x%08lx\n",
	   info->gartTexHandle);

   /* Initialize Radeon's AGP registers */
   /* Ring buffer is at AGP offset 0 */
   OUTREG(RADEON_AGP_BASE, info->ringHandle);

   return 1;
}

/* Initialize the PCI GART state.  Request memory for use in PCI space,
 * and initialize the Radeon registers to point to that memory.
 */
static int RADEONDRIPciInit(const DRIDriverContext *ctx, RADEONInfoPtr info)
{
    int  ret;
    int  flags = DRM_READ_ONLY | DRM_LOCKED | DRM_KERNEL;
    int            s, l;

    ret = drmScatterGatherAlloc(ctx->drmFD, info->gartSize*1024*1024,
				&info->gartMemHandle);
    if (ret < 0) {
	fprintf(stderr, "[pci] Out of memory (%d)\n", ret);
	return 0;
    }
    fprintf(stderr,
	       "[pci] %d kB allocated with handle 0x%08x\n",
	       info->gartSize*1024, info->gartMemHandle);

   info->gartOffset = 0;<commit_msg>Remove OUTREG(RADEON_AGP_BASE, info->ringHandle); from DRI driver Code is already in DRM driver to do this.<commit_after>/**
 * \file server/radeon_dri.c
 * \brief File to perform the device-specific initialization tasks typically
 * done in the X server.
 *
 * Here they are converted to run in the client (or perhaps a standalone
 * process), and to work with the frame buffer device rather than the X
 * server infrastructure.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>

#include "driver.h"
#include "drm.h"
#include "memops.h"

#include "radeon.h"
#include "radeon_dri.h"
#include "radeon_macros.h"
#include "radeon_reg.h"
#include "drm_sarea.h"

static size_t radeon_drm_page_size;

/**
 * \brief Wait for free FIFO entries.
 *
 * \param ctx display handle.
 * \param entries number of free entries to wait.
 *
 * It polls the free entries from the chip until it reaches the requested value
 * or a timeout (3000 tries) occurs. Aborts the program if the FIFO times out.
 */
static void RADEONWaitForFifo( const DRIDriverContext *ctx,
			       int entries )
{
   unsigned char *RADEONMMIO = ctx->MMIOAddress;
   int i;

   for (i = 0; i < 3000; i++) {
      int fifo_slots =
	 INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK;
      if (fifo_slots >= entries) return;
   }

   /* There are recoveries possible, but I haven't seen them work
    * in practice:
    */
   fprintf(stderr, "FIFO timed out: %d entries, stat=0x%08x\n",
	   INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK,
	   INREG(RADEON_RBBM_STATUS));
   exit(1);
}

/**
 * \brief Read a PLL register.
 *
 * \param ctx display handle.
 * \param addr PLL register index.
 *
 * \return value of the PLL register.
 */
static unsigned int RADEONINPLL( const DRIDriverContext *ctx, int addr)
{
    unsigned char *RADEONMMIO = ctx->MMIOAddress;
    unsigned int data;

    OUTREG8(RADEON_CLOCK_CNTL_INDEX, addr & 0x3f);
    data = INREG(RADEON_CLOCK_CNTL_DATA);

    return data;
}

/**
 * \brief Reset graphics card to known state.
 *
 * \param ctx display handle.
 *
 * Resets the values of several Radeon registers.
 */
static void RADEONEngineReset( const DRIDriverContext *ctx )
{
   unsigned char *RADEONMMIO = ctx->MMIOAddress;
   unsigned int clock_cntl_index;
   unsigned int mclk_cntl;
   unsigned int rbbm_soft_reset;
   unsigned int host_path_cntl;
   int i;

   OUTREGP(RADEON_RB2D_DSTCACHE_CTLSTAT,
	   RADEON_RB2D_DC_FLUSH_ALL,
	   ~RADEON_RB2D_DC_FLUSH_ALL);
   for (i = 0; i < 512; i++) {
      if (!(INREG(RADEON_RB2D_DSTCACHE_CTLSTAT) & RADEON_RB2D_DC_BUSY))
	 break;
   }

   clock_cntl_index = INREG(RADEON_CLOCK_CNTL_INDEX);

   mclk_cntl = INPLL(ctx, RADEON_MCLK_CNTL);
   OUTPLL(RADEON_MCLK_CNTL, (mclk_cntl |
			     RADEON_FORCEON_MCLKA |
			     RADEON_FORCEON_MCLKB |
			     RADEON_FORCEON_YCLKA |
			     RADEON_FORCEON_YCLKB |
			     RADEON_FORCEON_MC |
			     RADEON_FORCEON_AIC));

   /* Soft resetting HDP thru RBBM_SOFT_RESET register can cause some
    * unexpected behaviour on some machines.  Here we use
    * RADEON_HOST_PATH_CNTL to reset it.
    */
   host_path_cntl = INREG(RADEON_HOST_PATH_CNTL);
   rbbm_soft_reset = INREG(RADEON_RBBM_SOFT_RESET);

   OUTREG(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset |
				   RADEON_SOFT_RESET_CP |
				   RADEON_SOFT_RESET_HI |
				   RADEON_SOFT_RESET_SE |
				   RADEON_SOFT_RESET_RE |
				   RADEON_SOFT_RESET_PP |
				   RADEON_SOFT_RESET_E2 |
				   RADEON_SOFT_RESET_RB));
   INREG(RADEON_RBBM_SOFT_RESET);
   OUTREG(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset & 
				   (unsigned int) ~(RADEON_SOFT_RESET_CP |
						    RADEON_SOFT_RESET_HI |
						    RADEON_SOFT_RESET_SE |
						    RADEON_SOFT_RESET_RE |
						    RADEON_SOFT_RESET_PP |
						    RADEON_SOFT_RESET_E2 |
						    RADEON_SOFT_RESET_RB)));
   INREG(RADEON_RBBM_SOFT_RESET);

   OUTREG(RADEON_HOST_PATH_CNTL, host_path_cntl | RADEON_HDP_SOFT_RESET);
   INREG(RADEON_HOST_PATH_CNTL);
   OUTREG(RADEON_HOST_PATH_CNTL, host_path_cntl);

   OUTREG(RADEON_RBBM_SOFT_RESET, rbbm_soft_reset);

   OUTREG(RADEON_CLOCK_CNTL_INDEX, clock_cntl_index);
   OUTPLL(RADEON_MCLK_CNTL, mclk_cntl);
}

/**
 * \brief Restore the drawing engine.
 *
 * \param ctx display handle
 *
 * Resets the graphics card and sets initial values for several registers of
 * the card's drawing engine.
 *
 * Turns on the radeon command processor engine (i.e., the ringbuffer).
 */
static int RADEONEngineRestore( const DRIDriverContext *ctx )
{
   RADEONInfoPtr info = ctx->driverPrivate;
   unsigned char *RADEONMMIO = ctx->MMIOAddress;
   int pitch64, datatype, dp_gui_master_cntl, err;

   fprintf(stderr, "%s\n", __FUNCTION__);

   OUTREG(RADEON_RB3D_CNTL, 0);
   RADEONEngineReset( ctx );

   switch (ctx->bpp) {
   case 16: datatype = 4; break;
   case 32: datatype = 6; break;
   default: return 0;
   }

   dp_gui_master_cntl =
      ((datatype << RADEON_GMC_DST_DATATYPE_SHIFT)
       | RADEON_GMC_CLR_CMP_CNTL_DIS);

   pitch64 = ((ctx->shared.virtualWidth * (ctx->bpp / 8) + 0x3f)) >> 6;

   RADEONWaitForFifo(ctx, 1);
   OUTREG(RADEON_DEFAULT_OFFSET, ((INREG(RADEON_DEFAULT_OFFSET) & 0xC0000000)
				  | (pitch64 << 22)));

   RADEONWaitForFifo(ctx, 1);
   OUTREG(RADEON_SURFACE_CNTL, RADEON_SURF_TRANSLATION_DIS); 

   RADEONWaitForFifo(ctx, 1);
   OUTREG(RADEON_DEFAULT_SC_BOTTOM_RIGHT, (RADEON_DEFAULT_SC_RIGHT_MAX
					   | RADEON_DEFAULT_SC_BOTTOM_MAX));

   RADEONWaitForFifo(ctx, 1);
   OUTREG(RADEON_DP_GUI_MASTER_CNTL, (dp_gui_master_cntl
				      | RADEON_GMC_BRUSH_SOLID_COLOR
				      | RADEON_GMC_SRC_DATATYPE_COLOR));

   RADEONWaitForFifo(ctx, 7);
   OUTREG(RADEON_DST_LINE_START,    0);
   OUTREG(RADEON_DST_LINE_END,      0);
   OUTREG(RADEON_DP_BRUSH_FRGD_CLR, 0xffffffff);
   OUTREG(RADEON_DP_BRUSH_BKGD_CLR, 0);
   OUTREG(RADEON_DP_SRC_FRGD_CLR,   0xffffffff);
   OUTREG(RADEON_DP_SRC_BKGD_CLR,   0);
   OUTREG(RADEON_DP_WRITE_MASK,     0xffffffff);
   OUTREG(RADEON_AUX_SC_CNTL,       0);

/*    RADEONWaitForIdleMMIO(ctx); */
   usleep(100); 


   OUTREG(RADEON_GEN_INT_CNTL, info->gen_int_cntl);
   OUTREG(RADEON_CRTC_OFFSET_CNTL, info->crtc_offset_cntl);

   /* Initialize and start the CP if required */
   if ((err = drmCommandNone(ctx->drmFD, DRM_RADEON_CP_START)) != 0) {
      fprintf(stderr, "%s: CP start %d\n", __FUNCTION__, err);
      return 0;
   }

   return 1;
}


/**
 * \brief Shutdown the drawing engine.
 *
 * \param ctx display handle
 *
 * Turns off the command processor engine & restores the graphics card
 * to a state that fbdev understands.
 */
static int RADEONEngineShutdown( const DRIDriverContext *ctx )
{
   drm_radeon_cp_stop_t  stop;
   int              ret, i;

   stop.flush = 1;
   stop.idle  = 1;

   ret = drmCommandWrite(ctx->drmFD, DRM_RADEON_CP_STOP, &stop, 
			 sizeof(drm_radeon_cp_stop_t));

   if (ret == 0) {
      return 0;
   } else if (errno != EBUSY) {
      return -errno;
   }

   stop.flush = 0;
 
   i = 0;
   do {
      ret = drmCommandWrite(ctx->drmFD, DRM_RADEON_CP_STOP, &stop, 
			    sizeof(drm_radeon_cp_stop_t));
   } while (ret && errno == EBUSY && i++ < 10);

   if (ret == 0) {
      return 0;
   } else if (errno != EBUSY) {
      return -errno;
   }

   stop.idle = 0;

   if (drmCommandWrite(ctx->drmFD, DRM_RADEON_CP_STOP,
		       &stop, sizeof(drm_radeon_cp_stop_t))) {
      return -errno;
   } else {
      return 0;
   }
}

/**
 * \brief Compute base 2 logarithm.
 *
 * \param val value.
 * 
 * \return base 2 logarithm of \p val.
 */
static int RADEONMinBits(int val)
{
   int  bits;

   if (!val) return 1;
   for (bits = 0; val; val >>= 1, ++bits);
   return bits;
}

/**
 * \brief Initialize the AGP state
 *
 * \param ctx display handle.
 * \param info driver private data.
 *
 * \return one on success, or zero on failure.
 * 
 * Acquires and enables the AGP device. Reserves memory in the AGP space for
 * the ring buffer, vertex buffers and textures. Initialize the Radeon
 * registers to point to that memory and add client mappings.
 */
static int RADEONDRIAgpInit( const DRIDriverContext *ctx, RADEONInfoPtr info)
{
   unsigned char *RADEONMMIO = ctx->MMIOAddress;
   unsigned long  mode;
   int            ret;
   int            s, l;

   if (drmAgpAcquire(ctx->drmFD) < 0) {
      fprintf(stderr, "[gart] AGP not available\n");
      return 0;
   }
    
   /* Modify the mode if the default mode is not appropriate for this
    * particular combination of graphics card and AGP chipset.
    */
   mode   = drmAgpGetMode(ctx->drmFD);	/* Default mode */

   /* Disable fast write entirely - too many lockups.
    */
   mode &= ~RADEON_AGP_MODE_MASK;
   switch (ctx->agpmode) {
   case 4:          mode |= RADEON_AGP_4X_MODE;
   case 2:          mode |= RADEON_AGP_2X_MODE;
   case 1: default: mode |= RADEON_AGP_1X_MODE;
   }

   if (drmAgpEnable(ctx->drmFD, mode) < 0) {
      fprintf(stderr, "[gart] AGP not enabled\n");
      drmAgpRelease(ctx->drmFD);
      return 0;
   }
   else
     fprintf(stderr, "[gart] AGP enabled at %dx\n", ctx->agpmode);

   /* Workaround for some hardware bugs */
   if (info->ChipFamily < CHIP_FAMILY_R200)
      OUTREG(RADEON_AGP_CNTL, INREG(RADEON_AGP_CNTL) | 0x000e0000);

   info->gartOffset = 0;

   if ((ret = drmAgpAlloc(ctx->drmFD, info->gartSize*1024*1024, 0, NULL,
			  &info->gartMemHandle)) < 0) {
      fprintf(stderr, "[gart] Out of memory (%d)\n", ret);
      drmAgpRelease(ctx->drmFD);
      return 0;
   }
   fprintf(stderr,
	   "[gart] %d kB allocated with handle 0x%08x\n",
	   info->gartSize*1024, (unsigned)info->gartMemHandle);
    
   if (drmAgpBind(ctx->drmFD,
		  info->gartMemHandle, info->gartOffset) < 0) {
      fprintf(stderr, "[gart] Could not bind\n");
      drmAgpFree(ctx->drmFD, info->gartMemHandle);
      drmAgpRelease(ctx->drmFD);
      return 0;
   }

   /* Initialize the CP ring buffer data */
   info->ringStart       = info->gartOffset;
   info->ringMapSize     = info->ringSize*1024*1024 + radeon_drm_page_size;

   info->ringReadOffset  = info->ringStart + info->ringMapSize;
   info->ringReadMapSize = radeon_drm_page_size;

   /* Reserve space for vertex/indirect buffers */
   info->bufStart        = info->ringReadOffset + info->ringReadMapSize;
   info->bufMapSize      = info->bufSize*1024*1024;

   /* Reserve the rest for AGP textures */
   info->gartTexStart     = info->bufStart + info->bufMapSize;
   s = (info->gartSize*1024*1024 - info->gartTexStart);
   l = RADEONMinBits((s-1) / RADEON_NR_TEX_REGIONS);
   if (l < RADEON_LOG_TEX_GRANULARITY) l = RADEON_LOG_TEX_GRANULARITY;
   info->gartTexMapSize   = (s >> l) << l;
   info->log2GARTTexGran  = l;

   if (drmAddMap(ctx->drmFD, info->ringStart, info->ringMapSize,
		 DRM_AGP, DRM_READ_ONLY, &info->ringHandle) < 0) {
      fprintf(stderr, "[gart] Could not add ring mapping\n");
      return 0;
   }
   fprintf(stderr, "[gart] ring handle = 0x%08lx\n", info->ringHandle);
    

   if (drmAddMap(ctx->drmFD, info->ringReadOffset, info->ringReadMapSize,
		 DRM_AGP, DRM_READ_ONLY, &info->ringReadPtrHandle) < 0) {
      fprintf(stderr,
	      "[gart] Could not add ring read ptr mapping\n");
      return 0;
   }
    
   fprintf(stderr,
	   "[gart] ring read ptr handle = 0x%08lx\n",
	   info->ringReadPtrHandle);
    
   if (drmAddMap(ctx->drmFD, info->bufStart, info->bufMapSize,
		 DRM_AGP, 0, &info->bufHandle) < 0) {
      fprintf(stderr,
	      "[gart] Could not add vertex/indirect buffers mapping\n");
      return 0;
   }
   fprintf(stderr,
	   "[gart] vertex/indirect buffers handle = 0x%08lx\n",
	   info->bufHandle);

   if (drmAddMap(ctx->drmFD, info->gartTexStart, info->gartTexMapSize,
		 DRM_AGP, 0, &info->gartTexHandle) < 0) {
      fprintf(stderr,
	      "[gart] Could not add AGP texture map mapping\n");
      return 0;
   }
   fprintf(stderr,
	   "[gart] AGP texture map handle = 0x%08lx\n",
	   info->gartTexHandle);

   return 1;
}

/* Initialize the PCI GART state.  Request memory for use in PCI space,
 * and initialize the Radeon registers to point to that memory.
 */
static int RADEONDRIPciInit(const DRIDriverContext *ctx, RADEONInfoPtr info)
{
    int  ret;
    int  flags = DRM_READ_ONLY | DRM_LOCKED | DRM_KERNEL;
    int            s, l;

    ret = drmScatterGatherAlloc(ctx->drmFD, info->gartSize*1024*1024,
				&info->gartMemHandle);
    if (ret < 0) {
	fprintf(stderr, "[pci] Out of memory (%d)\n", ret);
	return 0;
    }
    fprintf(stderr,
	       "[pci] %d kB allocated with handle 0x%08x\n",
	       info->gartSize*1024, info->gartMemHandle);

   info->gartOffset = 0;
{'fraction_non_alphanumeric': 0.11171357945937326, 'fraction_numerical': 0.01606729925843234, 'mean_word_length': 3.2234382892742888, 'pattern_counts': {'":': 0, '<': 53, '<?xml version=': 0, '>': 191, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 8, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3513439', 'n_tokens_mistral': 10370, 'n_tokens_neox': 9317, 'n_words': 2138}