diff options
| -rw-r--r-- | drivers/char/drm/r300_cmdbuf.c | 67 | ||||
| -rw-r--r-- | drivers/char/drm/radeon_drm.h | 4 | ||||
| -rw-r--r-- | drivers/char/drm/radeon_drv.h | 5 |
3 files changed, 75 insertions, 1 deletions
diff --git a/drivers/char/drm/r300_cmdbuf.c b/drivers/char/drm/r300_cmdbuf.c index 20b6cb39213d..b108c7f913b2 100644 --- a/drivers/char/drm/r300_cmdbuf.c +++ b/drivers/char/drm/r300_cmdbuf.c | |||
| @@ -704,6 +704,64 @@ static void r300_discard_buffer(drm_device_t * dev, drm_buf_t * buf) | |||
| 704 | buf->used = 0; | 704 | buf->used = 0; |
| 705 | } | 705 | } |
| 706 | 706 | ||
| 707 | static int r300_scratch(drm_radeon_private_t *dev_priv, | ||
| 708 | drm_radeon_kcmd_buffer_t *cmdbuf, | ||
| 709 | drm_r300_cmd_header_t header) | ||
| 710 | { | ||
| 711 | u32 *ref_age_base; | ||
| 712 | u32 i, buf_idx, h_pending; | ||
| 713 | RING_LOCALS; | ||
| 714 | |||
| 715 | if (cmdbuf->bufsz < | ||
| 716 | (sizeof(u64) + header.scratch.n_bufs * sizeof(buf_idx))) { | ||
| 717 | return DRM_ERR(EINVAL); | ||
| 718 | } | ||
| 719 | |||
| 720 | if (header.scratch.reg >= 5) { | ||
| 721 | return DRM_ERR(EINVAL); | ||
| 722 | } | ||
| 723 | |||
| 724 | dev_priv->scratch_ages[header.scratch.reg]++; | ||
| 725 | |||
| 726 | ref_age_base = *(u32 **)cmdbuf->buf; | ||
| 727 | |||
| 728 | cmdbuf->buf += sizeof(u64); | ||
| 729 | cmdbuf->bufsz -= sizeof(u64); | ||
| 730 | |||
| 731 | for (i=0; i < header.scratch.n_bufs; i++) { | ||
| 732 | buf_idx = *(u32 *)cmdbuf->buf; | ||
| 733 | buf_idx *= 2; /* 8 bytes per buf */ | ||
| 734 | |||
| 735 | if (DRM_COPY_TO_USER(ref_age_base + buf_idx, &dev_priv->scratch_ages[header.scratch.reg], sizeof(u32))) { | ||
| 736 | return DRM_ERR(EINVAL); | ||
| 737 | } | ||
| 738 | |||
| 739 | if (DRM_COPY_FROM_USER(&h_pending, ref_age_base + buf_idx + 1, sizeof(u32))) { | ||
| 740 | return DRM_ERR(EINVAL); | ||
| 741 | } | ||
| 742 | |||
| 743 | if (h_pending == 0) { | ||
| 744 | return DRM_ERR(EINVAL); | ||
| 745 | } | ||
| 746 | |||
| 747 | h_pending--; | ||
| 748 | |||
| 749 | if (DRM_COPY_TO_USER(ref_age_base + buf_idx + 1, &h_pending, sizeof(u32))) { | ||
| 750 | return DRM_ERR(EINVAL); | ||
| 751 | } | ||
| 752 | |||
| 753 | cmdbuf->buf += sizeof(buf_idx); | ||
| 754 | cmdbuf->bufsz -= sizeof(buf_idx); | ||
| 755 | } | ||
| 756 | |||
| 757 | BEGIN_RING(2); | ||
| 758 | OUT_RING(CP_PACKET0(RADEON_SCRATCH_REG0 + header.scratch.reg * 4, 0)); | ||
| 759 | OUT_RING(dev_priv->scratch_ages[header.scratch.reg]); | ||
| 760 | ADVANCE_RING(); | ||
| 761 | |||
| 762 | return 0; | ||
| 763 | } | ||
| 764 | |||
| 707 | /** | 765 | /** |
| 708 | * Parses and validates a user-supplied command buffer and emits appropriate | 766 | * Parses and validates a user-supplied command buffer and emits appropriate |
| 709 | * commands on the DMA ring buffer. | 767 | * commands on the DMA ring buffer. |
| @@ -841,6 +899,15 @@ int r300_do_cp_cmdbuf(drm_device_t *dev, | |||
| 841 | } | 899 | } |
| 842 | break; | 900 | break; |
| 843 | 901 | ||
| 902 | case R300_CMD_SCRATCH: | ||
| 903 | DRM_DEBUG("R300_CMD_SCRATCH\n"); | ||
| 904 | ret = r300_scratch(dev_priv, cmdbuf, header); | ||
| 905 | if (ret) { | ||
| 906 | DRM_ERROR("r300_scratch failed\n"); | ||
| 907 | goto cleanup; | ||
| 908 | } | ||
| 909 | break; | ||
| 910 | |||
| 844 | default: | 911 | default: |
| 845 | DRM_ERROR("bad cmd_type %i at %p\n", | 912 | DRM_ERROR("bad cmd_type %i at %p\n", |
| 846 | header.header.cmd_type, | 913 | header.header.cmd_type, |
diff --git a/drivers/char/drm/radeon_drm.h b/drivers/char/drm/radeon_drm.h index bb63e6806fd1..c8e279e89c2e 100644 --- a/drivers/char/drm/radeon_drm.h +++ b/drivers/char/drm/radeon_drm.h | |||
| @@ -222,6 +222,7 @@ typedef union { | |||
| 222 | # define R300_WAIT_3D 0x2 | 222 | # define R300_WAIT_3D 0x2 |
| 223 | # define R300_WAIT_2D_CLEAN 0x3 | 223 | # define R300_WAIT_2D_CLEAN 0x3 |
| 224 | # define R300_WAIT_3D_CLEAN 0x4 | 224 | # define R300_WAIT_3D_CLEAN 0x4 |
| 225 | #define R300_CMD_SCRATCH 8 | ||
| 225 | 226 | ||
| 226 | typedef union { | 227 | typedef union { |
| 227 | unsigned int u; | 228 | unsigned int u; |
| @@ -247,6 +248,9 @@ typedef union { | |||
| 247 | struct { | 248 | struct { |
| 248 | unsigned char cmd_type, flags, pad0, pad1; | 249 | unsigned char cmd_type, flags, pad0, pad1; |
| 249 | } wait; | 250 | } wait; |
| 251 | struct { | ||
| 252 | unsigned char cmd_type, reg, n_bufs, flags; | ||
| 253 | } scratch; | ||
| 250 | } drm_r300_cmd_header_t; | 254 | } drm_r300_cmd_header_t; |
| 251 | 255 | ||
| 252 | #define RADEON_FRONT 0x1 | 256 | #define RADEON_FRONT 0x1 |
diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h index a0c198895a27..5cf555e4637b 100644 --- a/drivers/char/drm/radeon_drv.h +++ b/drivers/char/drm/radeon_drv.h | |||
| @@ -92,9 +92,10 @@ | |||
| 92 | * 1.21- Add support for card type getparam | 92 | * 1.21- Add support for card type getparam |
| 93 | * 1.22- Add support for texture cache flushes (R300_TX_CNTL) | 93 | * 1.22- Add support for texture cache flushes (R300_TX_CNTL) |
| 94 | * 1.23- Add new radeon memory map work from benh | 94 | * 1.23- Add new radeon memory map work from benh |
| 95 | * 1.24- Add general-purpose packet for manipulating scratch registers (r300) | ||
| 95 | */ | 96 | */ |
| 96 | #define DRIVER_MAJOR 1 | 97 | #define DRIVER_MAJOR 1 |
| 97 | #define DRIVER_MINOR 23 | 98 | #define DRIVER_MINOR 24 |
| 98 | #define DRIVER_PATCHLEVEL 0 | 99 | #define DRIVER_PATCHLEVEL 0 |
| 99 | 100 | ||
| 100 | /* | 101 | /* |
| @@ -276,6 +277,8 @@ typedef struct drm_radeon_private { | |||
| 276 | unsigned long pcigart_offset; | 277 | unsigned long pcigart_offset; |
| 277 | drm_ati_pcigart_info gart_info; | 278 | drm_ati_pcigart_info gart_info; |
| 278 | 279 | ||
| 280 | u32 scratch_ages[5]; | ||
| 281 | |||
| 279 | /* starting from here on, data is preserved accross an open */ | 282 | /* starting from here on, data is preserved accross an open */ |
| 280 | uint32_t flags; /* see radeon_chip_flags */ | 283 | uint32_t flags; /* see radeon_chip_flags */ |
| 281 | } drm_radeon_private_t; | 284 | } drm_radeon_private_t; |
