summaryrefslogtreecommitdiff
path: root/reg.c
diff options
context:
space:
mode:
authorAustin Yuan <shengquan.yuan@intel.com>2015-05-20 13:26:26 +0800
committerAustin Yuan <shengquan.yuan@intel.com>2015-05-20 13:26:26 +0800
commit23bd23703b9e23491935d4657ad9472305c10409 (patch)
treec96f5623fea47cde99e7e803087bb43c59dd6347 /reg.c
igdbg init commitHEADmaster
Signed-off-by: Austin Yuan <shengquan.yuan@intel.com>
Diffstat (limited to 'reg.c')
-rw-r--r--reg.c446
1 files changed, 446 insertions, 0 deletions
diff --git a/reg.c b/reg.c
new file mode 100644
index 0000000..aa73ba6
--- /dev/null
+++ b/reg.c
@@ -0,0 +1,446 @@
+/*
+ * Copyright © 2014 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <errno.h>
+#include <sys/time.h>
+
+#include "i915_reg.h"
+#include "main.h"
+
+int process_regread(char *cmdhdr,unsigned int reg)
+{
+ uint32_t value=INREG(linear_mmio,reg);
+
+ printf("read register 0x%x,value is 0x%08x\n",reg,value);
+
+ print_bin_fmt(value,15);
+
+ return 0;
+}
+
+int process_regwrite(char *cmdhdr,unsigned int reg, unsigned int value)
+{
+ printf("Write register 0x%x with value 0x%x\n",reg,value);
+ OUTREG(linear_mmio,reg,value);
+
+ return 0;
+}
+
+
+static uint64_t now_us()
+{
+ struct timeval tv;
+ if (gettimeofday(&tv, NULL))
+ return 0;
+ return tv.tv_usec + tv.tv_sec*1000*1000;
+}
+
+static int current_render(uint32_t delta_ms, uint32_t delta_us);
+static int current_video(uint32_t delta_ms, uint32_t delta_us);
+
+#define I915_GEM_HWS_INDEX 0x20
+
+
+/* Linux kernle file i915_irq.c */
+#define GEN8_GT_IIR(which) (0x44308 + (0x10 * (which)))
+#define GEN8_BCS_IRQ_SHIFT 16
+#define GEN8_RCS_IRQ_SHIFT 0
+#define GEN8_VCS2_IRQ_SHIFT 16
+#define GEN8_VCS1_IRQ_SHIFT 0
+#define GEN8_VECS_IRQ_SHIFT 0
+#define GEN8_OACS_IRQ_SHIFT 19
+int process_irq(char *cmdhdr,unsigned int seconds)
+{
+ uint64_t start = now_us();
+ uint64_t expected_end = start + 1000 * 1000 * seconds;
+ unsigned int render_iir=0, video_iir=0;
+ uint32_t *render_seqno, *video_seqno, last_render_seqno=0, last_video_seqno=0;
+ uint32_t *blit_seqno, *video2_seqno, last_blit_seqno=0, last_video2_seqno=0;
+ uint32_t render_hws, video_hws, blit_hws, video2_hws;
+
+ if (is_gen7) {
+ printf("IRQ sample tbd on GEN7\n");
+ return 0;
+ }
+ render_hws = INREG(linear_mmio, 0x2080);
+ video_hws = INREG(linear_mmio, 0x12080);
+ blit_hws = INREG(linear_mmio, 0x1a080);
+ video2_hws = INREG(linear_mmio, 0x1c080);
+
+ printf("Sample IRQ for %d seconds....It is not accurate, just rough view\n", seconds);
+ printf("Render HWS_PGA=0x%08x, Video HWS_PGA=0x%08x\n", render_hws, video_hws);
+
+ render_seqno = (uint32_t *)((unsigned char *)linear_fb + render_hws) + I915_GEM_HWS_INDEX;
+ video_seqno = (uint32_t *)((unsigned char *)linear_fb + video_hws) + I915_GEM_HWS_INDEX;
+ blit_seqno = (uint32_t *)((unsigned char *)linear_fb + blit_hws) + I915_GEM_HWS_INDEX;
+ video2_seqno = (uint32_t *)((unsigned char *)linear_fb + video2_hws) + I915_GEM_HWS_INDEX;
+
+ while (1) {
+ uint64_t now = now_us();
+ int64_t test = now - expected_end;
+
+ //printf("now=%u, expected end=%u, test = %d\n", now, expected_end, test);
+ if (test > 0)
+ break;
+
+ uint64_t delta = now - start;
+ uint32_t delta_ms = (uint32_t)(delta/1000);
+ uint32_t delta_us = (uint32_t)(delta%1000);
+
+ uint32_t tmp = INREG(linear_mmio, GEN8_GT_IIR(0));
+ uint32_t tmp1 = INREG(linear_mmio, GEN8_GT_IIR(1));
+
+ while (render_iir != tmp) {
+ uint32_t rcs = tmp >> GEN8_RCS_IRQ_SHIFT;
+ uint32_t bcs = tmp >> GEN8_BCS_IRQ_SHIFT;
+ int has_irq;
+
+ render_iir = tmp;
+
+ has_irq = (rcs|bcs) & (GT_RENDER_USER_INTERRUPT|GT_CONTEXT_SWITCH_INTERRUPT);
+ if (has_irq) {
+ printf("T%d.%03d:iir=0x%08x\n", delta_ms, delta_us, tmp);
+ //print_bin_fmt(tmp, 8);
+ } else
+ break;
+
+ if ((rcs & GT_RENDER_USER_INTERRUPT)
+ && (last_render_seqno != *render_seqno)) {
+ printf("\tRCS:GT_USER_INTERRUPT (seqno=0x%08x)\n", *render_seqno);
+ last_render_seqno = *render_seqno;
+ }
+
+ if (rcs & GT_CONTEXT_SWITCH_INTERRUPT) {
+ printf("\tRCS:GT_CONTEXT_SWITCH_INTERRUPT (seqno=0x%08x)\n", *render_seqno);
+ if (verbose)
+ current_render(delta_ms, delta_us);
+ }
+
+ if ((bcs & GT_RENDER_USER_INTERRUPT)
+ && (last_blit_seqno != *blit_seqno)) {
+ last_blit_seqno = *blit_seqno;
+ printf("\tBCS:GT_USER_INTERRUPT (seqno=0x%08x)\n", *blit_seqno);
+ }
+
+ if (bcs & GT_CONTEXT_SWITCH_INTERRUPT)
+ printf("\tBCS:GT_CONTEXT_SWITCH_INTERRUPT (seqno=0x%08x)\n", *render_seqno);
+
+
+ break;
+ }
+
+ while (video_iir != tmp1) {
+ /* video engine */
+ uint32_t vcs = tmp1 >> GEN8_VCS1_IRQ_SHIFT;
+ uint32_t vcs2 = tmp1 >> GEN8_VCS2_IRQ_SHIFT;
+ int has_irq;
+
+ video_iir = tmp1;
+
+ has_irq = (vcs|vcs2) & (GT_RENDER_USER_INTERRUPT|GT_CONTEXT_SWITCH_INTERRUPT);
+ if (has_irq) {
+ printf("T%d.%03d:iir=0x%08x\n", delta_ms, delta_us, tmp1);
+ //print_bin_fmt(tmp, 8);
+ } else
+ break;
+
+ if ((vcs & GT_RENDER_USER_INTERRUPT)
+ && (last_video_seqno != *video_seqno)) {
+ last_video_seqno = *video_seqno;
+ printf("\tVCS:GT_USER_INTERRUPT (seqno=0x%08x)\n", *video_seqno);
+ }
+
+ if (vcs & GT_CONTEXT_SWITCH_INTERRUPT) {
+ printf("\tVCS:GT_CONTEXT_SWITCH_INTERRUPT (seqno=0x%08x)\n", *video_seqno);
+ if (verbose)
+ current_video(delta_ms, delta_us);
+ }
+
+ if ((vcs2 & GT_RENDER_USER_INTERRUPT)
+ && (last_video2_seqno != *video2_seqno)) {
+ last_video2_seqno = *video2_seqno;
+ printf("\tVCS2:GT_USER_INTERRUPT (seqno=0x%08x)\n", *video2_seqno);
+ }
+
+ if (vcs2 & GT_CONTEXT_SWITCH_INTERRUPT)
+ printf("\tVCS2:GT_CONTEXT_SWITCH_INTERRUPT (seqno=0x%08x)\n", *video_seqno);
+
+ break;
+ }
+ }
+
+ return 0;
+}
+
+
+static void print_estatus(uint32_t estatus)
+{
+ uint32_t tmp;
+
+ printf("\tExeclist 0 Active = %d\n", (estatus>>18) & 0x1);
+ printf("\tExeclist 1 Active = %d\n", (estatus>>18) & 0x1);
+
+ tmp = (estatus>>14) & 0x2;
+ printf("\tCurrent Active Element Status = %d", tmp);
+ if (tmp == 0)
+ printf("(No Active Element being executed)\n");
+ else if (tmp == 1)
+ printf("(Element0 of current execlist being executed)\n");
+ else if (tmp == 2)
+ printf("(Element1 of current execlist being executed)\n");
+
+ tmp = (estatus>>5) & 0x1ff;
+ printf("\tLast Context Switch Reason = 0x%x\n", tmp);
+ if (tmp & 1)
+ printf("\t\tIDLE to ACTIVE\n");
+ if (tmp & 2)
+ printf("\t\tPreempted\n");
+ if (tmp & 4)
+ printf("\t\tElement Switch: from element0 to element1 in the current execlist\n");
+ if (tmp & 8)
+ printf("\t\tACTIVE to IDLE\n");
+ if (tmp & 0x10)
+ printf("\t\tContext Complete:Element is completely processed\n");
+ if (tmp & 0x1e0)
+ printf("\t\tWait on display\n");
+
+ printf("\tExeclist 0 Valid = %d\n", (estatus>>4) & 0x1);
+ printf("\tExeclist 1 Valid = %d\n", (estatus>>3) & 0x1);
+}
+
+int process_estatus(char *cmdhdr,unsigned int seconds)
+{
+ uint64_t start = now_us();
+ uint64_t expected_end = start + 1000 * 1000 * seconds;
+ uint32_t previous_r_eid = 0, previous_r_estatus = 0;
+ uint32_t previous_v_eid = 0, previous_v_estatus = 0;
+
+ if (is_gen7) {
+ printf("Execlist is not supported on GEN7\n");
+ return 0;
+ }
+
+ printf("Sample ExecList Status for %d seconds....\n", seconds);
+ printf("It is not accurate, just for a rough view\n");
+
+ while (1) {
+ uint64_t now = now_us();
+ int64_t test = now - expected_end;
+
+ if (test > 0)
+ break;
+
+ uint64_t delta = now - start;
+ uint32_t delta_ms = (uint32_t)(delta/1000);
+ uint32_t delta_us = (uint32_t)(delta%1000);
+
+ uint32_t r_estatus = INREG(linear_mmio, 0x2234);
+ uint32_t r_eid = INREG(linear_mmio, 0x2238);
+
+ uint32_t v_estatus = INREG(linear_mmio, 0x12234);
+ uint32_t v_eid = INREG(linear_mmio, 0x12238);
+
+ if ((r_eid !=0) && (r_estatus != 0)
+ && ((previous_r_eid != r_eid) || (previous_r_estatus!= r_estatus))) {
+ printf("----------------------------------Render---------------------------------\n");
+ printf("T%d.%03d:context id=0x%08x, status=0x%08x\n",
+ delta_ms, delta_us, r_eid, r_estatus);
+
+ print_estatus(r_estatus);
+
+ previous_r_eid = r_eid;
+ previous_r_estatus = r_estatus;
+ }
+
+ if ((v_eid !=0) && (v_estatus != 0)
+ && ((previous_v_eid != v_eid) || (previous_v_estatus!= v_estatus))) {
+
+ printf("----------------------------------Video---------------------------------\n");
+ printf("T%d.%03d:context id=0x%08x, status=0x%08x\n",
+ delta_ms, delta_us, v_eid, v_estatus);
+
+ print_estatus(v_estatus);
+
+ previous_v_eid = v_eid;
+ previous_v_estatus = v_estatus;
+ }
+ }
+
+ return 0;
+}
+
+static void print_cstatus(uint32_t ldw, uint32_t udw)
+{
+ uint32_t tmp;
+
+ printf("\tContext id=0x%08x\n", udw);
+ printf("\tContext status = 0x%08x\n", ldw);
+
+ printf("\t\tWait display plane = 0x%04x\n", (ldw>>16) & 0xf);
+ printf("\t\tLite restore = %d\n", (ldw>>15)&1);
+ printf("\t\tWait display plane = 0x%03x\n", (ldw>>12) & 0x3);
+ printf("\t\tSemaphore wait mode = %d\n", (ldw>>11)&1);
+
+ tmp = ldw & 0x1ff;
+ printf("\t\tLast Context Switch Reason = 0x%x\n", tmp);
+ if (tmp & 1)
+ printf("\t\t\tIDLE to ACTIVE\n");
+ if (tmp & 2)
+ printf("\t\t\tPreempted\n");
+ if (tmp & 4)
+ printf("\t\t\tElement Switch: from element0 to element1 in the current execlist\n");
+ if (tmp & 8)
+ printf("\t\t\tACTIVE to IDLE\n");
+ if (tmp & 0x10)
+ printf("\t\t\tContext Complete:Element is completely processed\n");
+ if (tmp & 0x1e0)
+ printf("\t\t\tWait on display\n");
+}
+
+static struct context_status_t {
+ uint32_t udw;
+ uint32_t ldw;
+} render[6], video[6];
+static int render_wp, video_wp, last_render_wp, last_video_wp;
+
+static int current_render(uint32_t delta_ms, uint32_t delta_us)
+{
+ uint32_t mmio_addr;
+
+ render_wp = INREG(linear_mmio, 0x23a0) % 6;
+ if (render_wp == last_render_wp)
+ return 0;
+
+ last_render_wp = render_wp;
+
+ if (render_wp == 0)
+ render_wp = 5;
+ else
+ render_wp--;
+
+ mmio_addr = 0x2370;
+ render[render_wp].ldw = INREG(linear_mmio, mmio_addr + render_wp*8);
+ render[render_wp].udw = INREG(linear_mmio, mmio_addr + render_wp*8 + 4);
+
+ if (render[render_wp].udw != 0) {
+ printf("-----------------------------------------------\n");
+ printf("T%d.%03d:Render Context Info(write ponter = %d)\n", delta_ms, delta_us, render_wp);
+ print_cstatus(render[render_wp].ldw, render[render_wp].udw);
+ printf("-----------------------------------------------\n");
+ }
+
+ return 0;
+}
+
+static int current_video(uint32_t delta_ms, uint32_t delta_us)
+{
+ uint32_t mmio_addr;
+
+ video_wp = INREG(linear_mmio, 0x123a0) % 6;
+ if (video_wp == last_video_wp)
+ return 0;
+ last_video_wp = video_wp;
+
+ if (video_wp == 0)
+ video_wp = 5;
+ else
+ video_wp--;
+
+ mmio_addr = 0x12370;
+ video[video_wp].ldw = INREG(linear_mmio, mmio_addr + video_wp*8);
+ video[video_wp].udw = INREG(linear_mmio, mmio_addr + video_wp*8 + 4);
+ if (video[video_wp].udw != 0) {
+ printf("-----------------------------------------------\n");
+ printf("T%d.%03d:Video Context Info (write ponter = %d)\n", delta_ms, delta_us, video_wp);
+ print_cstatus(video[video_wp].ldw, video[video_wp].udw);
+ printf("-----------------------------------------------\n");
+ }
+
+ return 0;
+}
+
+int process_cstatus(char *cmdhdr,unsigned int seconds)
+{
+ uint64_t start = now_us();
+ uint64_t expected_end = start + 1000 * 1000 * seconds;
+
+ if (is_gen7) {
+ printf("Execlist is not supported on GEN7\n");
+ return 0;
+ }
+
+ printf("Sample Context Status for %d seconds....\n", seconds);
+ printf("It is not accurate, just for rough view\n");
+
+ while (1) {
+ uint64_t now = now_us();
+ int64_t test = now - expected_end;
+
+ if (test > 0)
+ break;
+
+ uint64_t delta = now - start;
+ uint32_t delta_ms = (uint32_t)(delta/1000);
+ uint32_t delta_us = (uint32_t)(delta%1000);
+
+ current_render(delta_ms, delta_us);
+ current_video(delta_ms, delta_us);
+ }
+
+ return 0;
+}
+
+int process_msgread(char *cmdhdr,unsigned int port,unsigned int reg)
+{
+ unsigned int value = 0;
+
+ //value = MSG_READ32(port, reg)
+ printf("read MSG port 0x%x, reg 0x%x, value=0x%08x\n",port, reg, value);
+ print_bin_fmt(value,15);
+
+ return 0;
+}
+
+int process_msgwrite(char *cmdhdr,unsigned int port, unsigned int reg, unsigned int new_value)
+{
+ unsigned int value = 0;
+
+ //value = MSG_READ32(port, reg);
+ printf("Read MSG port 0x%x, reg 0x%x, value 0x%08x,try to write 0x%08x\n",port, reg, value, new_value);
+
+ //MSG_WRITE32(port,reg,new_value);
+
+ //value = MSG_READ32(port, reg);
+ printf("After write, MSG port 0x%x, reg 0x%x, new value=0x%08x\n",port, reg, value);
+
+ return 0;
+}