static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t *
dev_priv,
- drm_file_t * filp_priv,
+ struct drm_file * filp_priv,
u32 *offset)
{
u64 off = *offset;
- u32 fb_start = dev_priv->fb_location;
- u32 fb_end = fb_start + dev_priv->fb_size - 1;
- u32 gart_start = dev_priv->gart_vm_start;
- u32 gart_end = gart_start + dev_priv->gart_size - 1;
+ u32 fb_end = dev_priv->fb_location + dev_priv->fb_size - 1;
struct drm_radeon_driver_file_fields *radeon_priv;
/* Hrm ... the story of the offset ... So this function converts
/* First, the best case, the offset already lands in either the
* framebuffer or the GART mapped space
*/
- if ((off >= fb_start && off <= fb_end) ||
- (off >= gart_start && off <= gart_end))
+ if (radeon_check_offset(dev_priv, off))
return 0;
/* Ok, that didn't happen... now check if we have a zero based
/* Finally, assume we aimed at a GART offset if beyond the fb */
if (off > fb_end)
- off = off - fb_end - 1 + gart_start;
+ off = off - fb_end - 1 + dev_priv->gart_vm_start;
/* Now recheck and fail if out of bounds */
- if ((off >= fb_start && off <= fb_end) ||
- (off >= gart_start && off <= gart_end)) {
+ if (radeon_check_offset(dev_priv, off)) {
DRM_DEBUG("offset fixed up to 0x%x\n", (unsigned int)off);
*offset = off;
return 0;
static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
dev_priv,
- drm_file_t * filp_priv,
+ struct drm_file * filp_priv,
int id, u32 *data)
{
switch (id) {
static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
dev_priv,
- drm_file_t *filp_priv,
+ struct drm_file *filp_priv,
drm_radeon_kcmd_buffer_t *
cmdbuf,
unsigned int *cmdsz)
{
u32 *cmd = (u32 *) cmdbuf->buf;
+ u32 offset, narrays;
+ int count, i, k;
*cmdsz = 2 + ((cmd[0] & RADEON_CP_PACKET_COUNT_MASK) >> 16);
return DRM_ERR(EINVAL);
}
- /* Check client state and fix it up if necessary */
- if (cmd[0] & 0x8000) { /* MSB of opcode: next DWORD GUI_CNTL */
- u32 offset;
+ switch(cmd[0] & 0xff00) {
+ /* XXX Are there old drivers needing other packets? */
+ case RADEON_3D_DRAW_IMMD:
+ case RADEON_3D_DRAW_VBUF:
+ case RADEON_3D_DRAW_INDX:
+ case RADEON_WAIT_FOR_IDLE:
+ case RADEON_CP_NOP:
+ case RADEON_3D_CLEAR_ZMASK:
+/* case RADEON_CP_NEXT_CHAR:
+ case RADEON_CP_PLY_NEXTSCAN:
+ case RADEON_CP_SET_SCISSORS: */ /* probably safe but will never need them? */
+ /* these packets are safe */
+ break;
+
+ case RADEON_CP_3D_DRAW_IMMD_2:
+ case RADEON_CP_3D_DRAW_VBUF_2:
+ case RADEON_CP_3D_DRAW_INDX_2:
+ case RADEON_3D_CLEAR_HIZ:
+ /* safe but r200 only */
+ if (dev_priv->microcode_version != UCODE_R200) {
+ DRM_ERROR("Invalid 3d packet for r100-class chip\n");
+ return DRM_ERR(EINVAL);
+ }
+ break;
+
+ case RADEON_3D_LOAD_VBPNTR:
+ count = (cmd[0] >> 16) & 0x3fff;
+
+ if (count > 18) { /* 12 arrays max */
+ DRM_ERROR("Too large payload in 3D_LOAD_VBPNTR (count=%d)\n",
+ count);
+ return DRM_ERR(EINVAL);
+ }
+
+ /* carefully check packet contents */
+ narrays = cmd[1] & ~0xc000;
+ k = 0;
+ i = 2;
+ while ((k < narrays) && (i < (count + 2))) {
+ i++; /* skip attribute field */
+ if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &cmd[i])) {
+ DRM_ERROR
+ ("Invalid offset (k=%d i=%d) in 3D_LOAD_VBPNTR packet.\n",
+ k, i);
+ return DRM_ERR(EINVAL);
+ }
+ k++;
+ i++;
+ if (k == narrays)
+ break;
+ /* have one more to process, they come in pairs */
+ if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &cmd[i])) {
+ DRM_ERROR
+ ("Invalid offset (k=%d i=%d) in 3D_LOAD_VBPNTR packet.\n",
+ k, i);
+ return DRM_ERR(EINVAL);
+ }
+ k++;
+ i++;
+ }
+ /* do the counts match what we expect ? */
+ if ((k != narrays) || (i != (count + 2))) {
+ DRM_ERROR
+ ("Malformed 3D_LOAD_VBPNTR packet (k=%d i=%d narrays=%d count+1=%d).\n",
+ k, i, narrays, count + 1);
+ return DRM_ERR(EINVAL);
+ }
+ break;
+
+ case RADEON_3D_RNDR_GEN_INDX_PRIM:
+ if (dev_priv->microcode_version != UCODE_R100) {
+ DRM_ERROR("Invalid 3d packet for r200-class chip\n");
+ return DRM_ERR(EINVAL);
+ }
+ if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &cmd[1])) {
+ DRM_ERROR("Invalid rndr_gen_indx offset\n");
+ return DRM_ERR(EINVAL);
+ }
+ break;
+
+ case RADEON_CP_INDX_BUFFER:
+ if (dev_priv->microcode_version != UCODE_R200) {
+ DRM_ERROR("Invalid 3d packet for r100-class chip\n");
+ return DRM_ERR(EINVAL);
+ }
+ if ((cmd[1] & 0x8000ffff) != 0x80000810) {
+ DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]);
+ return DRM_ERR(EINVAL);
+ }
+ if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &cmd[2])) {
+ DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]);
+ return DRM_ERR(EINVAL);
+ }
+ break;
+
+ case RADEON_CNTL_HOSTDATA_BLT:
+ case RADEON_CNTL_PAINT_MULTI:
+ case RADEON_CNTL_BITBLT_MULTI:
+ /* MSB of opcode: next DWORD GUI_CNTL */
if (cmd[1] & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL
| RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
offset = cmd[2] << 10;
}
cmd[3] = (cmd[3] & 0xffc00000) | offset >> 10;
}
+ break;
+
+ default:
+ DRM_ERROR("Invalid packet type %x\n", cmd[0] & 0xff00);
+ return DRM_ERR(EINVAL);
}
return 0;
*/
static __inline__ void radeon_emit_clip_rect(drm_radeon_private_t * dev_priv,
- drm_clip_rect_t * box)
+ struct drm_clip_rect * box)
{
RING_LOCALS;
/* Emit 1.1 state
*/
static int radeon_emit_state(drm_radeon_private_t * dev_priv,
- drm_file_t * filp_priv,
+ struct drm_file * filp_priv,
drm_radeon_context_regs_t * ctx,
drm_radeon_texture_regs_t * tex,
unsigned int dirty)
/* Emit 1.2 state
*/
static int radeon_emit_state2(drm_radeon_private_t * dev_priv,
- drm_file_t * filp_priv,
+ struct drm_file * filp_priv,
drm_radeon_state_t * state)
{
RING_LOCALS;
RADEON_GMC_SRC_DATATYPE_COLOR |
RADEON_ROP3_P | RADEON_GMC_CLR_CMP_CNTL_DIS);
- if (dev_priv->page_flipping && dev_priv->current_page == 1) {
+ if (dev_priv->sarea_priv->pfCurrentPage == 1) {
OUT_RING(dev_priv->front_pitch_offset);
} else {
OUT_RING(dev_priv->back_pitch_offset);
* CP command dispatch functions
*/
-static void radeon_cp_dispatch_clear(drm_device_t * dev,
+static void radeon_cp_dispatch_clear(struct drm_device * dev,
drm_radeon_clear_t * clear,
drm_radeon_clear_rect_t * depth_boxes)
{
drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
drm_radeon_depth_clear_t *depth_clear = &dev_priv->depth_clear;
int nbox = sarea_priv->nbox;
- drm_clip_rect_t *pbox = sarea_priv->boxes;
+ struct drm_clip_rect *pbox = sarea_priv->boxes;
unsigned int flags = clear->flags;
u32 rb3d_cntl = 0, rb3d_stencilrefmask = 0;
int i;
dev_priv->stats.clears++;
- if (dev_priv->page_flipping && dev_priv->current_page == 1) {
+ if (dev_priv->sarea_priv->pfCurrentPage == 1) {
unsigned int tmp = flags;
flags &= ~(RADEON_FRONT | RADEON_BACK);
ADVANCE_RING();
}
-static void radeon_cp_dispatch_swap(drm_device_t * dev)
+static void radeon_cp_dispatch_swap(struct drm_device * dev)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
int nbox = sarea_priv->nbox;
- drm_clip_rect_t *pbox = sarea_priv->boxes;
+ struct drm_clip_rect *pbox = sarea_priv->boxes;
int i;
RING_LOCALS;
DRM_DEBUG("\n");
/* Make this work even if front & back are flipped:
*/
OUT_RING(CP_PACKET0(RADEON_SRC_PITCH_OFFSET, 1));
- if (dev_priv->current_page == 0) {
+ if (dev_priv->sarea_priv->pfCurrentPage == 0) {
OUT_RING(dev_priv->back_pitch_offset);
OUT_RING(dev_priv->front_pitch_offset);
} else {
ADVANCE_RING();
}
-static void radeon_cp_dispatch_flip(drm_device_t * dev)
+static void radeon_cp_dispatch_flip(struct drm_device * dev)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
- drm_sarea_t *sarea = (drm_sarea_t *) dev_priv->sarea->handle;
- int offset = (dev_priv->current_page == 1)
+ struct drm_sarea *sarea = (struct drm_sarea *) dev_priv->sarea->handle;
+ int offset = (dev_priv->sarea_priv->pfCurrentPage == 1)
? dev_priv->front_offset : dev_priv->back_offset;
RING_LOCALS;
- DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
+ DRM_DEBUG("%s: pfCurrentPage=%d\n",
__FUNCTION__,
- dev_priv->current_page, dev_priv->sarea_priv->pfCurrentPage);
+ dev_priv->sarea_priv->pfCurrentPage);
/* Do some trivial performance monitoring...
*/
* performing the swapbuffer ioctl.
*/
dev_priv->sarea_priv->last_frame++;
- dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page =
- 1 - dev_priv->current_page;
+ dev_priv->sarea_priv->pfCurrentPage =
+ 1 - dev_priv->sarea_priv->pfCurrentPage;
BEGIN_RING(2);
unsigned int vc_format;
} drm_radeon_tcl_prim_t;
-static void radeon_cp_dispatch_vertex(drm_device_t * dev,
- drm_buf_t * buf,
+static void radeon_cp_dispatch_vertex(struct drm_device * dev,
+ struct drm_buf * buf,
drm_radeon_tcl_prim_t * prim)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
} while (i < nbox);
}
-static void radeon_cp_discard_buffer(drm_device_t * dev, drm_buf_t * buf)
+static void radeon_cp_discard_buffer(struct drm_device * dev, struct drm_buf * buf)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
buf->used = 0;
}
-static void radeon_cp_dispatch_indirect(drm_device_t * dev,
- drm_buf_t * buf, int start, int end)
+static void radeon_cp_dispatch_indirect(struct drm_device * dev,
+ struct drm_buf * buf, int start, int end)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
RING_LOCALS;
}
}
-static void radeon_cp_dispatch_indices(drm_device_t * dev,
- drm_buf_t * elt_buf,
+static void radeon_cp_dispatch_indices(struct drm_device * dev,
+ struct drm_buf * elt_buf,
drm_radeon_tcl_prim_t * prim)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
#define RADEON_MAX_TEXTURE_SIZE RADEON_BUFFER_SIZE
static int radeon_cp_dispatch_texture(DRMFILE filp,
- drm_device_t * dev,
+ struct drm_device * dev,
drm_radeon_texture_t * tex,
drm_radeon_tex_image_t * image)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
- drm_file_t *filp_priv;
- drm_buf_t *buf;
+ struct drm_file *filp_priv;
+ struct drm_buf *buf;
u32 format;
u32 *buffer;
const u8 __user *data;
return 0;
}
-static void radeon_cp_dispatch_stipple(drm_device_t * dev, u32 * stipple)
+static void radeon_cp_dispatch_stipple(struct drm_device * dev, u32 * stipple)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
int i;
/* Not sure why this isn't set all the time:
*/
-static int radeon_do_init_pageflip(drm_device_t * dev)
+static int radeon_do_init_pageflip(struct drm_device * dev)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
RING_LOCALS;
ADVANCE_RING();
dev_priv->page_flipping = 1;
- dev_priv->current_page = 0;
- dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page;
- return 0;
-}
+ if (dev_priv->sarea_priv->pfCurrentPage != 1)
+ dev_priv->sarea_priv->pfCurrentPage = 0;
-/* Called whenever a client dies, from drm_release.
- * NOTE: Lock isn't necessarily held when this is called!
- */
-static int radeon_do_cleanup_pageflip(drm_device_t * dev)
-{
- drm_radeon_private_t *dev_priv = dev->dev_private;
- DRM_DEBUG("\n");
-
- if (dev_priv->current_page != 0)
- radeon_cp_dispatch_flip(dev);
-
- dev_priv->page_flipping = 0;
return 0;
}
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
- drm_file_t *filp_priv;
+ struct drm_file *filp_priv;
drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
- drm_device_dma_t *dma = dev->dma;
- drm_buf_t *buf;
+ struct drm_device_dma *dma = dev->dma;
+ struct drm_buf *buf;
drm_radeon_vertex_t vertex;
drm_radeon_tcl_prim_t prim;
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
- drm_file_t *filp_priv;
+ struct drm_file *filp_priv;
drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
- drm_device_dma_t *dma = dev->dma;
- drm_buf_t *buf;
+ struct drm_device_dma *dma = dev->dma;
+ struct drm_buf *buf;
drm_radeon_indices_t elts;
drm_radeon_tcl_prim_t prim;
int count;
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
- drm_device_dma_t *dma = dev->dma;
- drm_buf_t *buf;
+ struct drm_device_dma *dma = dev->dma;
+ struct drm_buf *buf;
drm_radeon_indirect_t indirect;
RING_LOCALS;
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
- drm_file_t *filp_priv;
+ struct drm_file *filp_priv;
drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
- drm_device_dma_t *dma = dev->dma;
- drm_buf_t *buf;
+ struct drm_device_dma *dma = dev->dma;
+ struct drm_buf *buf;
drm_radeon_vertex2_t vertex;
int i;
unsigned char laststate;
}
static int radeon_emit_packets(drm_radeon_private_t * dev_priv,
- drm_file_t * filp_priv,
+ struct drm_file * filp_priv,
drm_radeon_cmd_header_t header,
drm_radeon_kcmd_buffer_t *cmdbuf)
{
return 0;
}
-static int radeon_emit_packet3(drm_device_t * dev,
- drm_file_t * filp_priv,
+static int radeon_emit_packet3(struct drm_device * dev,
+ struct drm_file * filp_priv,
drm_radeon_kcmd_buffer_t *cmdbuf)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
return 0;
}
-static int radeon_emit_packet3_cliprect(drm_device_t *dev,
- drm_file_t *filp_priv,
+static int radeon_emit_packet3_cliprect(struct drm_device *dev,
+ struct drm_file *filp_priv,
drm_radeon_kcmd_buffer_t *cmdbuf,
int orig_nbox)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
- drm_clip_rect_t box;
+ struct drm_clip_rect box;
unsigned int cmdsz;
int ret;
- drm_clip_rect_t __user *boxes = cmdbuf->boxes;
+ struct drm_clip_rect __user *boxes = cmdbuf->boxes;
int i = 0;
RING_LOCALS;
return 0;
}
-static int radeon_emit_wait(drm_device_t * dev, int flags)
+static int radeon_emit_wait(struct drm_device * dev, int flags)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
RING_LOCALS;
{
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 = NULL;
+ struct drm_file *filp_priv;
+ struct drm_device_dma *dma = dev->dma;
+ struct drm_buf *buf = NULL;
int idx;
drm_radeon_kcmd_buffer_t cmdbuf;
drm_radeon_cmd_header_t header;
else
value = RADEON_CARD_PCI;
break;
+ case RADEON_PARAM_VBLANK_CRTC:
+ value = radeon_vblank_crtc_get(dev);
+ break;
default:
DRM_DEBUG("Invalid parameter %d\n", param.param);
return DRM_ERR(EINVAL);
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
- drm_file_t *filp_priv;
+ struct drm_file *filp_priv;
drm_radeon_setparam_t sp;
struct drm_radeon_driver_file_fields *radeon_priv;
break;
case RADEON_SETPARAM_PCIGART_LOCATION:
dev_priv->pcigart_offset = sp.value;
+ dev_priv->pcigart_offset_set = 1;
break;
case RADEON_SETPARAM_NEW_MEMMAP:
dev_priv->new_memmap = sp.value;
break;
+ case RADEON_SETPARAM_PCIGART_TABLE_SIZE:
+ dev_priv->gart_info.table_size = sp.value;
+ if (dev_priv->gart_info.table_size < RADEON_PCIGART_TABLE_SIZE)
+ dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE;
+ break;
+ case RADEON_SETPARAM_VBLANK_CRTC:
+ return radeon_vblank_crtc_set(dev, sp.value);
+ break;
default:
DRM_DEBUG("Invalid parameter %d\n", sp.param);
return DRM_ERR(EINVAL);
*
* DRM infrastructure takes care of reclaiming dma buffers.
*/
-void radeon_driver_preclose(drm_device_t * dev, DRMFILE filp)
+void radeon_driver_preclose(struct drm_device *dev, DRMFILE filp)
{
if (dev->dev_private) {
drm_radeon_private_t *dev_priv = dev->dev_private;
- if (dev_priv->page_flipping) {
- radeon_do_cleanup_pageflip(dev);
- }
+ dev_priv->page_flipping = 0;
radeon_mem_release(filp, dev_priv->gart_heap);
radeon_mem_release(filp, dev_priv->fb_heap);
radeon_surfaces_release(filp, dev_priv);
}
}
-void radeon_driver_lastclose(drm_device_t * dev)
+void radeon_driver_lastclose(struct drm_device *dev)
{
+ if (dev->dev_private) {
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+
+ if (dev_priv->sarea_priv &&
+ dev_priv->sarea_priv->pfCurrentPage != 0)
+ radeon_cp_dispatch_flip(dev);
+ }
+
radeon_do_release(dev);
}
-int radeon_driver_open(drm_device_t * dev, drm_file_t * filp_priv)
+int radeon_driver_open(struct drm_device *dev, struct drm_file *filp_priv)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
struct drm_radeon_driver_file_fields *radeon_priv;
return 0;
}
-void radeon_driver_postclose(drm_device_t * dev, drm_file_t * filp_priv)
+void radeon_driver_postclose(struct drm_device *dev, struct drm_file *filp_priv)
{
struct drm_radeon_driver_file_fields *radeon_priv =
filp_priv->driver_priv;