summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordaenzer <daenzer>2003-11-04 00:46:04 +0000
committerdaenzer <daenzer>2003-11-04 00:46:04 +0000
commitf16ad3b582846cbdbffda8fb35fb15c6c659a6f2 (patch)
treeeca840e56ab0e00e3c8c0da969af0c9746eefddc
parent59a31925ce7320a09c0f71e5919c0d81ccb07f68 (diff)
Memory layout transition:
* the 2D driver initializes MC_FB_LOCATION and related registers sanely * the DRM deduces the layout from these registers * clients use the new SETPARAM ioctl to tell the DRM where they think the framebuffer is located in the card's address space * the DRM uses all this information to check client state and fix it up if necessary This is a prerequisite for things like direct rendering with IGP chips and video capturing.
-rw-r--r--xc/lib/GL/mesa/src/drv/r200/r200_ioctl.c3
-rw-r--r--xc/lib/GL/mesa/src/drv/r200/r200_lock.c3
-rw-r--r--xc/lib/GL/mesa/src/drv/r200/r200_pixel.c14
-rw-r--r--xc/lib/GL/mesa/src/drv/r200/r200_screen.c17
-rw-r--r--xc/lib/GL/mesa/src/drv/r200/r200_screen.h1
-rw-r--r--xc/lib/GL/mesa/src/drv/r200/r200_state.c5
-rw-r--r--xc/lib/GL/mesa/src/drv/r200/r200_state_init.c7
-rw-r--r--xc/lib/GL/mesa/src/drv/radeon/radeon_ioctl.c3
-rw-r--r--xc/lib/GL/mesa/src/drv/radeon/radeon_lock.c3
-rw-r--r--xc/lib/GL/mesa/src/drv/radeon/radeon_screen.c17
-rw-r--r--xc/lib/GL/mesa/src/drv/radeon/radeon_screen.h1
-rw-r--r--xc/lib/GL/mesa/src/drv/radeon/radeon_state.c5
-rw-r--r--xc/lib/GL/mesa/src/drv/radeon/radeon_state_init.c7
-rw-r--r--xc/programs/Xserver/hw/xfree86/drivers/ati/radeon.h1
-rw-r--r--xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_accel.c13
-rw-r--r--xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_accelfuncs.c4
-rw-r--r--xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_common.h16
-rw-r--r--xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c91
-rw-r--r--xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drmP.h3
-rw-r--r--xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_drv.h3
-rw-r--r--xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_fops.h3
-rw-r--r--xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_os_freebsd.h2
-rw-r--r--xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_os_netbsd.h2
-rw-r--r--xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drmP.h3
-rw-r--r--xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_drv.h3
-rw-r--r--xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_fops.h2
-rw-r--r--xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_os_linux.h4
-rw-r--r--xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon.h21
-rw-r--r--xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_cp.c29
-rw-r--r--xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_drm.h16
-rw-r--r--xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_drv.h5
-rw-r--r--xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_state.c323
32 files changed, 510 insertions, 120 deletions
diff --git a/xc/lib/GL/mesa/src/drv/r200/r200_ioctl.c b/xc/lib/GL/mesa/src/drv/r200/r200_ioctl.c
index 458b51913..284cd47b9 100644
--- a/xc/lib/GL/mesa/src/drv/r200/r200_ioctl.c
+++ b/xc/lib/GL/mesa/src/drv/r200/r200_ioctl.c
@@ -531,7 +531,8 @@ void r200PageFlip( const __DRIdrawablePrivate *dPriv )
}
R200_STATECHANGE( rmesa, ctx );
- rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] = rmesa->state.color.drawOffset;
+ rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] = rmesa->state.color.drawOffset
+ + rmesa->r200Screen->fbLocation;
rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = rmesa->state.color.drawPitch;
}
diff --git a/xc/lib/GL/mesa/src/drv/r200/r200_lock.c b/xc/lib/GL/mesa/src/drv/r200/r200_lock.c
index 9d6cff50a..3c3356eec 100644
--- a/xc/lib/GL/mesa/src/drv/r200/r200_lock.c
+++ b/xc/lib/GL/mesa/src/drv/r200/r200_lock.c
@@ -64,7 +64,8 @@ r200UpdatePageFlipping( r200ContextPtr rmesa )
}
R200_STATECHANGE( rmesa, ctx );
- rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] = rmesa->state.color.drawOffset;
+ rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] = rmesa->state.color.drawOffset
+ + rmesa->r200Screen->fbLocation;
rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = rmesa->state.color.drawPitch;
}
diff --git a/xc/lib/GL/mesa/src/drv/r200/r200_pixel.c b/xc/lib/GL/mesa/src/drv/r200/r200_pixel.c
index 29eab6cd2..806484404 100644
--- a/xc/lib/GL/mesa/src/drv/r200/r200_pixel.c
+++ b/xc/lib/GL/mesa/src/drv/r200/r200_pixel.c
@@ -215,7 +215,8 @@ r200TryReadPixels( GLcontext *ctx,
{
__DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
int nbox = dPriv->numClipRects;
- int src_offset = rmesa->state.color.drawOffset;
+ int src_offset = rmesa->state.color.drawOffset
+ + rmesa->r200Screen->fbLocation;
int src_pitch = rmesa->state.color.drawPitch * rmesa->r200Screen->cpp;
int dst_offset = r200GartOffsetFromVirtual( rmesa, pixels );
int dst_pitch = pitch * rmesa->r200Screen->cpp;
@@ -288,7 +289,7 @@ static void do_draw_pix( GLcontext *ctx,
GLint x, GLint y, GLsizei width, GLsizei height,
GLint pitch,
const void *pixels,
- GLuint dest, GLuint planemask)
+ GLuint planemask)
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
__DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
@@ -354,7 +355,7 @@ static void do_draw_pix( GLcontext *ctx,
blit_format,
src_pitch, src_offset,
rmesa->state.color.drawPitch * rmesa->r200Screen->cpp,
- rmesa->state.color.drawOffset,
+ rmesa->state.color.drawOffset + rmesa->r200Screen->fbLocation,
bx - x, by - y,
bx, by,
bw, bh );
@@ -377,7 +378,7 @@ r200TryDrawPixels( GLcontext *ctx,
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
GLint pitch = unpack->RowLength ? unpack->RowLength : width;
- GLuint dest, planemask;
+ GLuint planemask;
GLuint cpp = rmesa->r200Screen->cpp;
GLint size = width * pitch * cpp;
@@ -388,8 +389,6 @@ r200TryDrawPixels( GLcontext *ctx,
case GL_RGB:
case GL_RGBA:
case GL_BGRA:
- dest = rmesa->state.color.drawOffset;
-
planemask = r200PackColor(cpp,
ctx->Color.ColorMask[RCOMP],
ctx->Color.ColorMask[GCOMP],
@@ -428,8 +427,7 @@ r200TryDrawPixels( GLcontext *ctx,
if ( r200IsGartMemory(rmesa, pixels, size) )
{
- do_draw_pix( ctx, x, y, width, height, pitch, pixels,
- dest, planemask );
+ do_draw_pix( ctx, x, y, width, height, pitch, pixels, planemask );
return GL_TRUE;
}
else if (0)
diff --git a/xc/lib/GL/mesa/src/drv/r200/r200_screen.c b/xc/lib/GL/mesa/src/drv/r200/r200_screen.c
index 268d38ffb..332c89d55 100644
--- a/xc/lib/GL/mesa/src/drv/r200/r200_screen.c
+++ b/xc/lib/GL/mesa/src/drv/r200/r200_screen.c
@@ -76,6 +76,7 @@ r200CreateScreen( __DRIscreenPrivate *sPriv )
{
r200ScreenPtr screen;
RADEONDRIPtr dri_priv = (RADEONDRIPtr)sPriv->pDevPriv;
+ unsigned char *RADEONMMIO;
if ( ! driCheckDriDdxDrmVersions( sPriv, "R200", 4, 0, 4, 0, 1, 5 ) )
return NULL;
@@ -170,6 +171,8 @@ r200CreateScreen( __DRIscreenPrivate *sPriv )
return NULL;
}
+ RADEONMMIO = screen->mmio.map;
+
screen->status.handle = dri_priv->statusHandle;
screen->status.size = dri_priv->statusSize;
if ( drmMap( sPriv->fd,
@@ -194,8 +197,6 @@ r200CreateScreen( __DRIscreenPrivate *sPriv )
}
if ( dri_priv->gartTexHandle && dri_priv->gartTexMapSize ) {
- unsigned char *RADEONMMIO = screen->mmio.map;
-
screen->gartTextures.handle = dri_priv->gartTexHandle;
screen->gartTextures.size = dri_priv->gartTexMapSize;
if ( drmMap( sPriv->fd,
@@ -218,6 +219,18 @@ r200CreateScreen( __DRIscreenPrivate *sPriv )
screen->cpp = dri_priv->bpp / 8;
screen->AGPMode = dri_priv->AGPMode;
+ screen->fbLocation = ( INREG( RADEON_MC_FB_LOCATION ) & 0xffff ) << 16;
+
+ if ( sPriv->drmMinor >= 10 ) {
+ drmRadeonSetParam sp;
+
+ sp.param = RADEON_SETPARAM_FB_LOCATION;
+ sp.value = screen->fbLocation;
+
+ drmCommandWrite( sPriv->fd, DRM_RADEON_SETPARAM,
+ &sp, sizeof( sp ) );
+ }
+
screen->frontOffset = dri_priv->frontOffset;
screen->frontPitch = dri_priv->frontPitch;
screen->backOffset = dri_priv->backOffset;
diff --git a/xc/lib/GL/mesa/src/drv/r200/r200_screen.h b/xc/lib/GL/mesa/src/drv/r200/r200_screen.h
index 3ed4f5502..6b12227ec 100644
--- a/xc/lib/GL/mesa/src/drv/r200/r200_screen.h
+++ b/xc/lib/GL/mesa/src/drv/r200/r200_screen.h
@@ -64,6 +64,7 @@ typedef struct {
int AGPMode;
unsigned int irq; /* IRQ number (0 means none) */
+ unsigned int fbLocation;
unsigned int frontOffset;
unsigned int frontPitch;
unsigned int backOffset;
diff --git a/xc/lib/GL/mesa/src/drv/r200/r200_state.c b/xc/lib/GL/mesa/src/drv/r200/r200_state.c
index b501f9111..5e10b52c0 100644
--- a/xc/lib/GL/mesa/src/drv/r200/r200_state.c
+++ b/xc/lib/GL/mesa/src/drv/r200/r200_state.c
@@ -1646,8 +1646,9 @@ static void r200DrawBuffer( GLcontext *ctx, GLenum mode )
_swrast_DrawBuffer(ctx, mode);
R200_STATECHANGE( rmesa, ctx );
- rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] = (rmesa->state.color.drawOffset &
- R200_COLOROFFSET_MASK);
+ rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] = ((rmesa->state.color.drawOffset +
+ rmesa->r200Screen->fbLocation)
+ & R200_COLOROFFSET_MASK);
rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = rmesa->state.color.drawPitch;
}
diff --git a/xc/lib/GL/mesa/src/drv/r200/r200_state_init.c b/xc/lib/GL/mesa/src/drv/r200/r200_state_init.c
index 006e8d82a..1afd59c27 100644
--- a/xc/lib/GL/mesa/src/drv/r200/r200_state_init.c
+++ b/xc/lib/GL/mesa/src/drv/r200/r200_state_init.c
@@ -365,7 +365,7 @@ void r200InitState( r200ContextPtr rmesa )
R200_DST_BLEND_GL_ZERO );
rmesa->hw.ctx.cmd[CTX_RB3D_DEPTHOFFSET] =
- rmesa->r200Screen->depthOffset;
+ rmesa->r200Screen->depthOffset + rmesa->r200Screen->fbLocation;
rmesa->hw.ctx.cmd[CTX_RB3D_DEPTHPITCH] =
((rmesa->r200Screen->depthPitch &
@@ -403,8 +403,9 @@ void r200InitState( r200ContextPtr rmesa )
else
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= rmesa->state.color.roundEnable;
- rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] = (rmesa->state.color.drawOffset &
- R200_COLOROFFSET_MASK);
+ rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] = ((rmesa->state.color.drawOffset +
+ rmesa->r200Screen->fbLocation)
+ & R200_COLOROFFSET_MASK);
rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = ((rmesa->state.color.drawPitch &
R200_COLORPITCH_MASK) |
diff --git a/xc/lib/GL/mesa/src/drv/radeon/radeon_ioctl.c b/xc/lib/GL/mesa/src/drv/radeon/radeon_ioctl.c
index 93bfa3bc1..483733305 100644
--- a/xc/lib/GL/mesa/src/drv/radeon/radeon_ioctl.c
+++ b/xc/lib/GL/mesa/src/drv/radeon/radeon_ioctl.c
@@ -920,7 +920,8 @@ void radeonPageFlip( const __DRIdrawablePrivate *dPriv )
}
RADEON_STATECHANGE( rmesa, ctx );
- rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] = rmesa->state.color.drawOffset;
+ rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] = rmesa->state.color.drawOffset
+ + rmesa->radeonScreen->fbLocation;
rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = rmesa->state.color.drawPitch;
}
diff --git a/xc/lib/GL/mesa/src/drv/radeon/radeon_lock.c b/xc/lib/GL/mesa/src/drv/radeon/radeon_lock.c
index daf001e04..fb285157a 100644
--- a/xc/lib/GL/mesa/src/drv/radeon/radeon_lock.c
+++ b/xc/lib/GL/mesa/src/drv/radeon/radeon_lock.c
@@ -73,7 +73,8 @@ radeonUpdatePageFlipping( radeonContextPtr rmesa )
}
RADEON_STATECHANGE( rmesa, ctx );
- rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] = rmesa->state.color.drawOffset;
+ rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] = rmesa->state.color.drawOffset
+ + rmesa->radeonScreen->fbLocation;
rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = rmesa->state.color.drawPitch;
}
diff --git a/xc/lib/GL/mesa/src/drv/radeon/radeon_screen.c b/xc/lib/GL/mesa/src/drv/radeon/radeon_screen.c
index 75221c61d..c861fe590 100644
--- a/xc/lib/GL/mesa/src/drv/radeon/radeon_screen.c
+++ b/xc/lib/GL/mesa/src/drv/radeon/radeon_screen.c
@@ -75,6 +75,7 @@ radeonScreenPtr radeonCreateScreen( __DRIscreenPrivate *sPriv )
{
radeonScreenPtr screen;
RADEONDRIPtr dri_priv = (RADEONDRIPtr)sPriv->pDevPriv;
+ unsigned char *RADEONMMIO;
if ( ! driCheckDriDdxDrmVersions( sPriv, "Radeon", 4, 0, 4, 0, 1, 3 ) )
return NULL;
@@ -135,6 +136,8 @@ radeonScreenPtr radeonCreateScreen( __DRIscreenPrivate *sPriv )
return NULL;
}
+ RADEONMMIO = screen->mmio.map;
+
screen->status.handle = dri_priv->statusHandle;
screen->status.size = dri_priv->statusSize;
if ( drmMap( sPriv->fd,
@@ -159,8 +162,6 @@ radeonScreenPtr radeonCreateScreen( __DRIscreenPrivate *sPriv )
}
if ( dri_priv->gartTexHandle && dri_priv->gartTexMapSize ) {
- unsigned char *RADEONMMIO = screen->mmio.map;
-
screen->gartTextures.handle = dri_priv->gartTexHandle;
screen->gartTextures.size = dri_priv->gartTexMapSize;
if ( drmMap( sPriv->fd,
@@ -201,6 +202,18 @@ radeonScreenPtr radeonCreateScreen( __DRIscreenPrivate *sPriv )
screen->cpp = dri_priv->bpp / 8;
screen->AGPMode = dri_priv->AGPMode;
+ screen->fbLocation = ( INREG( RADEON_MC_FB_LOCATION ) & 0xffff ) << 16;
+
+ if ( sPriv->drmMinor >= 10 ) {
+ drmRadeonSetParam sp;
+
+ sp.param = RADEON_SETPARAM_FB_LOCATION;
+ sp.value = screen->fbLocation;
+
+ drmCommandWrite( sPriv->fd, DRM_RADEON_SETPARAM,
+ &sp, sizeof( sp ) );
+ }
+
screen->frontOffset = dri_priv->frontOffset;
screen->frontPitch = dri_priv->frontPitch;
screen->backOffset = dri_priv->backOffset;
diff --git a/xc/lib/GL/mesa/src/drv/radeon/radeon_screen.h b/xc/lib/GL/mesa/src/drv/radeon/radeon_screen.h
index 133c3633c..4a0f6d47f 100644
--- a/xc/lib/GL/mesa/src/drv/radeon/radeon_screen.h
+++ b/xc/lib/GL/mesa/src/drv/radeon/radeon_screen.h
@@ -68,6 +68,7 @@ typedef struct {
int AGPMode;
unsigned int irq; /* IRQ number (0 means none) */
+ unsigned int fbLocation;
unsigned int frontOffset;
unsigned int frontPitch;
unsigned int backOffset;
diff --git a/xc/lib/GL/mesa/src/drv/radeon/radeon_state.c b/xc/lib/GL/mesa/src/drv/radeon/radeon_state.c
index f33183b29..c291701d3 100644
--- a/xc/lib/GL/mesa/src/drv/radeon/radeon_state.c
+++ b/xc/lib/GL/mesa/src/drv/radeon/radeon_state.c
@@ -1617,8 +1617,9 @@ static void radeonDrawBuffer( GLcontext *ctx, GLenum mode )
_swrast_DrawBuffer(ctx, mode);
RADEON_STATECHANGE( rmesa, ctx );
- rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] = (rmesa->state.color.drawOffset &
- RADEON_COLOROFFSET_MASK);
+ rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] = ((rmesa->state.color.drawOffset +
+ rmesa->radeonScreen->fbLocation)
+ & RADEON_COLOROFFSET_MASK);
rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = rmesa->state.color.drawPitch;
}
diff --git a/xc/lib/GL/mesa/src/drv/radeon/radeon_state_init.c b/xc/lib/GL/mesa/src/drv/radeon/radeon_state_init.c
index a43084ead..09ec4417b 100644
--- a/xc/lib/GL/mesa/src/drv/radeon/radeon_state_init.c
+++ b/xc/lib/GL/mesa/src/drv/radeon/radeon_state_init.c
@@ -324,7 +324,7 @@ void radeonInitState( radeonContextPtr rmesa )
RADEON_DST_BLEND_GL_ZERO );
rmesa->hw.ctx.cmd[CTX_RB3D_DEPTHOFFSET] =
- rmesa->radeonScreen->depthOffset;
+ rmesa->radeonScreen->depthOffset + rmesa->radeonScreen->fbLocation;
rmesa->hw.ctx.cmd[CTX_RB3D_DEPTHPITCH] =
((rmesa->radeonScreen->depthPitch &
@@ -365,8 +365,9 @@ void radeonInitState( radeonContextPtr rmesa )
else
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= rmesa->state.color.roundEnable;
- rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] = (rmesa->state.color.drawOffset &
- RADEON_COLOROFFSET_MASK);
+ rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] = ((rmesa->state.color.drawOffset +
+ rmesa->radeonScreen->fbLocation)
+ & RADEON_COLOROFFSET_MASK);
rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = ((rmesa->state.color.drawPitch &
RADEON_COLORPITCH_MASK) |
diff --git a/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon.h b/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon.h
index 7121c9305..625dd0c65 100644
--- a/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon.h
+++ b/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon.h
@@ -499,6 +499,7 @@ typedef struct {
int depthX;
int depthY;
+ unsigned int fbLocation;
int frontOffset;
int frontPitch;
int backOffset;
diff --git a/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_accel.c b/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_accel.c
index 8556cc25f..58d883614 100644
--- a/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_accel.c
+++ b/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_accel.c
@@ -283,8 +283,8 @@ void RADEONEngineRestore(ScrnInfoPtr pScrn)
pitch64 = ((pScrn->displayWidth * (pScrn->bitsPerPixel / 8) + 0x3f)) >> 6;
RADEONWaitForFifo(pScrn, 1);
- OUTREG(RADEON_DEFAULT_OFFSET, ((INREG(RADEON_DISPLAY_BASE_ADDR) >> 10)
- | (pitch64 << 22)));
+ OUTREG(RADEON_DEFAULT_OFFSET, ((info->fbLocation >> 10)
+ | (pitch64 << 22)));
RADEONWaitForFifo(pScrn, 1);
#if X_BYTE_ORDER == X_BIG_ENDIAN
@@ -329,15 +329,6 @@ void RADEONEngineInit(ScrnInfoPtr pScrn)
info->CurrentLayout.bitsPerPixel));
OUTREG(RADEON_RB3D_CNTL, 0);
-#if defined(__powerpc__)
-#if defined(XF86_DRI)
- if(!info->directRenderingEnabled)
-#endif
- {
- OUTREG(RADEON_MC_FB_LOCATION, 0xffff0000);
- OUTREG(RADEON_MC_AGP_LOCATION, 0xfffff000);
- }
-#endif
RADEONEngineReset(pScrn);
diff --git a/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_accelfuncs.c b/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_accelfuncs.c
index 843fd6bb7..c1eb29ec8 100644
--- a/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_accelfuncs.c
+++ b/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_accelfuncs.c
@@ -181,8 +181,8 @@ FUNC_NAME(RADEONRestoreAccelState)(ScrnInfoPtr pScrn)
pitch64 = ((pScrn->displayWidth * (pScrn->bitsPerPixel / 8) + 0x3f)) >> 6;
- OUTREG(RADEON_DEFAULT_OFFSET, (((INREG(RADEON_DISPLAY_BASE_ADDR) + pScrn->fbOffset) >> 10) |
- (pitch64 << 22)));
+ OUTREG(RADEON_DEFAULT_OFFSET, ((info->fbLocation + pScrn->fbOffset) >> 10)
+ | (pitch64 << 22));
/* FIXME: May need to restore other things, like BKGD_CLK FG_CLK... */
diff --git a/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_common.h b/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_common.h
index 31e2a0b77..2193e7698 100644
--- a/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_common.h
+++ b/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_common.h
@@ -38,6 +38,7 @@
#ifndef _RADEON_COMMON_H_
#define _RADEON_COMMON_H_
+#include <inttypes.h>
#include "xf86drm.h"
/* WARNING: If you change any of these defines, make sure to change
@@ -71,6 +72,7 @@
#define DRM_RADEON_IRQ_EMIT 0x16
#define DRM_RADEON_IRQ_WAIT 0x17
#define DRM_RADEON_CP_RESUME 0x18
+#define DRM_RADEON_SETPARAM 0x19
#define DRM_RADEON_MAX_DRM_COMMAND_INDEX 0x39
@@ -159,7 +161,7 @@ typedef struct {
} drmRadeonTexImage;
typedef struct {
- int offset;
+ unsigned int offset;
int pitch;
int format;
int width; /* Texture image coordinates */
@@ -445,4 +447,16 @@ typedef struct drm_radeon_irq_wait {
} drmRadeonIrqWait;
+/* 1.10: Clients tell the DRM where they think the framebuffer is located in
+ * the card's address space, via a new generic ioctl to set parameters
+ */
+
+typedef struct drm_radeon_set_param {
+ unsigned int param;
+ int64_t value;
+} drmRadeonSetParam;
+
+#define RADEON_SETPARAM_FB_LOCATION 1
+
+
#endif
diff --git a/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c b/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c
index 3a9d9f943..33220dac3 100644
--- a/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c
+++ b/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c
@@ -1982,6 +1982,61 @@ static Bool RADEONPreInitWeight(ScrnInfoPtr pScrn)
return TRUE;
}
+/* Set up MC_FB_LOCATION and related registers */
+static void
+RADEONSetFBLocation(ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+ CARD32 mc_fb_location;
+ CARD32 mc_agp_location = INREG(RADEON_MC_AGP_LOCATION);
+
+ if (info->IsIGP) {
+ mc_fb_location = INREG(RADEON_NB_TOM);
+
+ OUTREG(RADEON_GRPH2_BUFFER_CNTL,
+ INREG(RADEON_GRPH2_BUFFER_CNTL) & ~0x7f0000);
+
+ if ((info->ChipFamily == CHIP_FAMILY_RS100) ||
+ (info->ChipFamily == CHIP_FAMILY_RS200)) {
+ /* This is to workaround the asic bug for RMX, some versions
+ of BIOS don't have this register initialized correctly.
+ */
+ OUTREGP(RADEON_CRTC_MORE_CNTL, RADEON_CRTC_H_CUTOFF_ACTIVE_EN,
+ ~RADEON_CRTC_H_CUTOFF_ACTIVE_EN);
+ }
+ } else
+#ifdef XF86DRI
+ if ( info->directRenderingEnabled && info->drmMinor < 10 ) {
+ mc_fb_location = (INREG(RADEON_CONFIG_APER_SIZE) - 1) & 0xffff0000U;
+ } else
+#endif
+ {
+ CARD32 aper0_base = INREG(RADEON_CONFIG_APER_0_BASE);
+
+ mc_fb_location = (aper0_base >> 16)
+ | ((aper0_base + (INREG(RADEON_CONFIG_APER_SIZE) - 1)
+ ) & 0xffff0000U);
+ }
+
+ info->fbLocation = (mc_fb_location & 0xffff) << 16;
+
+ if (((mc_agp_location & 0xffff) << 16) !=
+ ((mc_fb_location & 0xffff0000U) + 0x10000)) {
+ mc_agp_location = mc_fb_location & 0xffff0000U;
+ mc_agp_location |= (mc_agp_location + 0x10000) >> 16;
+ }
+
+ RADEONWaitForIdleMMIO(pScrn);
+
+ OUTREG(RADEON_MC_FB_LOCATION, mc_fb_location);
+ OUTREG(RADEON_MC_AGP_LOCATION, mc_agp_location);
+ OUTREG(RADEON_DISPLAY_BASE_ADDR, info->fbLocation);
+ if (info->HasCRTC2)
+ OUTREG(RADEON_DISPLAY2_BASE_ADDR, info->fbLocation);
+ OUTREG(RADEON_OV0_BASE_ADDR, info->fbLocation);
+}
+
static void RADEONGetVRamType(ScrnInfoPtr pScrn)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
@@ -2226,34 +2281,18 @@ static Bool RADEONPreInitConfig(ScrnInfoPtr pScrn)
from = X_PROBED;
if (info->FBDev)
pScrn->videoRam = fbdevHWGetVidmem(pScrn) / 1024;
- else if ((info->ChipFamily == CHIP_FAMILY_RS100) ||
+ else if ((info->ChipFamily == CHIP_FAMILY_RS100) ||
(info->ChipFamily == CHIP_FAMILY_RS200) ||
(info->ChipFamily == CHIP_FAMILY_RS300)) {
CARD32 tom = INREG(RADEON_NB_TOM);
- pScrn->videoRam = (((tom >> 16) -
- (tom & 0xffff) + 1) << 6);
- OUTREG(RADEON_MC_FB_LOCATION, tom);
- OUTREG(RADEON_DISPLAY_BASE_ADDR, (tom & 0xffff) << 16);
- OUTREG(RADEON_DISPLAY2_BASE_ADDR, (tom & 0xffff) << 16);
- OUTREG(RADEON_OV0_BASE_ADDR, (tom & 0xffff) << 16);
- /* This is supposed to fix the crtc2 noise problem.
- */
- OUTREG(RADEON_GRPH2_BUFFER_CNTL,
- INREG(RADEON_GRPH2_BUFFER_CNTL) & ~0x7f0000);
-
- if ((info->ChipFamily == CHIP_FAMILY_RS100) ||
- (info->ChipFamily == CHIP_FAMILY_RS200)) {
- /* This is to workaround the asic bug for RMX, some versions
- of BIOS dosen't have this register initialized correctly.
- */
- OUTREGP(RADEON_CRTC_MORE_CNTL, RADEON_CRTC_H_CUTOFF_ACTIVE_EN,
- ~RADEON_CRTC_H_CUTOFF_ACTIVE_EN);
- }
+ pScrn->videoRam = (((tom >> 16) -
+ (tom & 0xffff) + 1) << 6);
- }
- else
+ OUTREG(RADEON_CONFIG_MEMSIZE, pScrn->videoRam * 1024);
+ } else {
pScrn->videoRam = INREG(RADEON_CONFIG_MEMSIZE) / 1024;
+ }
/* Some production boards of m6 will return 0 if it's 8 MB */
if (pScrn->videoRam == 0) pScrn->videoRam = 8192;
@@ -4397,6 +4436,8 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
}
#endif
+ RADEONSetFBLocation(pScrn);
+
if (!fbScreenInit(pScreen, info->FB,
pScrn->virtualX, pScrn->virtualY,
pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth,
@@ -4628,13 +4669,13 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
info->textureSize/1024, info->textureOffset);
info->frontPitchOffset = (((info->frontPitch * cpp / 64) << 22) |
- (info->frontOffset >> 10));
+ ((info->frontOffset + info->fbLocation) >> 10));
info->backPitchOffset = (((info->backPitch * cpp / 64) << 22) |
- (info->backOffset >> 10));
+ ((info->backOffset + info->fbLocation) >> 10));
info->depthPitchOffset = (((info->depthPitch * cpp / 64) << 22) |
- (info->depthOffset >> 10));
+ ((info->depthOffset + info->fbLocation) >> 10));
} else
#endif
{
diff --git a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drmP.h b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drmP.h
index eec3faed4..2bbe2733d 100644
--- a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drmP.h
+++ b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drmP.h
@@ -210,6 +210,9 @@ struct drm_file {
drm_magic_t magic;
unsigned long ioctl_count;
struct drm_device *devXX;
+#ifdef DRIVER_FILE_FIELDS
+ DRIVER_FILE_FIELDS;
+#endif
};
typedef struct drm_lock_data {
diff --git a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_drv.h b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_drv.h
index 3f4946949..911e7f705 100644
--- a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_drv.h
+++ b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_drv.h
@@ -101,6 +101,9 @@
#ifndef DRIVER_IOCTLS
#define DRIVER_IOCTLS
#endif
+#ifndef DRIVER_OPEN_HELPER
+#define DRIVER_OPEN_HELPER( priv, dev )
+#endif
#ifndef DRIVER_FOPS
#endif
diff --git a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_fops.h b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_fops.h
index 3c4553dec..55ef8ce0c 100644
--- a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_fops.h
+++ b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_fops.h
@@ -88,6 +88,9 @@ int DRM(open_helper)(dev_t kdev, int flags, int fmt, DRM_STRUCTPROC *p,
priv->devXX = dev;
priv->ioctl_count = 0;
priv->authenticated = !DRM_SUSER(p);
+
+ DRIVER_OPEN_HELPER( priv, dev );
+
TAILQ_INSERT_TAIL(&dev->files, priv, link);
}
DRM_UNLOCK();
diff --git a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_os_freebsd.h b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_os_freebsd.h
index 4822b0569..480a53f59 100644
--- a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_os_freebsd.h
+++ b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_os_freebsd.h
@@ -267,6 +267,8 @@ for ( ret = 0 ; !ret && !(condition) ; ) { \
(!useracc((caddr_t)uaddr, size, VM_PROT_READ))
#define DRM_COPY_FROM_USER_UNCHECKED(arg1, arg2, arg3) \
copyin(arg2, arg1, arg3)
+#define DRM_COPY_TO_USER_UNCHECKED(arg1, arg2, arg3) \
+ copyout(arg2, arg1, arg3)
#define DRM_GET_USER_UNCHECKED(val, uaddr) \
((val) = fuword(uaddr), 0)
#define DRM_PUT_USER_UNCHECKED(val, uaddr) \
diff --git a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_os_netbsd.h b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_os_netbsd.h
index 4c95c50f6..47b8f5017 100644
--- a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_os_netbsd.h
+++ b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_os_netbsd.h
@@ -215,6 +215,8 @@ while (!condition) { \
(!uvm_useracc((caddr_t)uaddr, size, VM_PROT_READ))
#define DRM_COPY_FROM_USER_UNCHECKED(arg1, arg2, arg3) \
copyin(arg2, arg1, arg3)
+#define DRM_COPY_TO_USER_UNCHECKED(arg1, arg2, arg3) \
+ copyout(arg2, arg1, arg3)
#define DRM_GET_USER_UNCHECKED(val, uaddr) \
((val) = fuword(uaddr), 0)
diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drmP.h b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drmP.h
index 3d3796645..f0fc64d4c 100644
--- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drmP.h
+++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drmP.h
@@ -520,6 +520,9 @@ typedef struct drm_file {
struct drm_device *dev;
int remove_auth_on_close;
unsigned long lock_count;
+#ifdef DRIVER_FILE_FIELDS
+ DRIVER_FILE_FIELDS;
+#endif
} drm_file_t;
/** Wait queue */
diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_drv.h b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_drv.h
index e0c00f02f..e472dc332 100644
--- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_drv.h
+++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_drv.h
@@ -126,6 +126,9 @@
#ifndef DRIVER_IOCTLS
#define DRIVER_IOCTLS
#endif
+#ifndef DRIVER_OPEN_HELPER
+#define DRIVER_OPEN_HELPER( priv, dev )
+#endif
#ifndef DRIVER_FOPS
#define DRIVER_FOPS \
static struct file_operations DRM(fops) = { \
diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_fops.h b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_fops.h
index f4841ae8b..771a2fa28 100644
--- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_fops.h
+++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_fops.h
@@ -73,6 +73,8 @@ int DRM(open_helper)(struct inode *inode, struct file *filp, drm_device_t *dev)
priv->authenticated = capable(CAP_SYS_ADMIN);
priv->lock_count = 0;
+ DRIVER_OPEN_HELPER( priv, dev );
+
down(&dev->struct_sem);
if (!dev->file_last) {
priv->next = NULL;
diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_os_linux.h b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_os_linux.h
index cf7d7c2d4..c26a41086 100644
--- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_os_linux.h
+++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_os_linux.h
@@ -74,8 +74,12 @@ typedef void irqreturn_t;
verify_area( VERIFY_READ, uaddr, size )
#define DRM_COPY_FROM_USER_UNCHECKED(arg1, arg2, arg3) \
__copy_from_user(arg1, arg2, arg3)
+#define DRM_COPY_TO_USER_UNCHECKED(arg1, arg2, arg3) \
+ __copy_to_user(arg1, arg2, arg3)
#define DRM_GET_USER_UNCHECKED(val, uaddr) \
__get_user(val, uaddr)
+#define DRM_PUT_USER_UNCHECKED(uaddr, val) \
+ __put_user(val, uaddr)
/** 'malloc' without the overhead of DRM(alloc)() */
diff --git a/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon.h b/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon.h
index fadb248b7..af1f6ca4b 100644
--- a/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon.h
+++ b/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon.h
@@ -51,7 +51,7 @@
#define DRIVER_DATE "20020828"
#define DRIVER_MAJOR 1
-#define DRIVER_MINOR 9
+#define DRIVER_MINOR 10
#define DRIVER_PATCHLEVEL 0
/* Interface history:
@@ -81,6 +81,9 @@
* Add 'GET' queries for starting additional clients on different VT's.
* 1.9 - Add DRM_IOCTL_RADEON_CP_RESUME ioctl.
* Add texture rectangle support for r100.
+ * 1.10- Add SETPARAM ioctl; first parameter to set is FB_LOCATION, which
+ * clients use to tell the DRM where they think the framebuffer is
+ * located in the card's address space
*/
#define DRIVER_IOCTLS \
[DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { radeon_cp_buffers, 1, 0 }, \
@@ -106,8 +109,9 @@
[DRM_IOCTL_NR(DRM_IOCTL_RADEON_ALLOC)] = { radeon_mem_alloc, 1, 0 }, \
[DRM_IOCTL_NR(DRM_IOCTL_RADEON_FREE)] = { radeon_mem_free, 1, 0 }, \
[DRM_IOCTL_NR(DRM_IOCTL_RADEON_INIT_HEAP)] = { radeon_mem_init_heap, 1, 1 }, \
- [DRM_IOCTL_NR(DRM_IOCTL_RADEON_IRQ_EMIT)] = { radeon_irq_emit, 1, 0 }, \
- [DRM_IOCTL_NR(DRM_IOCTL_RADEON_IRQ_WAIT)] = { radeon_irq_wait, 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_IRQ_EMIT)] = { radeon_irq_emit, 1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_IRQ_WAIT)] = { radeon_irq_wait, 1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_SETPARAM)] = { radeon_cp_setparam, 1, 0 }, \
#define DRIVER_PCI_IDS \
{0x1002, 0x4242, 0, "ATI Radeon BB R200 AIW 8500DV"}, \
@@ -147,6 +151,17 @@
{0x1002, 0x5961, 0, "ATI Radeon RV280 9200"}, \
{0, 0, 0, NULL}
+#define DRIVER_FILE_FIELDS \
+ s64 radeon_fb_delta; \
+
+#define DRIVER_OPEN_HELPER( filp_priv, dev ) \
+do { \
+ drm_radeon_private_t *dev_priv = dev->dev_private; \
+ if ( dev_priv ) \
+ filp_priv->radeon_fb_delta = dev_priv->fb_location; \
+ else \
+ filp_priv->radeon_fb_delta = 0; \
+} while( 0 )
/* When a client dies:
* - Check for and clean up flipped page state
diff --git a/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_cp.c b/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_cp.c
index b24880a8b..87aef0105 100644
--- a/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_cp.c
+++ b/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_cp.c
@@ -855,7 +855,8 @@ static void radeon_cp_init_ring_buffer( drm_device_t *dev,
/* Initialize the memory controller */
RADEON_WRITE( RADEON_MC_FB_LOCATION,
- (dev_priv->gart_vm_start - 1) & 0xffff0000 );
+ ( ( dev_priv->gart_vm_start - 1 ) & 0xffff0000 )
+ | ( dev_priv->fb_location >> 16 ) );
#if __REALLY_HAVE_AGP
if ( !dev_priv->is_pci ) {
@@ -1071,13 +1072,6 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
dev_priv->depth_offset = init->depth_offset;
dev_priv->depth_pitch = init->depth_pitch;
- dev_priv->front_pitch_offset = (((dev_priv->front_pitch/64) << 22) |
- (dev_priv->front_offset >> 10));
- dev_priv->back_pitch_offset = (((dev_priv->back_pitch/64) << 22) |
- (dev_priv->back_offset >> 10));
- dev_priv->depth_pitch_offset = (((dev_priv->depth_pitch/64) << 22) |
- (dev_priv->depth_offset >> 10));
-
/* Hardware state for depth clears. Remove this if/when we no
* longer clear the depth buffer with a 3D rectangle. Hard-code
* all values to prevent unwanted 3D state from slipping through
@@ -1204,9 +1198,26 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
dev_priv->buffers->handle );
}
+ dev_priv->fb_location = ( RADEON_READ( RADEON_MC_FB_LOCATION )
+ & 0xffff ) << 16;
+
+ dev_priv->front_pitch_offset = (((dev_priv->front_pitch/64) << 22) |
+ ( ( dev_priv->front_offset
+ + dev_priv->fb_location ) >> 10 ) );
+
+ dev_priv->back_pitch_offset = (((dev_priv->back_pitch/64) << 22) |
+ ( ( dev_priv->back_offset
+ + dev_priv->fb_location ) >> 10 ) );
+
+ dev_priv->depth_pitch_offset = (((dev_priv->depth_pitch/64) << 22) |
+ ( ( dev_priv->depth_offset
+ + dev_priv->fb_location ) >> 10 ) );
+
dev_priv->gart_size = init->gart_size;
- dev_priv->gart_vm_start = RADEON_READ( RADEON_CONFIG_APER_SIZE );
+ dev_priv->gart_vm_start = dev_priv->fb_location
+ + RADEON_READ( RADEON_CONFIG_APER_SIZE );
+
#if __REALLY_HAVE_AGP
if ( !dev_priv->is_pci )
dev_priv->gart_buffers_offset = (dev_priv->buffers->offset
diff --git a/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_drm.h b/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_drm.h
index c4a746490..f56b188dd 100644
--- a/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_drm.h
+++ b/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_drm.h
@@ -390,6 +390,7 @@ typedef struct {
#define DRM_IOCTL_RADEON_IRQ_WAIT DRM_IOW( 0x57, drm_radeon_irq_wait_t)
/* added by Charl P. Botha - see radeon_cp.c for details */
#define DRM_IOCTL_RADEON_CP_RESUME DRM_IO(0x58)
+#define DRM_IOCTL_RADEON_SETPARAM DRM_IOW(0x59, drm_radeon_setparam_t)
typedef struct drm_radeon_init {
enum {
@@ -502,7 +503,7 @@ typedef struct drm_radeon_tex_image {
} drm_radeon_tex_image_t;
typedef struct drm_radeon_texture {
- int offset;
+ unsigned int offset;
int pitch;
int format;
int width; /* Texture image coordinates */
@@ -537,6 +538,7 @@ typedef struct drm_radeon_indirect {
#define RADEON_PARAM_STATUS_HANDLE 8
#define RADEON_PARAM_SAREA_HANDLE 9
#define RADEON_PARAM_GART_TEX_HANDLE 10
+#define RADEON_PARAM_SCRATCH_OFFSET 11
typedef struct drm_radeon_getparam {
int param;
@@ -578,4 +580,16 @@ typedef struct drm_radeon_irq_wait {
} drm_radeon_irq_wait_t;
+/* 1.10: Clients tell the DRM where they think the framebuffer is located in
+ * the card's address space, via a new generic ioctl to set parameters
+ */
+
+typedef struct drm_radeon_setparam {
+ unsigned int param;
+ int64_t value;
+} drm_radeon_setparam_t;
+
+#define RADEON_SETPARAM_FB_LOCATION 1 /* determined framebuffer location */
+
+
#endif
diff --git a/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_drv.h b/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_drv.h
index fd23aa28e..1569caa70 100644
--- a/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_drv.h
+++ b/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_drv.h
@@ -73,6 +73,8 @@ typedef struct drm_radeon_private {
drm_radeon_ring_buffer_t ring;
drm_radeon_sarea_t *sarea_priv;
+ u32 fb_location;
+
int gart_size;
u32 gart_vm_start;
unsigned long gart_buffers_offset;
@@ -184,6 +186,7 @@ extern int radeon_cp_indirect( DRM_IOCTL_ARGS );
extern int radeon_cp_vertex2( DRM_IOCTL_ARGS );
extern int radeon_cp_cmdbuf( DRM_IOCTL_ARGS );
extern int radeon_cp_getparam( DRM_IOCTL_ARGS );
+extern int radeon_cp_setparam( DRM_IOCTL_ARGS );
extern int radeon_cp_flip( DRM_IOCTL_ARGS );
extern int radeon_mem_alloc( DRM_IOCTL_ARGS );
@@ -239,6 +242,7 @@ extern void radeon_do_release(drm_device_t *dev);
#define RADEON_CRTC2_OFFSET 0x0324
#define RADEON_CRTC2_OFFSET_CNTL 0x0328
+#define RADEON_RB3D_COLOROFFSET 0x1c40
#define RADEON_RB3D_COLORPITCH 0x1c48
#define RADEON_DP_GUI_MASTER_CNTL 0x146c
@@ -332,6 +336,7 @@ extern void radeon_do_release(drm_device_t *dev);
#define RADEON_PP_MISC 0x1c14
#define RADEON_PP_ROT_MATRIX_0 0x1d58
#define RADEON_PP_TXFILTER_0 0x1c54
+#define RADEON_PP_TXOFFSET_0 0x1c5c
#define RADEON_PP_TXFILTER_1 0x1c6c
#define RADEON_PP_TXFILTER_2 0x1c84
diff --git a/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_state.c b/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_state.c
index 833f96981..e24bee8aa 100644
--- a/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_state.c
+++ b/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_state.c
@@ -36,6 +36,151 @@
/* ================================================================
+ * Helper functions for client state checking and fixup
+ */
+
+static __inline__ int radeon_check_and_fixup_offset( drm_radeon_private_t *dev_priv,
+ drm_file_t *filp_priv,
+ u32 *offset ) {
+ u32 off = *offset;
+
+ if ( off >= dev_priv->fb_location &&
+ off < ( dev_priv->gart_vm_start + dev_priv->gart_size ) )
+ return 0;
+
+ off += filp_priv->radeon_fb_delta;
+
+ DRM_DEBUG( "offset fixed up to 0x%x\n", off );
+
+ if ( off < dev_priv->fb_location ||
+ off >= ( dev_priv->gart_vm_start + dev_priv->gart_size ) )
+ return DRM_ERR( EINVAL );
+
+ *offset = off;
+
+ return 0;
+}
+
+static __inline__ int radeon_check_and_fixup_offset_user( drm_radeon_private_t *dev_priv,
+ drm_file_t *filp_priv,
+ u32 *offset ) {
+ u32 off;
+
+ DRM_GET_USER_UNCHECKED( off, offset );
+
+ if ( radeon_check_and_fixup_offset( dev_priv, filp_priv, &off ) )
+ return DRM_ERR( EINVAL );
+
+ DRM_PUT_USER_UNCHECKED( offset, off );
+
+ return 0;
+}
+
+static __inline__ int radeon_check_and_fixup_packets( drm_radeon_private_t *dev_priv,
+ drm_file_t *filp_priv,
+ int id,
+ u32 *data ) {
+ if ( id == RADEON_EMIT_PP_MISC &&
+ radeon_check_and_fixup_offset_user( dev_priv, filp_priv,
+ &data[( RADEON_RB3D_DEPTHOFFSET
+ - RADEON_PP_MISC ) / 4] ) ) {
+ DRM_ERROR( "Invalid depth buffer offset\n" );
+ return DRM_ERR( EINVAL );
+ } else if ( id == RADEON_EMIT_PP_CNTL &&
+ radeon_check_and_fixup_offset_user( dev_priv, filp_priv,
+ &data[( RADEON_RB3D_COLOROFFSET
+ - RADEON_PP_CNTL ) / 4] ) ) {
+ DRM_ERROR( "Invalid colour buffer offset\n" );
+ return DRM_ERR( EINVAL );
+ } else if ( id >= R200_EMIT_PP_TXOFFSET_0 &&
+ id <= R200_EMIT_PP_TXOFFSET_5 &&
+ radeon_check_and_fixup_offset_user( dev_priv, filp_priv,
+ &data[0] ) ) {
+ DRM_ERROR( "Invalid R200 texture offset\n" );
+ return DRM_ERR( EINVAL );
+ } else if ( ( id == RADEON_EMIT_PP_TXFILTER_0 || id == RADEON_EMIT_PP_TXFILTER_1 ||
+ id == RADEON_EMIT_PP_TXFILTER_2 /*|| id == RADEON_EMIT_PP_TXFILTER_3 ||
+ id == RADEON_EMIT_PP_TXFILTER_4 || id == RADEON_EMIT_PP_TXFILTER_5*/ ) &&
+ radeon_check_and_fixup_offset_user( dev_priv, filp_priv,
+ &data[( RADEON_PP_TXOFFSET_0
+ - RADEON_PP_TXFILTER_0 ) / 4] ) ) {
+ DRM_ERROR( "Invalid R100 texture offset\n" );
+ return DRM_ERR( EINVAL );
+ } else if ( id == R200_PP_CUBIC_OFFSET_F1_0 || id == R200_PP_CUBIC_OFFSET_F1_1 ||
+ id == R200_PP_CUBIC_OFFSET_F1_2 || id == R200_PP_CUBIC_OFFSET_F1_3 ||
+ id == R200_PP_CUBIC_OFFSET_F1_4 || id == R200_PP_CUBIC_OFFSET_F1_5 ) {
+ int i;
+ for ( i = 0; i < 6; i++ ) {
+ if ( radeon_check_and_fixup_offset_user( dev_priv,
+ filp_priv,
+ &data[i] ) ) {
+ DRM_ERROR( "Invalid R200 cubic texture offset\n" );
+ return DRM_ERR( EINVAL );
+ }
+ }
+ }
+
+ return 0;
+}
+
+static __inline__ int radeon_check_and_fixup_packet3( drm_radeon_private_t *dev_priv,
+ drm_file_t *filp_priv,
+ drm_radeon_cmd_buffer_t *cmdbuf,
+ unsigned int *cmdsz ) {
+ u32 tmp[4], *cmd = ( u32* )cmdbuf->buf;
+
+ if ( DRM_COPY_FROM_USER_UNCHECKED( tmp, cmd, sizeof( tmp ) ) ) {
+ DRM_ERROR( "Failed to copy data from user space\n" );
+ return DRM_ERR( EFAULT );
+ }
+
+ *cmdsz = 2 + ( ( tmp[0] & RADEON_CP_PACKET_COUNT_MASK ) >> 16 );
+
+ if ( ( tmp[0] & 0xc0000000 ) != RADEON_CP_PACKET3 ) {
+ DRM_ERROR( "Not a type 3 packet\n" );
+ return DRM_ERR( EINVAL );
+ }
+
+ if ( 4 * *cmdsz > cmdbuf->bufsz ) {
+ DRM_ERROR( "Packet size larger than size of data provided\n" );
+ return DRM_ERR( EINVAL );
+ }
+
+ /* Check client state and fix it up if necessary */
+ if ( tmp[0] & 0x8000 ) { /* MSB of opcode: next DWORD GUI_CNTL */
+ u32 offset;
+
+ if ( tmp[1] & ( RADEON_GMC_SRC_PITCH_OFFSET_CNTL
+ | RADEON_GMC_DST_PITCH_OFFSET_CNTL ) ) {
+ offset = tmp[2] << 10;
+ if ( radeon_check_and_fixup_offset( dev_priv, filp_priv, &offset ) ) {
+ DRM_ERROR( "Invalid first packet offset\n" );
+ return DRM_ERR( EINVAL );
+ }
+ tmp[2] = ( tmp[2] & 0xffc00000 ) | offset >> 10;
+ }
+
+ if ( ( tmp[1] & RADEON_GMC_SRC_PITCH_OFFSET_CNTL ) &&
+ ( tmp[1] & RADEON_GMC_DST_PITCH_OFFSET_CNTL ) ) {
+ offset = tmp[3] << 10;
+ if ( radeon_check_and_fixup_offset( dev_priv, filp_priv, &offset ) ) {
+ DRM_ERROR( "Invalid second packet offset\n" );
+ return DRM_ERR( EINVAL );
+ }
+ tmp[3] = ( tmp[3] & 0xffc00000 ) | offset >> 10;
+ }
+
+ if ( DRM_COPY_TO_USER_UNCHECKED( cmd, tmp, sizeof( tmp ) ) ) {
+ DRM_ERROR( "Failed to copy data to user space\n" );
+ return DRM_ERR( EFAULT );
+ }
+ }
+
+ return 0;
+}
+
+
+/* ================================================================
* CP hardware state programming functions
*/
@@ -57,15 +202,28 @@ static __inline__ void radeon_emit_clip_rect( drm_radeon_private_t *dev_priv,
/* Emit 1.1 state
*/
-static void radeon_emit_state( drm_radeon_private_t *dev_priv,
- drm_radeon_context_regs_t *ctx,
- drm_radeon_texture_regs_t *tex,
- unsigned int dirty )
+static int radeon_emit_state( drm_radeon_private_t *dev_priv,
+ drm_file_t *filp_priv,
+ drm_radeon_context_regs_t *ctx,
+ drm_radeon_texture_regs_t *tex,
+ unsigned int dirty )
{
RING_LOCALS;
DRM_DEBUG( "dirty=0x%08x\n", dirty );
if ( dirty & RADEON_UPLOAD_CONTEXT ) {
+ if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
+ &ctx->rb3d_depthoffset ) ) {
+ DRM_ERROR( "Invalid depth buffer offset\n" );
+ return DRM_ERR( EINVAL );
+ }
+
+ if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
+ &ctx->rb3d_coloroffset ) ) {
+ DRM_ERROR( "Invalid depth buffer offset\n" );
+ return DRM_ERR( EINVAL );
+ }
+
BEGIN_RING( 14 );
OUT_RING( CP_PACKET0( RADEON_PP_MISC, 6 ) );
OUT_RING( ctx->pp_misc );
@@ -149,6 +307,12 @@ static void radeon_emit_state( drm_radeon_private_t *dev_priv,
}
if ( dirty & RADEON_UPLOAD_TEX0 ) {
+ if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
+ &tex[0].pp_txoffset ) ) {
+ DRM_ERROR( "Invalid texture offset for unit 0\n" );
+ return DRM_ERR( EINVAL );
+ }
+
BEGIN_RING( 9 );
OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_0, 5 ) );
OUT_RING( tex[0].pp_txfilter );
@@ -163,6 +327,12 @@ static void radeon_emit_state( drm_radeon_private_t *dev_priv,
}
if ( dirty & RADEON_UPLOAD_TEX1 ) {
+ if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
+ &tex[1].pp_txoffset ) ) {
+ DRM_ERROR( "Invalid texture offset for unit 1\n" );
+ return DRM_ERR( EINVAL );
+ }
+
BEGIN_RING( 9 );
OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_1, 5 ) );
OUT_RING( tex[1].pp_txfilter );
@@ -177,6 +347,12 @@ static void radeon_emit_state( drm_radeon_private_t *dev_priv,
}
if ( dirty & RADEON_UPLOAD_TEX2 ) {
+ if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
+ &tex[2].pp_txoffset ) ) {
+ DRM_ERROR( "Invalid texture offset for unit 2\n" );
+ return DRM_ERR( EINVAL );
+ }
+
BEGIN_RING( 9 );
OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_2, 5 ) );
OUT_RING( tex[2].pp_txfilter );
@@ -189,12 +365,15 @@ static void radeon_emit_state( drm_radeon_private_t *dev_priv,
OUT_RING( tex[2].pp_border_color );
ADVANCE_RING();
}
+
+ return 0;
}
/* Emit 1.2 state
*/
-static void radeon_emit_state2( drm_radeon_private_t *dev_priv,
- drm_radeon_state_t *state )
+static int radeon_emit_state2( drm_radeon_private_t *dev_priv,
+ drm_file_t *filp_priv,
+ drm_radeon_state_t *state )
{
RING_LOCALS;
@@ -206,7 +385,7 @@ static void radeon_emit_state2( drm_radeon_private_t *dev_priv,
ADVANCE_RING();
}
- radeon_emit_state( dev_priv, &state->context,
+ return radeon_emit_state( dev_priv, filp_priv, &state->context,
state->tex, state->dirty );
}
@@ -1065,6 +1244,7 @@ static int radeon_cp_dispatch_texture( DRMFILE filp,
drm_radeon_tex_image_t *image )
{
drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_file_t *filp_priv;
drm_buf_t *buf;
u32 format;
u32 *buffer;
@@ -1074,6 +1254,13 @@ static int radeon_cp_dispatch_texture( DRMFILE filp,
int i;
RING_LOCALS;
+ DRM_GET_PRIV_WITH_RETURN( filp_priv, filp );
+
+ if ( radeon_check_and_fixup_offset( dev_priv, filp_priv, &tex->offset ) ) {
+ DRM_ERROR( "Invalid destination offset\n" );
+ return DRM_ERR( EINVAL );
+ }
+
dev_priv->stats.boxes |= RADEON_BOX_TEXTURE_LOAD;
/* Flush the pixel cache. This ensures no pixel data gets mixed
@@ -1377,6 +1564,7 @@ int radeon_cp_vertex( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_file_t *filp_priv;
drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
drm_device_dma_t *dma = dev->dma;
drm_buf_t *buf;
@@ -1390,6 +1578,8 @@ int radeon_cp_vertex( DRM_IOCTL_ARGS )
return DRM_ERR(EINVAL);
}
+ DRM_GET_PRIV_WITH_RETURN( filp_priv, filp );
+
DRM_COPY_FROM_USER_IOCTL( vertex, (drm_radeon_vertex_t *)data,
sizeof(vertex) );
@@ -1429,11 +1619,14 @@ int radeon_cp_vertex( DRM_IOCTL_ARGS )
buf->used = vertex.count; /* not used? */
if ( sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS ) {
- radeon_emit_state( dev_priv,
- &sarea_priv->context_state,
- sarea_priv->tex_state,
- sarea_priv->dirty );
-
+ if ( radeon_emit_state( dev_priv, filp_priv,
+ &sarea_priv->context_state,
+ sarea_priv->tex_state,
+ sarea_priv->dirty ) ) {
+ DRM_ERROR( "radeon_emit_state failed\n" );
+ return DRM_ERR( EINVAL );
+ }
+
sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES |
RADEON_UPLOAD_TEX1IMAGES |
RADEON_UPLOAD_TEX2IMAGES |
@@ -1461,6 +1654,7 @@ int radeon_cp_indices( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_file_t *filp_priv;
drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
drm_device_dma_t *dma = dev->dma;
drm_buf_t *buf;
@@ -1475,6 +1669,8 @@ int radeon_cp_indices( DRM_IOCTL_ARGS )
return DRM_ERR(EINVAL);
}
+ DRM_GET_PRIV_WITH_RETURN( filp_priv, filp );
+
DRM_COPY_FROM_USER_IOCTL( elts, (drm_radeon_indices_t *)data,
sizeof(elts) );
@@ -1523,10 +1719,13 @@ int radeon_cp_indices( DRM_IOCTL_ARGS )
buf->used = elts.end;
if ( sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS ) {
- radeon_emit_state( dev_priv,
- &sarea_priv->context_state,
- sarea_priv->tex_state,
- sarea_priv->dirty );
+ if ( radeon_emit_state( dev_priv, filp_priv,
+ &sarea_priv->context_state,
+ sarea_priv->tex_state,
+ sarea_priv->dirty ) ) {
+ DRM_ERROR( "radeon_emit_state failed\n" );
+ return DRM_ERR( EINVAL );
+ }
sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES |
RADEON_UPLOAD_TEX1IMAGES |
@@ -1686,6 +1885,7 @@ int radeon_cp_vertex2( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_file_t *filp_priv;
drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
drm_device_dma_t *dma = dev->dma;
drm_buf_t *buf;
@@ -1700,6 +1900,8 @@ int radeon_cp_vertex2( DRM_IOCTL_ARGS )
return DRM_ERR(EINVAL);
}
+ DRM_GET_PRIV_WITH_RETURN( filp_priv, filp );
+
DRM_COPY_FROM_USER_IOCTL( vertex, (drm_radeon_vertex2_t *)data,
sizeof(vertex) );
@@ -1747,7 +1949,10 @@ int radeon_cp_vertex2( DRM_IOCTL_ARGS )
sizeof(state) ) )
return DRM_ERR(EFAULT);
- radeon_emit_state2( dev_priv, &state );
+ if ( radeon_emit_state2( dev_priv, filp_priv, &state ) ) {
+ DRM_ERROR( "radeon_emit_state2 failed\n" );
+ return DRM_ERR( EINVAL );
+ }
laststate = prim.stateidx;
}
@@ -1784,6 +1989,7 @@ int radeon_cp_vertex2( DRM_IOCTL_ARGS )
static int radeon_emit_packets(
drm_radeon_private_t *dev_priv,
+ drm_file_t *filp_priv,
drm_radeon_cmd_header_t header,
drm_radeon_cmd_buffer_t *cmdbuf )
{
@@ -1798,8 +2004,15 @@ static int radeon_emit_packets(
sz = packet[id].len;
reg = packet[id].start;
- if (sz * sizeof(int) > cmdbuf->bufsz)
+ if (sz * sizeof(int) > cmdbuf->bufsz) {
+ DRM_ERROR( "Packet size provided larger than data provided\n" );
return DRM_ERR(EINVAL);
+ }
+
+ if ( radeon_check_and_fixup_packets( dev_priv, filp_priv, id, data ) ) {
+ DRM_ERROR( "Packet verification failed\n" );
+ return DRM_ERR( EINVAL );
+ }
BEGIN_RING(sz+1);
OUT_RING( CP_PACKET0( reg, (sz-1) ) );
@@ -1882,24 +2095,21 @@ static __inline__ int radeon_emit_vectors(
static int radeon_emit_packet3( drm_device_t *dev,
+ drm_file_t *filp_priv,
drm_radeon_cmd_buffer_t *cmdbuf )
{
drm_radeon_private_t *dev_priv = dev->dev_private;
- int cmdsz, tmp;
- int *cmd = (int *)cmdbuf->buf;
+ unsigned int cmdsz;
+ int *cmd = (int *)cmdbuf->buf, ret;
RING_LOCALS;
-
DRM_DEBUG("\n");
- if (DRM_GET_USER_UNCHECKED( tmp, &cmd[0]))
- return DRM_ERR(EFAULT);
-
- cmdsz = 2 + ((tmp & RADEON_CP_PACKET_COUNT_MASK) >> 16);
-
- if ((tmp & 0xc0000000) != RADEON_CP_PACKET3 ||
- cmdsz * 4 > cmdbuf->bufsz)
- return DRM_ERR(EINVAL);
+ if ( ( ret = radeon_check_and_fixup_packet3( dev_priv, filp_priv,
+ cmdbuf, &cmdsz ) ) ) {
+ DRM_ERROR( "Packet verification failed\n" );
+ return ret;
+ }
BEGIN_RING( cmdsz );
OUT_RING_USER_TABLE( cmd, cmdsz );
@@ -1912,27 +2122,25 @@ static int radeon_emit_packet3( drm_device_t *dev,
static int radeon_emit_packet3_cliprect( drm_device_t *dev,
+ drm_file_t *filp_priv,
drm_radeon_cmd_buffer_t *cmdbuf,
int orig_nbox )
{
drm_radeon_private_t *dev_priv = dev->dev_private;
drm_clip_rect_t box;
- int cmdsz, tmp;
- int *cmd = (int *)cmdbuf->buf;
+ unsigned int cmdsz;
+ int *cmd = (int *)cmdbuf->buf, ret;
drm_clip_rect_t *boxes = cmdbuf->boxes;
int i = 0;
RING_LOCALS;
DRM_DEBUG("\n");
- if (DRM_GET_USER_UNCHECKED( tmp, &cmd[0]))
- return DRM_ERR(EFAULT);
-
- cmdsz = 2 + ((tmp & RADEON_CP_PACKET_COUNT_MASK) >> 16);
-
- if ((tmp & 0xc0000000) != RADEON_CP_PACKET3 ||
- cmdsz * 4 > cmdbuf->bufsz)
- return DRM_ERR(EINVAL);
+ if ( ( ret = radeon_check_and_fixup_packet3( dev_priv, filp_priv,
+ cmdbuf, &cmdsz ) ) ) {
+ DRM_ERROR( "Packet verification failed\n" );
+ return ret;
+ }
if (!orig_nbox)
goto out;
@@ -2009,6 +2217,7 @@ int radeon_cp_cmdbuf( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_file_t *filp_priv;
drm_device_dma_t *dma = dev->dma;
drm_buf_t *buf = 0;
int idx;
@@ -2023,6 +2232,8 @@ int radeon_cp_cmdbuf( DRM_IOCTL_ARGS )
return DRM_ERR(EINVAL);
}
+ DRM_GET_PRIV_WITH_RETURN( filp_priv, filp );
+
DRM_COPY_FROM_USER_IOCTL( cmdbuf, (drm_radeon_cmd_buffer_t *)data,
sizeof(cmdbuf) );
@@ -2053,7 +2264,7 @@ int radeon_cp_cmdbuf( DRM_IOCTL_ARGS )
switch (header.header.cmd_type) {
case RADEON_CMD_PACKET:
DRM_DEBUG("RADEON_CMD_PACKET\n");
- if (radeon_emit_packets( dev_priv, header, &cmdbuf )) {
+ if (radeon_emit_packets( dev_priv, filp_priv, header, &cmdbuf )) {
DRM_ERROR("radeon_emit_packets failed\n");
return DRM_ERR(EINVAL);
}
@@ -2096,7 +2307,7 @@ int radeon_cp_cmdbuf( DRM_IOCTL_ARGS )
case RADEON_CMD_PACKET3:
DRM_DEBUG("RADEON_CMD_PACKET3\n");
- if (radeon_emit_packet3( dev, &cmdbuf )) {
+ if (radeon_emit_packet3( dev, filp_priv, &cmdbuf )) {
DRM_ERROR("radeon_emit_packet3 failed\n");
return DRM_ERR(EINVAL);
}
@@ -2104,7 +2315,7 @@ int radeon_cp_cmdbuf( DRM_IOCTL_ARGS )
case RADEON_CMD_PACKET3_CLIP:
DRM_DEBUG("RADEON_CMD_PACKET3_CLIP\n");
- if (radeon_emit_packet3_cliprect( dev, &cmdbuf, orig_nbox )) {
+ if (radeon_emit_packet3_cliprect( dev, filp_priv, &cmdbuf, orig_nbox )) {
DRM_ERROR("radeon_emit_packet3_clip failed\n");
return DRM_ERR(EINVAL);
}
@@ -2203,3 +2414,31 @@ int radeon_cp_getparam( DRM_IOCTL_ARGS )
return 0;
}
+
+int radeon_cp_setparam( DRM_IOCTL_ARGS ) {
+ DRM_DEVICE;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_file_t *filp_priv;
+ drm_radeon_setparam_t sp;
+
+ if ( !dev_priv ) {
+ DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+ return DRM_ERR( EINVAL );
+ }
+
+ DRM_GET_PRIV_WITH_RETURN( filp_priv, filp );
+
+ DRM_COPY_FROM_USER_IOCTL( sp, ( drm_radeon_setparam_t* )data,
+ sizeof( sp ) );
+
+ switch( sp.param ) {
+ case RADEON_SETPARAM_FB_LOCATION:
+ filp_priv->radeon_fb_delta = dev_priv->fb_location - sp.value;
+ break;
+ default:
+ DRM_DEBUG( "Invalid parameter %d\n", sp.param );
+ return DRM_ERR( EINVAL );
+ }
+
+ return 0;
+}