1 /*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 2014 LunarG, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 *
24 * Authors:
25 * Chia-I Wu <olv@lunarg.com>
26 */
27
28 #ifndef ILO_BUILDER_MI_H
29 #define ILO_BUILDER_MI_H
30
31 #include "genhw/genhw.h"
32 #include "intel_winsys.h"
33
34 #include "ilo_core.h"
35 #include "ilo_dev.h"
36 #include "ilo_builder.h"
37
38 static inline void
gen6_MI_STORE_DATA_IMM(struct ilo_builder * builder,struct intel_bo * bo,uint32_t bo_offset,uint64_t val)39 gen6_MI_STORE_DATA_IMM(struct ilo_builder *builder,
40 struct intel_bo *bo, uint32_t bo_offset,
41 uint64_t val)
42 {
43 const uint8_t cmd_len = (ilo_dev_gen(builder->dev) >= ILO_GEN(8)) ? 6 : 5;
44 uint32_t reloc_flags = INTEL_RELOC_WRITE;
45 uint32_t *dw;
46 unsigned pos;
47
48 ILO_DEV_ASSERT(builder->dev, 6, 8);
49
50 assert(bo_offset % 8 == 0);
51
52 pos = ilo_builder_batch_pointer(builder, cmd_len, &dw);
53
54 dw[0] = GEN6_MI_CMD(MI_STORE_DATA_IMM) | (cmd_len - 2);
55 /* must use GGTT on GEN6 as in PIPE_CONTROL */
56 if (ilo_dev_gen(builder->dev) == ILO_GEN(6)) {
57 dw[0] |= GEN6_MI_STORE_DATA_IMM_DW0_USE_GGTT;
58 reloc_flags |= INTEL_RELOC_GGTT;
59 }
60
61 dw[1] = 0; /* MBZ */
62
63 if (ilo_dev_gen(builder->dev) >= ILO_GEN(8)) {
64 dw[4] = (uint32_t) val;
65 dw[5] = (uint32_t) (val >> 32);
66
67 ilo_builder_batch_reloc64(builder, pos + 2, bo, bo_offset, reloc_flags);
68 } else {
69 dw[3] = (uint32_t) val;
70 dw[4] = (uint32_t) (val >> 32);
71
72 ilo_builder_batch_reloc(builder, pos + 2, bo, bo_offset, reloc_flags);
73 }
74 }
75
76 static inline void
gen6_MI_LOAD_REGISTER_IMM(struct ilo_builder * builder,uint32_t reg,uint32_t val)77 gen6_MI_LOAD_REGISTER_IMM(struct ilo_builder *builder,
78 uint32_t reg, uint32_t val)
79 {
80 const uint8_t cmd_len = 3;
81 uint32_t *dw;
82
83 ILO_DEV_ASSERT(builder->dev, 6, 8);
84
85 assert(reg % 4 == 0);
86
87 ilo_builder_batch_pointer(builder, cmd_len, &dw);
88
89 dw[0] = GEN6_MI_CMD(MI_LOAD_REGISTER_IMM) | (cmd_len - 2);
90 dw[1] = reg;
91 dw[2] = val;
92 }
93
94 static inline void
gen6_MI_STORE_REGISTER_MEM(struct ilo_builder * builder,uint32_t reg,struct intel_bo * bo,uint32_t bo_offset)95 gen6_MI_STORE_REGISTER_MEM(struct ilo_builder *builder, uint32_t reg,
96 struct intel_bo *bo, uint32_t bo_offset)
97 {
98 const uint8_t cmd_len = (ilo_dev_gen(builder->dev) >= ILO_GEN(8)) ? 4 : 3;
99 uint32_t reloc_flags = INTEL_RELOC_WRITE;
100 uint32_t *dw;
101 unsigned pos;
102
103 ILO_DEV_ASSERT(builder->dev, 6, 8);
104
105 assert(reg % 4 == 0 && bo_offset % 4 == 0);
106
107 pos = ilo_builder_batch_pointer(builder, cmd_len, &dw);
108
109 dw[0] = GEN6_MI_CMD(MI_STORE_REGISTER_MEM) | (cmd_len - 2);
110 dw[1] = reg;
111
112 if (ilo_dev_gen(builder->dev) >= ILO_GEN(8)) {
113 ilo_builder_batch_reloc64(builder, pos + 2, bo, bo_offset, reloc_flags);
114 } else {
115 /* must use GGTT on Gen6 as in PIPE_CONTROL */
116 if (ilo_dev_gen(builder->dev) == ILO_GEN(6)) {
117 dw[0] |= GEN6_MI_STORE_REGISTER_MEM_DW0_USE_GGTT;
118 reloc_flags |= INTEL_RELOC_GGTT;
119 }
120
121 ilo_builder_batch_reloc(builder, pos + 2, bo, bo_offset, reloc_flags);
122 }
123 }
124
125 static inline void
gen6_MI_FLUSH_DW(struct ilo_builder * builder)126 gen6_MI_FLUSH_DW(struct ilo_builder *builder)
127 {
128 const uint8_t cmd_len = 4;
129 uint32_t *dw;
130
131 ILO_DEV_ASSERT(builder->dev, 6, 8);
132
133 ilo_builder_batch_pointer(builder, cmd_len, &dw);
134
135 dw[0] = GEN6_MI_CMD(MI_FLUSH_DW) | (cmd_len - 2);
136 dw[1] = 0;
137 dw[2] = 0;
138 dw[3] = 0;
139 }
140
141 static inline void
gen6_MI_REPORT_PERF_COUNT(struct ilo_builder * builder,struct intel_bo * bo,uint32_t bo_offset,uint32_t report_id)142 gen6_MI_REPORT_PERF_COUNT(struct ilo_builder *builder,
143 struct intel_bo *bo, uint32_t bo_offset,
144 uint32_t report_id)
145 {
146 const uint8_t cmd_len = 3;
147 uint32_t reloc_flags = INTEL_RELOC_WRITE;
148 uint32_t *dw;
149 unsigned pos;
150
151 ILO_DEV_ASSERT(builder->dev, 6, 7.5);
152
153 assert(bo_offset % 64 == 0);
154
155 /* must use GGTT on GEN6 as in PIPE_CONTROL */
156 if (ilo_dev_gen(builder->dev) == ILO_GEN(6)) {
157 bo_offset |= GEN6_MI_REPORT_PERF_COUNT_DW1_USE_GGTT;
158 reloc_flags |= INTEL_RELOC_GGTT;
159 }
160
161 pos = ilo_builder_batch_pointer(builder, cmd_len, &dw);
162
163 dw[0] = GEN6_MI_CMD(MI_REPORT_PERF_COUNT) | (cmd_len - 2);
164 dw[2] = report_id;
165
166 ilo_builder_batch_reloc(builder, pos + 1, bo, bo_offset, reloc_flags);
167 }
168
169 static inline void
gen7_MI_LOAD_REGISTER_MEM(struct ilo_builder * builder,uint32_t reg,struct intel_bo * bo,uint32_t bo_offset)170 gen7_MI_LOAD_REGISTER_MEM(struct ilo_builder *builder, uint32_t reg,
171 struct intel_bo *bo, uint32_t bo_offset)
172 {
173 const uint8_t cmd_len = (ilo_dev_gen(builder->dev) >= ILO_GEN(8)) ? 4 : 3;
174 uint32_t *dw;
175 unsigned pos;
176
177 ILO_DEV_ASSERT(builder->dev, 7, 8);
178
179 assert(reg % 4 == 0 && bo_offset % 4 == 0);
180
181 pos = ilo_builder_batch_pointer(builder, cmd_len, &dw);
182
183 dw[0] = GEN7_MI_CMD(MI_LOAD_REGISTER_MEM) | (cmd_len - 2);
184 dw[1] = reg;
185
186 if (ilo_dev_gen(builder->dev) >= ILO_GEN(8))
187 ilo_builder_batch_reloc64(builder, pos + 2, bo, bo_offset, 0);
188 else
189 ilo_builder_batch_reloc(builder, pos + 2, bo, bo_offset, 0);
190 }
191
192 /**
193 * Add a MI_BATCH_BUFFER_END to the batch buffer. Pad with MI_NOOP if
194 * necessary.
195 */
196 static inline void
gen6_mi_batch_buffer_end(struct ilo_builder * builder)197 gen6_mi_batch_buffer_end(struct ilo_builder *builder)
198 {
199 /*
200 * From the Sandy Bridge PRM, volume 1 part 1, page 107:
201 *
202 * "The batch buffer must be QWord aligned and a multiple of QWords in
203 * length."
204 */
205 const bool pad = !(builder->writers[ILO_BUILDER_WRITER_BATCH].used & 0x7);
206 uint32_t *dw;
207
208 ILO_DEV_ASSERT(builder->dev, 6, 8);
209
210 if (pad) {
211 ilo_builder_batch_pointer(builder, 2, &dw);
212 dw[0] = GEN6_MI_CMD(MI_BATCH_BUFFER_END);
213 dw[1] = GEN6_MI_CMD(MI_NOOP);
214 } else {
215 ilo_builder_batch_pointer(builder, 1, &dw);
216 dw[0] = GEN6_MI_CMD(MI_BATCH_BUFFER_END);
217 }
218 }
219
220 #endif /* ILO_BUILDER_MI_H */
221