From patchwork Tue Jun 9 11:26:44 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrik Jakobsson X-Patchwork-Id: 6571381 Return-Path: X-Original-To: patchwork-intel-gfx@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 11990C0020 for ; Tue, 9 Jun 2015 11:26:14 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 9E083204E2 for ; Tue, 9 Jun 2015 11:26:12 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 0749B204D9 for ; Tue, 9 Jun 2015 11:26:11 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 6FF786E6EE; Tue, 9 Jun 2015 04:26:10 -0700 (PDT) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by gabe.freedesktop.org (Postfix) with ESMTP id 3859889949 for ; Tue, 9 Jun 2015 04:26:06 -0700 (PDT) Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga102.jf.intel.com with ESMTP; 09 Jun 2015 04:26:04 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.13,579,1427785200"; d="scan'208";a="743564471" Received: from rpjakobs-thinkcentre-e73.isw.intel.com ([10.237.180.166]) by orsmga002.jf.intel.com with ESMTP; 09 Jun 2015 04:26:01 -0700 From: Patrik Jakobsson To: strace-devel@lists.sourceforge.net Date: Tue, 9 Jun 2015 13:26:44 +0200 Message-Id: <1433849204-4125-5-git-send-email-patrik.jakobsson@linux.intel.com> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1433849204-4125-1-git-send-email-patrik.jakobsson@linux.intel.com> References: <1433849204-4125-1-git-send-email-patrik.jakobsson@linux.intel.com> Cc: intel-gfx@lists.freedesktop.org, "Dmitry V. Levin" Subject: [Intel-gfx] [PATCH 4/4] drm: Add decoding of DRM and KMS ioctls X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch adds many of the DRM and KMS ioctls. The rest can be added as needed. Signed-off-by: Patrik Jakobsson --- drm.c | 519 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 519 insertions(+) diff --git a/drm.c b/drm.c index fa98fb7..e550c34 100644 --- a/drm.c +++ b/drm.c @@ -82,6 +82,468 @@ int drm_is_driver(struct tcb *tcp, const char *name) return strcmp(name, drv) == 0; } +static int drm_version(struct tcb *tcp, const unsigned int code, long arg) +{ + struct drm_version ver; + char *name, *date, *desc; + int ret; + + if (entering(tcp) || umove(tcp, arg, &ver)) + return 0; + + name = calloc(ver.name_len + 1, 1); + if (!name) + return 0; + ret = umovestr(tcp, (long)ver.name, ver.name_len, name); + if (ret < 0) + goto free_name; + + date = calloc(ver.date_len + 1, 1); + if (!date) + goto free_name; + ret = umovestr(tcp, (long)ver.date, ver.date_len, date); + if (ret < 0) + goto free_date; + + desc = calloc(ver.desc_len + 1, 1); + if (!desc) + goto free_date; + ret = umovestr(tcp, (long)ver.desc, ver.desc_len, desc); + if (ret < 0) + goto free_desc; + + tprintf(", {version_major=%d, version_minor=%d, version_patchlevel=%d, " + "name_len=%lu, name=%s, date_len=%lu, date=%s, " + "desc_len=%lu, desc=%s}", + ver.version_major, ver.version_minor, ver.version_patchlevel, + ver.name_len, name, ver.date_len, date, ver.desc_len, + desc); + +free_desc: + free(desc); +free_date: + free(date); +free_name: + free(name); + + if (ret < 0) + return 0; + + return 1; +} + +static int drm_get_unique(struct tcb *tcp, const unsigned int code, long arg) +{ + struct drm_unique unique; + char *str; + int ret; + + if (entering(tcp) || umove(tcp, arg, &unique)) + return 0; + + str = calloc(unique.unique_len + 1, 1); + if (!str) + return 0; + ret = umovestr(tcp, (long)unique.unique, unique.unique_len, str); + + tprintf(", {unique_len=%lu, unique=%s}", unique.unique_len, str); + + free(str); + + if (ret < 0) + return 0; + + return 1; +} + +static int drm_get_magic(struct tcb *tcp, const unsigned int code, long arg) +{ + struct drm_auth auth; + + if (entering(tcp) || umove(tcp, arg, &auth)) + return 0; + + tprintf(", {magic=%u}", auth.magic); + + return 1; +} + +static int drm_wait_vblank(struct tcb *tcp, const unsigned int code, long arg) +{ + union drm_wait_vblank vblank; + + if (umove(tcp, arg, &vblank)) + return 0; + + if (entering(tcp)) { + tprintf(", {request={type=%u, sequence=%u, signal=%lu}", + vblank.request.type, vblank.request.sequence, + vblank.request.signal); + } else { + tprintf(", reply={type=%u, sequence=%u, tval_sec=%ld, tval_usec=%ld}}", + vblank.reply.type, vblank.reply.sequence, + vblank.reply.tval_sec, vblank.reply.tval_usec); + } + + return 1; +} + +static int drm_mode_get_resources(struct tcb *tcp, const unsigned int code, long arg) +{ + struct drm_mode_card_res res; + + if (entering(tcp) || umove(tcp, arg, &res)) + return 0; + + tprintf(", {fb_id_ptr=%p, crtc_id_ptr=%p, connector_id_ptr=%p, " + "encoder_id_ptr=%p, count_fbs=%u, count_crtcs=%u, " + "count_connectors=%u, count_encoders=%u, min_width=%u, " + "max_width=%u, min_height=%u, max_height=%u}", + (void *)res.fb_id_ptr, (void *)res.crtc_id_ptr, + (void *)res.connector_id_ptr, (void *)res.encoder_id_ptr, + res.count_fbs, res.count_crtcs, res.count_connectors, + res.count_encoders, res.min_width, res.max_width, + res.min_height, res.max_height); + + return 1; +} + +static void drm_mode_print_modeinfo(struct drm_mode_modeinfo *info) +{ + tprintf("clock=%u, hdisplay=%hu, hsync_start=%hu, hsync_end=%hu, " + "htotal=%hu, hskew=%hu, vdisplay=%hu, vsync_start=%hu, " + "vsync_end=%hu, vtotal=%hu, vscan=%hu, vrefresh=%u, " + "flags=0x%x, type=%u, name=%s", info->clock, info->hdisplay, + info->hsync_start, info->hsync_end, info->htotal, info->hskew, + info->vdisplay, info->vsync_start, info->vsync_end, + info->vtotal, info->vscan, info->vrefresh, info->flags, + info->type, info->name); +} + +static int drm_mode_get_crtc(struct tcb *tcp, const unsigned int code, long arg) +{ + struct drm_mode_crtc crtc; + + if (entering(tcp) || umove(tcp, arg, &crtc)) + return 0; + + tprintf(", {set_connectors_ptr=%p, count_connectors=%u, crtc_id=%u, " + "fb_id=%u, x=%u, y=%u, gamma_size=%u, mode_valid=%u, mode={", + (void *)crtc.set_connectors_ptr, crtc.count_connectors, + crtc.crtc_id, crtc.fb_id, crtc.x, crtc.y, crtc.gamma_size, + crtc.mode_valid); + + drm_mode_print_modeinfo(&crtc.mode); + tprintf("}}"); + + return 1; +} + +static int drm_mode_set_crtc(struct tcb *tcp, const unsigned int code, long arg) +{ + struct drm_mode_crtc crtc; + + if (entering(tcp) || umove(tcp, arg, &crtc)) + return 0; + + tprintf(", {set_connectors_ptr=%p, count_connectors=%u, crtc_id=%u, " + "fb_id=%u, x=%u, y=%u, gamma_size=%u, mode_valid=%u, mode={", + (void *)crtc.set_connectors_ptr, crtc.count_connectors, + crtc.crtc_id, crtc.fb_id, crtc.x, crtc.y, crtc.gamma_size, + crtc.mode_valid); + + drm_mode_print_modeinfo(&crtc.mode); + tprintf("}}"); + + return 1; +} + +static int drm_mode_cursor(struct tcb *tcp, const unsigned int code, long arg) +{ + struct drm_mode_cursor cursor; + + if (entering(tcp) || umove(tcp, arg, &cursor)) + return 0; + + tprintf(", {flags=0x%x, crtc_id=%u, x=%d, y=%d, width=%u, height=%u, " + "handle=%u}", cursor.flags, cursor.crtc_id, cursor.x, cursor.y, + cursor.width, cursor.height, cursor.handle); + + return 1; +} + +static int drm_mode_cursor2(struct tcb *tcp, const unsigned int code, long arg) +{ + struct drm_mode_cursor2 cursor; + + if (entering(tcp) || umove(tcp, arg, &cursor)) + return 0; + + tprintf(", {flags=0x%x, crtc_id=%u, x=%d, y=%d, width=%u, height=%u, " + "handle=%u, hot_x=%d, hot_y=%d}", cursor.flags, cursor.crtc_id, + cursor.x, cursor.y, cursor.width, cursor.height, cursor.handle, + cursor.hot_x, cursor.hot_y); + + return 1; +} + +static int drm_mode_get_gamma(struct tcb *tcp, const unsigned int code, long arg) +{ + struct drm_mode_crtc_lut lut; + + if (entering(tcp) || umove(tcp, arg, &lut)) + return 0; + + /* We don't print the entire table, just the pointers */ + tprintf(", {crtc_id=%u, gamma_size=%u, red=%p, green=%p, blue=%p}", + lut.crtc_id, lut.gamma_size, (void *)lut.red, (void *)lut.green, + (void *)lut.blue); + + return 1; +} + + +static int drm_mode_set_gamma(struct tcb *tcp, const unsigned int code, long arg) +{ + struct drm_mode_crtc_lut lut; + + if (entering(tcp) || umove(tcp, arg, &lut)) + return 0; + + /* We don't print the entire table, just the rgb pointers */ + tprintf(", {crtc_id=%u, gamma_size=%u, red=%p, green=%p, blue=%p}", + lut.crtc_id, lut.gamma_size, (void *)lut.red, (void *)lut.green, + (void *)lut.blue); + + return 1; +} + +static int drm_mode_get_encoder(struct tcb *tcp, const unsigned int code, long arg) +{ + struct drm_mode_get_encoder enc; + + if (entering(tcp) || umove(tcp, arg, &enc)) + return 0; + + /* TODO: Print name of encoder type */ + tprintf(", {encoder_id=%u, encoder_type=%u, crtc_id=%u, " + "possible_crtcs=0x%x, possible_clones=0x%x}", enc.encoder_id, + enc.encoder_type, enc.crtc_id, enc.possible_crtcs, + enc.possible_clones); + + return 1; +} + +static int drm_mode_get_connector(struct tcb *tcp, const unsigned int code, long arg) +{ + struct drm_mode_get_connector con; + + if (entering(tcp) || umove(tcp, arg, &con)) + return 0; + + /* We could be very verbose here but keep is simple for now */ + tprintf(", {encoders_ptr=%p, modes_ptr=%p, props_ptr=%p, " + "prop_values_ptr=%p, count_modes=%u, count_props=%u, " + "count_encoders=%u, encoder_id=%u, connector_id=%u, " + "connector_type=%u, connector_type_id=%u, connection=%u, " + "mm_width=%u, mm_height=%u, subpixel=%u}", + (void *)con.encoders_ptr, (void *)con.modes_ptr, + (void *)con.props_ptr, (void *)con.prop_values_ptr, + con.count_modes, con.count_props, con.count_encoders, + con.encoder_id, con.connector_id, con.connector_type, + con.connector_type_id, con.connection, con.mm_width, + con.mm_height, con.subpixel); + + return 1; +} + +static int drm_mode_attachmode(struct tcb *tcp, const unsigned int code, long arg) +{ + struct drm_mode_mode_cmd cmd; + + if (entering(tcp) || umove(tcp, arg, &cmd)) + return 0; + + tprintf(", {connector_id=%u, mode={", cmd.connector_id); + drm_mode_print_modeinfo(&cmd.mode); + tprintf("}"); + + return 1; +} + +static int drm_mode_detachmode(struct tcb *tcp, const unsigned int code, long arg) +{ + struct drm_mode_mode_cmd cmd; + + if (entering(tcp) || umove(tcp, arg, &cmd)) + return 0; + + tprintf(", {connector_id=%u, mode={", cmd.connector_id); + drm_mode_print_modeinfo(&cmd.mode); + tprintf("}"); + + return 1; +} + +static int drm_mode_get_property(struct tcb *tcp, const unsigned int code, long arg) +{ + struct drm_mode_get_property prop; + + if (entering(tcp) || umove(tcp, arg, &prop)) + return 0; + + tprintf(", {values_ptr=%p, enum_blob_ptr=%p, prop_id=%u, flags=0x%x, " + "name=%s, count_values=%u, count_enum_blobs=%u}", + (void *)prop.values_ptr, (void *)prop.enum_blob_ptr, + prop.prop_id, prop.flags, prop.name, prop.count_values, + prop.count_enum_blobs); + + return 1; +} + +static int drm_mode_set_property(struct tcb *tcp, const unsigned int code, long arg) +{ + struct drm_mode_connector_set_property prop; + + if (entering(tcp) || umove(tcp, arg, &prop)) + return 0; + + tprintf(", {value=%Lu, prop_id=%u, connector_id=%u}", prop.value, + prop.prop_id, prop.connector_id); + + return 1; +} + +static int drm_mode_get_prop_blob(struct tcb *tcp, const unsigned int code, long arg) +{ + struct drm_mode_get_blob blob; + + if (entering(tcp) || umove(tcp, arg, &blob)) + return 0; + + tprintf(", {blob_id=%u, length=%u, data=%p}", blob.blob_id, blob.length, + (void *)blob.data); + + return 1; +} + +static int drm_mode_add_fb(struct tcb *tcp, const unsigned int code, long arg) +{ + struct drm_mode_fb_cmd cmd; + + if (entering(tcp) || umove(tcp, arg, &cmd)) + return 0; + + tprintf(", {fb_id=%u, width=%u, height=%u, pitch=%u, bpp=%u, depth=%u, " + "handle=%u}", cmd.fb_id, cmd.width, cmd.height, cmd.pitch, + cmd.bpp, cmd.depth, cmd.handle); + + return 1; +} + +static int drm_mode_get_fb(struct tcb *tcp, const unsigned int code, long arg) +{ + struct drm_mode_fb_cmd cmd; + + if (entering(tcp) || umove(tcp, arg, &cmd)) + return 0; + + tprintf(", {fb_id=%u, width=%u, height=%u, pitch=%u, bpp=%u, depth=%u, " + "handle=%u}", cmd.fb_id, cmd.width, cmd.height, cmd.pitch, + cmd.bpp, cmd.depth, cmd.handle); + + return 1; +} + +static int drm_mode_rm_fb(struct tcb *tcp, const unsigned int code, long arg) +{ + unsigned int handle; + + if (entering(tcp) || umove(tcp, arg, &handle)) + return 0; + + tprintf(", %u", handle); + + return 1; +} + +static int drm_mode_page_flip(struct tcb *tcp, const unsigned int code, long arg) +{ + struct drm_mode_crtc_page_flip flip; + + if (entering(tcp) || umove(tcp, arg, &flip)) + return 0; + + tprintf(", {crtc_id=%u, fb_id=%u, flags=0x%x, user_data=0x%Lx}", + flip.crtc_id, flip.fb_id, flip.flags, flip.user_data); + + return 1; +} + +static int drm_mode_dirty_fb(struct tcb *tcp, const unsigned int code, long arg) +{ + struct drm_mode_fb_dirty_cmd cmd; + + if (entering(tcp) || umove(tcp, arg, &cmd)) + return 0; + + tprintf(", {fb_id=%u, flags=0x%x, color=0x%x, num_clips=%u, " + "clips_ptr=%p}", cmd.fb_id, cmd.flags, cmd.color, cmd.num_clips, + (void *)cmd.clips_ptr); + + return 1; +} + +static int drm_mode_create_dumb(struct tcb *tcp, const unsigned int code, long arg) +{ + struct drm_mode_create_dumb dumb; + + if (entering(tcp) || umove(tcp, arg, &dumb)) + return 0; + + tprintf(", {height=%u, width=%u, bpp=%u, flags=0x%x, handle=%u, " + "pitch=%u, size=%Lu}", dumb.height, dumb.width, dumb.bpp, + dumb.flags, dumb.handle, dumb.pitch, dumb.size); + + return 1; +} + +static int drm_mode_map_dumb(struct tcb *tcp, const unsigned int code, long arg) +{ + struct drm_mode_map_dumb dumb; + + if (entering(tcp) || umove(tcp, arg, &dumb)) + return 0; + + tprintf(", {handle=%u, offset=%Lu}", dumb.handle, dumb.offset); + + return 1; +} + +static int drm_mode_destroy_dumb(struct tcb *tcp, const unsigned int code, long arg) +{ + struct drm_mode_destroy_dumb dumb; + + if (entering(tcp) || umove(tcp, arg, &dumb)) + return 0; + + tprintf(", {handle=%u}", dumb.handle); + + return 1; +} + +static int drm_gem_close(struct tcb *tcp, const unsigned int code, long arg) +{ + struct drm_gem_close close; + + if (entering(tcp) || umove(tcp, arg, &close)) + return 0; + + tprintf(", {handle=%u}", close.handle); + + return 1; +} + int drm_ioctl(struct tcb *tcp, const unsigned int code, long arg) { /* Check for device specific ioctls */ @@ -90,5 +552,62 @@ int drm_ioctl(struct tcb *tcp, const unsigned int code, long arg) return drm_i915_ioctl(tcp, code, arg); } + switch (code) { + case DRM_IOCTL_VERSION: + return drm_version(tcp, code, arg); + case DRM_IOCTL_GET_UNIQUE: + return drm_get_unique(tcp, code, arg); + case DRM_IOCTL_GET_MAGIC: + return drm_get_magic(tcp, code, arg); + case DRM_IOCTL_WAIT_VBLANK: + return drm_wait_vblank(tcp, code, arg); + case DRM_IOCTL_MODE_GETRESOURCES: + return drm_mode_get_resources(tcp, code, arg); + case DRM_IOCTL_MODE_GETCRTC: + return drm_mode_get_crtc(tcp, code, arg); + case DRM_IOCTL_MODE_SETCRTC: + return drm_mode_set_crtc(tcp, code, arg); + case DRM_IOCTL_MODE_CURSOR: + return drm_mode_cursor(tcp, code, arg); + case DRM_IOCTL_MODE_CURSOR2: + return drm_mode_cursor2(tcp, code, arg); + case DRM_IOCTL_MODE_GETGAMMA: + return drm_mode_get_gamma(tcp, code, arg); + case DRM_IOCTL_MODE_SETGAMMA: + return drm_mode_set_gamma(tcp, code, arg); + case DRM_IOCTL_MODE_GETENCODER: + return drm_mode_get_encoder(tcp, code, arg); + case DRM_IOCTL_MODE_GETCONNECTOR: + return drm_mode_get_connector(tcp, code, arg); + case DRM_IOCTL_MODE_ATTACHMODE: + return drm_mode_attachmode(tcp, code, arg); + case DRM_IOCTL_MODE_DETACHMODE: + return drm_mode_detachmode(tcp, code, arg); + case DRM_IOCTL_MODE_GETPROPERTY: + return drm_mode_get_property(tcp, code, arg); + case DRM_IOCTL_MODE_SETPROPERTY: + return drm_mode_set_property(tcp, code, arg); + case DRM_IOCTL_MODE_GETPROPBLOB: + return drm_mode_get_prop_blob(tcp, code, arg); + case DRM_IOCTL_MODE_GETFB: + return drm_mode_get_fb(tcp, code, arg); + case DRM_IOCTL_MODE_ADDFB: + return drm_mode_add_fb(tcp, code, arg); + case DRM_IOCTL_MODE_RMFB: + return drm_mode_rm_fb(tcp, code, arg); + case DRM_IOCTL_MODE_PAGE_FLIP: + return drm_mode_page_flip(tcp, code, arg); + case DRM_IOCTL_MODE_DIRTYFB: + return drm_mode_dirty_fb(tcp, code, arg); + case DRM_IOCTL_MODE_CREATE_DUMB: + return drm_mode_create_dumb(tcp, code, arg); + case DRM_IOCTL_MODE_MAP_DUMB: + return drm_mode_map_dumb(tcp, code, arg); + case DRM_IOCTL_MODE_DESTROY_DUMB: + return drm_mode_destroy_dumb(tcp, code, arg); + case DRM_IOCTL_GEM_CLOSE: + return drm_gem_close(tcp, code, arg); + } + return 0; }