Bug Summary

File:dev/pci/drm/radeon/atom.c
Warning:line 951, column 2
Value stored to 'dst' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name atom.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -target-feature +retpoline-external-thunk -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/llvm16/lib/clang/16 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/legacy-dpm -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu13 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/inc -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc/pmfw_if -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D SUSPEND -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /home/ben/Projects/scan/2024-01-11-110808-61670-1 -x c /usr/src/sys/dev/pci/drm/radeon/atom.c
1/*
2 * Copyright 2008 Advanced Micro Devices, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Author: Stanislaw Skowronek
23 */
24
25#include <linux/module.h>
26#include <linux/sched.h>
27#include <linux/slab.h>
28#include <linux/string_helpers.h>
29
30#include <asm/unaligned.h>
31
32#include <drm/drm_device.h>
33#include <drm/drm_util.h>
34
35#define ATOM_DEBUG
36
37#include "atom.h"
38#include "atom-names.h"
39#include "atom-bits.h"
40#include "radeon.h"
41
42#define ATOM_COND_ABOVE0 0
43#define ATOM_COND_ABOVEOREQUAL1 1
44#define ATOM_COND_ALWAYS2 2
45#define ATOM_COND_BELOW3 3
46#define ATOM_COND_BELOWOREQUAL4 4
47#define ATOM_COND_EQUAL5 5
48#define ATOM_COND_NOTEQUAL6 6
49
50#define ATOM_PORT_ATI0 0
51#define ATOM_PORT_PCI1 1
52#define ATOM_PORT_SYSIO2 2
53
54#define ATOM_UNIT_MICROSEC0 0
55#define ATOM_UNIT_MILLISEC1 1
56
57#define PLL_INDEX2 2
58#define PLL_DATA3 3
59
60typedef struct {
61 struct atom_context *ctx;
62 uint32_t *ps, *ws;
63 int ps_shift;
64 uint16_t start;
65 unsigned last_jump;
66 unsigned long last_jump_jiffies;
67 bool_Bool abort;
68} atom_exec_context;
69
70int atom_debug = 0;
71static int atom_execute_table_locked(struct atom_context *ctx, int index, uint32_t * params);
72int atom_execute_table(struct atom_context *ctx, int index, uint32_t * params);
73
74static uint32_t atom_arg_mask[8] = {
75 0xFFFFFFFF, 0x0000FFFF, 0x00FFFF00, 0xFFFF0000,
76 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000
77};
78static int atom_arg_shift[8] = { 0, 0, 8, 16, 0, 8, 16, 24 };
79
80static int atom_dst_to_src[8][4] = {
81 /* translate destination alignment field to the source alignment encoding */
82 {0, 0, 0, 0},
83 {1, 2, 3, 0},
84 {1, 2, 3, 0},
85 {1, 2, 3, 0},
86 {4, 5, 6, 7},
87 {4, 5, 6, 7},
88 {4, 5, 6, 7},
89 {4, 5, 6, 7},
90};
91static int atom_def_dst[8] = { 0, 0, 1, 2, 0, 1, 2, 3 };
92
93static int debug_depth = 0;
94#ifdef ATOM_DEBUG
95static void debug_print_spaces(int n)
96{
97 while (n--)
98 printk(" ");
99}
100
101#ifdef DEBUG
102#undef DEBUG
103#endif
104
105#define DEBUG(...)do if (atom_debug) { printk("\0017" ...); } while (0) do if (atom_debug) { printk(KERN_DEBUG"\0017" __VA_ARGS__); } while (0)
106#define SDEBUG(...)do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(...); } while (0)
do if (atom_debug) { printk(KERN_DEBUG"\0017"); debug_print_spaces(debug_depth); printk(__VA_ARGS__); } while (0)
107#else
108#define DEBUG(...)do if (atom_debug) { printk("\0017" ...); } while (0) do { } while (0)
109#define SDEBUG(...)do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(...); } while (0)
do { } while (0)
110#endif
111
112static uint32_t atom_iio_execute(struct atom_context *ctx, int base,
113 uint32_t index, uint32_t data)
114{
115 struct radeon_device *rdev = ctx->card->dev->dev_private;
116 uint32_t temp = 0xCDCDCDCD;
117
118 while (1)
119 switch (CU8(base)get_u8(ctx->bios, (base))) {
120 case ATOM_IIO_NOP0:
121 base++;
122 break;
123 case ATOM_IIO_READ2:
124 temp = ctx->card->ioreg_read(ctx->card, CU16(base + 1)get_u16(ctx->bios, (base + 1)));
125 base += 3;
126 break;
127 case ATOM_IIO_WRITE3:
128 if (rdev->family == CHIP_RV515)
129 (void)ctx->card->ioreg_read(ctx->card, CU16(base + 1)get_u16(ctx->bios, (base + 1)));
130 ctx->card->ioreg_write(ctx->card, CU16(base + 1)get_u16(ctx->bios, (base + 1)), temp);
131 base += 3;
132 break;
133 case ATOM_IIO_CLEAR4:
134 temp &=
135 ~((0xFFFFFFFF >> (32 - CU8(base + 1)get_u8(ctx->bios, (base + 1)))) <<
136 CU8(base + 2)get_u8(ctx->bios, (base + 2)));
137 base += 3;
138 break;
139 case ATOM_IIO_SET5:
140 temp |=
141 (0xFFFFFFFF >> (32 - CU8(base + 1)get_u8(ctx->bios, (base + 1)))) << CU8(base +get_u8(ctx->bios, (base + 2))
142 2)get_u8(ctx->bios, (base + 2));
143 base += 3;
144 break;
145 case ATOM_IIO_MOVE_INDEX6:
146 temp &=
147 ~((0xFFFFFFFF >> (32 - CU8(base + 1)get_u8(ctx->bios, (base + 1)))) <<
148 CU8(base + 3)get_u8(ctx->bios, (base + 3)));
149 temp |=
150 ((index >> CU8(base + 2)get_u8(ctx->bios, (base + 2))) &
151 (0xFFFFFFFF >> (32 - CU8(base + 1)get_u8(ctx->bios, (base + 1))))) << CU8(base +get_u8(ctx->bios, (base + 3))
152 3)get_u8(ctx->bios, (base + 3));
153 base += 4;
154 break;
155 case ATOM_IIO_MOVE_DATA8:
156 temp &=
157 ~((0xFFFFFFFF >> (32 - CU8(base + 1)get_u8(ctx->bios, (base + 1)))) <<
158 CU8(base + 3)get_u8(ctx->bios, (base + 3)));
159 temp |=
160 ((data >> CU8(base + 2)get_u8(ctx->bios, (base + 2))) &
161 (0xFFFFFFFF >> (32 - CU8(base + 1)get_u8(ctx->bios, (base + 1))))) << CU8(base +get_u8(ctx->bios, (base + 3))
162 3)get_u8(ctx->bios, (base + 3));
163 base += 4;
164 break;
165 case ATOM_IIO_MOVE_ATTR7:
166 temp &=
167 ~((0xFFFFFFFF >> (32 - CU8(base + 1)get_u8(ctx->bios, (base + 1)))) <<
168 CU8(base + 3)get_u8(ctx->bios, (base + 3)));
169 temp |=
170 ((ctx->
171 io_attr >> CU8(base + 2)get_u8(ctx->bios, (base + 2))) & (0xFFFFFFFF >> (32 -
172 CU8get_u8(ctx->bios, (base + 1))
173 (baseget_u8(ctx->bios, (base + 1))
174 +get_u8(ctx->bios, (base + 1))
175 1)get_u8(ctx->bios, (base + 1)))))
176 << CU8(base + 3)get_u8(ctx->bios, (base + 3));
177 base += 4;
178 break;
179 case ATOM_IIO_END9:
180 return temp;
181 default:
182 pr_info("Unknown IIO opcode\n")do { } while(0);
183 return 0;
184 }
185}
186
187static uint32_t atom_get_src_int(atom_exec_context *ctx, uint8_t attr,
188 int *ptr, uint32_t *saved, int print)
189{
190 uint32_t idx, val = 0xCDCDCDCD, align, arg;
191 struct atom_context *gctx = ctx->ctx;
192 arg = attr & 7;
193 align = (attr >> 3) & 7;
194 switch (arg) {
195 case ATOM_ARG_REG0:
196 idx = U16(*ptr)get_u16(ctx->ctx->bios, (*ptr));
197 (*ptr) += 2;
198 if (print)
199 DEBUG("REG[0x%04X]", idx)do if (atom_debug) { printk("\0017" "REG[0x%04X]", idx); } while
(0)
;
200 idx += gctx->reg_block;
201 switch (gctx->io_mode) {
202 case ATOM_IO_MM0:
203 val = gctx->card->reg_read(gctx->card, idx);
204 break;
205 case ATOM_IO_PCI1:
206 pr_info("PCI registers are not implemented\n")do { } while(0);
207 return 0;
208 case ATOM_IO_SYSIO2:
209 pr_info("SYSIO registers are not implemented\n")do { } while(0);
210 return 0;
211 default:
212 if (!(gctx->io_mode & 0x80)) {
213 pr_info("Bad IO mode\n")do { } while(0);
214 return 0;
215 }
216 if (!gctx->iio[gctx->io_mode & 0x7F]) {
217 pr_info("Undefined indirect IO read method %d\n",do { } while(0)
218 gctx->io_mode & 0x7F)do { } while(0);
219 return 0;
220 }
221 val =
222 atom_iio_execute(gctx,
223 gctx->iio[gctx->io_mode & 0x7F],
224 idx, 0);
225 }
226 break;
227 case ATOM_ARG_PS1:
228 idx = U8(*ptr)get_u8(ctx->ctx->bios, (*ptr));
229 (*ptr)++;
230 /* get_unaligned_le32 avoids unaligned accesses from atombios
231 * tables, noticed on a DEC Alpha. */
232 val = get_unaligned_le32((u32 *)&ctx->ps[idx])((__uint32_t)(*(__uint32_t *)((u32 *)&ctx->ps[idx])));
233 if (print)
234 DEBUG("PS[0x%02X,0x%04X]", idx, val)do if (atom_debug) { printk("\0017" "PS[0x%02X,0x%04X]", idx,
val); } while (0)
;
235 break;
236 case ATOM_ARG_WS2:
237 idx = U8(*ptr)get_u8(ctx->ctx->bios, (*ptr));
238 (*ptr)++;
239 if (print)
240 DEBUG("WS[0x%02X]", idx)do if (atom_debug) { printk("\0017" "WS[0x%02X]", idx); } while
(0)
;
241 switch (idx) {
242 case ATOM_WS_QUOTIENT0x40:
243 val = gctx->divmul[0];
244 break;
245 case ATOM_WS_REMAINDER0x41:
246 val = gctx->divmul[1];
247 break;
248 case ATOM_WS_DATAPTR0x42:
249 val = gctx->data_block;
250 break;
251 case ATOM_WS_SHIFT0x43:
252 val = gctx->shift;
253 break;
254 case ATOM_WS_OR_MASK0x44:
255 val = 1 << gctx->shift;
256 break;
257 case ATOM_WS_AND_MASK0x45:
258 val = ~(1 << gctx->shift);
259 break;
260 case ATOM_WS_FB_WINDOW0x46:
261 val = gctx->fb_base;
262 break;
263 case ATOM_WS_ATTRIBUTES0x47:
264 val = gctx->io_attr;
265 break;
266 case ATOM_WS_REGPTR0x48:
267 val = gctx->reg_block;
268 break;
269 default:
270 val = ctx->ws[idx];
271 }
272 break;
273 case ATOM_ARG_ID4:
274 idx = U16(*ptr)get_u16(ctx->ctx->bios, (*ptr));
275 (*ptr) += 2;
276 if (print) {
277 if (gctx->data_block)
278 DEBUG("ID[0x%04X+%04X]", idx, gctx->data_block)do if (atom_debug) { printk("\0017" "ID[0x%04X+%04X]", idx, gctx
->data_block); } while (0)
;
279 else
280 DEBUG("ID[0x%04X]", idx)do if (atom_debug) { printk("\0017" "ID[0x%04X]", idx); } while
(0)
;
281 }
282 val = U32(idx + gctx->data_block)get_u32(ctx->ctx->bios, (idx + gctx->data_block));
283 break;
284 case ATOM_ARG_FB3:
285 idx = U8(*ptr)get_u8(ctx->ctx->bios, (*ptr));
286 (*ptr)++;
287 if ((gctx->fb_base + (idx * 4)) > gctx->scratch_size_bytes) {
288 DRM_ERROR("ATOM: fb read beyond scratch region: %d vs. %d\n",__drm_err("ATOM: fb read beyond scratch region: %d vs. %d\n",
gctx->fb_base + (idx * 4), gctx->scratch_size_bytes)
289 gctx->fb_base + (idx * 4), gctx->scratch_size_bytes)__drm_err("ATOM: fb read beyond scratch region: %d vs. %d\n",
gctx->fb_base + (idx * 4), gctx->scratch_size_bytes)
;
290 val = 0;
291 } else
292 val = gctx->scratch[(gctx->fb_base / 4) + idx];
293 if (print)
294 DEBUG("FB[0x%02X]", idx)do if (atom_debug) { printk("\0017" "FB[0x%02X]", idx); } while
(0)
;
295 break;
296 case ATOM_ARG_IMM5:
297 switch (align) {
298 case ATOM_SRC_DWORD0:
299 val = U32(*ptr)get_u32(ctx->ctx->bios, (*ptr));
300 (*ptr) += 4;
301 if (print)
302 DEBUG("IMM 0x%08X\n", val)do if (atom_debug) { printk("\0017" "IMM 0x%08X\n", val); } while
(0)
;
303 return val;
304 case ATOM_SRC_WORD01:
305 case ATOM_SRC_WORD82:
306 case ATOM_SRC_WORD163:
307 val = U16(*ptr)get_u16(ctx->ctx->bios, (*ptr));
308 (*ptr) += 2;
309 if (print)
310 DEBUG("IMM 0x%04X\n", val)do if (atom_debug) { printk("\0017" "IMM 0x%04X\n", val); } while
(0)
;
311 return val;
312 case ATOM_SRC_BYTE04:
313 case ATOM_SRC_BYTE85:
314 case ATOM_SRC_BYTE166:
315 case ATOM_SRC_BYTE247:
316 val = U8(*ptr)get_u8(ctx->ctx->bios, (*ptr));
317 (*ptr)++;
318 if (print)
319 DEBUG("IMM 0x%02X\n", val)do if (atom_debug) { printk("\0017" "IMM 0x%02X\n", val); } while
(0)
;
320 return val;
321 }
322 return 0;
323 case ATOM_ARG_PLL6:
324 idx = U8(*ptr)get_u8(ctx->ctx->bios, (*ptr));
325 (*ptr)++;
326 if (print)
327 DEBUG("PLL[0x%02X]", idx)do if (atom_debug) { printk("\0017" "PLL[0x%02X]", idx); } while
(0)
;
328 val = gctx->card->pll_read(gctx->card, idx);
329 break;
330 case ATOM_ARG_MC7:
331 idx = U8(*ptr)get_u8(ctx->ctx->bios, (*ptr));
332 (*ptr)++;
333 if (print)
334 DEBUG("MC[0x%02X]", idx)do if (atom_debug) { printk("\0017" "MC[0x%02X]", idx); } while
(0)
;
335 val = gctx->card->mc_read(gctx->card, idx);
336 break;
337 }
338 if (saved)
339 *saved = val;
340 val &= atom_arg_mask[align];
341 val >>= atom_arg_shift[align];
342 if (print)
343 switch (align) {
344 case ATOM_SRC_DWORD0:
345 DEBUG(".[31:0] -> 0x%08X\n", val)do if (atom_debug) { printk("\0017" ".[31:0] -> 0x%08X\n",
val); } while (0)
;
346 break;
347 case ATOM_SRC_WORD01:
348 DEBUG(".[15:0] -> 0x%04X\n", val)do if (atom_debug) { printk("\0017" ".[15:0] -> 0x%04X\n",
val); } while (0)
;
349 break;
350 case ATOM_SRC_WORD82:
351 DEBUG(".[23:8] -> 0x%04X\n", val)do if (atom_debug) { printk("\0017" ".[23:8] -> 0x%04X\n",
val); } while (0)
;
352 break;
353 case ATOM_SRC_WORD163:
354 DEBUG(".[31:16] -> 0x%04X\n", val)do if (atom_debug) { printk("\0017" ".[31:16] -> 0x%04X\n"
, val); } while (0)
;
355 break;
356 case ATOM_SRC_BYTE04:
357 DEBUG(".[7:0] -> 0x%02X\n", val)do if (atom_debug) { printk("\0017" ".[7:0] -> 0x%02X\n", val
); } while (0)
;
358 break;
359 case ATOM_SRC_BYTE85:
360 DEBUG(".[15:8] -> 0x%02X\n", val)do if (atom_debug) { printk("\0017" ".[15:8] -> 0x%02X\n",
val); } while (0)
;
361 break;
362 case ATOM_SRC_BYTE166:
363 DEBUG(".[23:16] -> 0x%02X\n", val)do if (atom_debug) { printk("\0017" ".[23:16] -> 0x%02X\n"
, val); } while (0)
;
364 break;
365 case ATOM_SRC_BYTE247:
366 DEBUG(".[31:24] -> 0x%02X\n", val)do if (atom_debug) { printk("\0017" ".[31:24] -> 0x%02X\n"
, val); } while (0)
;
367 break;
368 }
369 return val;
370}
371
372static void atom_skip_src_int(atom_exec_context *ctx, uint8_t attr, int *ptr)
373{
374 uint32_t align = (attr >> 3) & 7, arg = attr & 7;
375 switch (arg) {
376 case ATOM_ARG_REG0:
377 case ATOM_ARG_ID4:
378 (*ptr) += 2;
379 break;
380 case ATOM_ARG_PLL6:
381 case ATOM_ARG_MC7:
382 case ATOM_ARG_PS1:
383 case ATOM_ARG_WS2:
384 case ATOM_ARG_FB3:
385 (*ptr)++;
386 break;
387 case ATOM_ARG_IMM5:
388 switch (align) {
389 case ATOM_SRC_DWORD0:
390 (*ptr) += 4;
391 return;
392 case ATOM_SRC_WORD01:
393 case ATOM_SRC_WORD82:
394 case ATOM_SRC_WORD163:
395 (*ptr) += 2;
396 return;
397 case ATOM_SRC_BYTE04:
398 case ATOM_SRC_BYTE85:
399 case ATOM_SRC_BYTE166:
400 case ATOM_SRC_BYTE247:
401 (*ptr)++;
402 return;
403 }
404 return;
405 }
406}
407
408static uint32_t atom_get_src(atom_exec_context *ctx, uint8_t attr, int *ptr)
409{
410 return atom_get_src_int(ctx, attr, ptr, NULL((void *)0), 1);
411}
412
413static uint32_t atom_get_src_direct(atom_exec_context *ctx, uint8_t align, int *ptr)
414{
415 uint32_t val = 0xCDCDCDCD;
416
417 switch (align) {
418 case ATOM_SRC_DWORD0:
419 val = U32(*ptr)get_u32(ctx->ctx->bios, (*ptr));
420 (*ptr) += 4;
421 break;
422 case ATOM_SRC_WORD01:
423 case ATOM_SRC_WORD82:
424 case ATOM_SRC_WORD163:
425 val = U16(*ptr)get_u16(ctx->ctx->bios, (*ptr));
426 (*ptr) += 2;
427 break;
428 case ATOM_SRC_BYTE04:
429 case ATOM_SRC_BYTE85:
430 case ATOM_SRC_BYTE166:
431 case ATOM_SRC_BYTE247:
432 val = U8(*ptr)get_u8(ctx->ctx->bios, (*ptr));
433 (*ptr)++;
434 break;
435 }
436 return val;
437}
438
439static uint32_t atom_get_dst(atom_exec_context *ctx, int arg, uint8_t attr,
440 int *ptr, uint32_t *saved, int print)
441{
442 return atom_get_src_int(ctx,
443 arg | atom_dst_to_src[(attr >> 3) &
444 7][(attr >> 6) & 3] << 3,
445 ptr, saved, print);
446}
447
448static void atom_skip_dst(atom_exec_context *ctx, int arg, uint8_t attr, int *ptr)
449{
450 atom_skip_src_int(ctx,
451 arg | atom_dst_to_src[(attr >> 3) & 7][(attr >> 6) &
452 3] << 3, ptr);
453}
454
455static void atom_put_dst(atom_exec_context *ctx, int arg, uint8_t attr,
456 int *ptr, uint32_t val, uint32_t saved)
457{
458 uint32_t align =
459 atom_dst_to_src[(attr >> 3) & 7][(attr >> 6) & 3], old_val =
460 val, idx;
461 struct atom_context *gctx = ctx->ctx;
462 old_val &= atom_arg_mask[align] >> atom_arg_shift[align];
463 val <<= atom_arg_shift[align];
464 val &= atom_arg_mask[align];
465 saved &= ~atom_arg_mask[align];
466 val |= saved;
467 switch (arg) {
468 case ATOM_ARG_REG0:
469 idx = U16(*ptr)get_u16(ctx->ctx->bios, (*ptr));
470 (*ptr) += 2;
471 DEBUG("REG[0x%04X]", idx)do if (atom_debug) { printk("\0017" "REG[0x%04X]", idx); } while
(0)
;
472 idx += gctx->reg_block;
473 switch (gctx->io_mode) {
474 case ATOM_IO_MM0:
475 if (idx == 0)
476 gctx->card->reg_write(gctx->card, idx,
477 val << 2);
478 else
479 gctx->card->reg_write(gctx->card, idx, val);
480 break;
481 case ATOM_IO_PCI1:
482 pr_info("PCI registers are not implemented\n")do { } while(0);
483 return;
484 case ATOM_IO_SYSIO2:
485 pr_info("SYSIO registers are not implemented\n")do { } while(0);
486 return;
487 default:
488 if (!(gctx->io_mode & 0x80)) {
489 pr_info("Bad IO mode\n")do { } while(0);
490 return;
491 }
492 if (!gctx->iio[gctx->io_mode & 0xFF]) {
493 pr_info("Undefined indirect IO write method %d\n",do { } while(0)
494 gctx->io_mode & 0x7F)do { } while(0);
495 return;
496 }
497 atom_iio_execute(gctx, gctx->iio[gctx->io_mode & 0xFF],
498 idx, val);
499 }
500 break;
501 case ATOM_ARG_PS1:
502 idx = U8(*ptr)get_u8(ctx->ctx->bios, (*ptr));
503 (*ptr)++;
504 DEBUG("PS[0x%02X]", idx)do if (atom_debug) { printk("\0017" "PS[0x%02X]", idx); } while
(0)
;
505 ctx->ps[idx] = cpu_to_le32(val)((__uint32_t)(val));
506 break;
507 case ATOM_ARG_WS2:
508 idx = U8(*ptr)get_u8(ctx->ctx->bios, (*ptr));
509 (*ptr)++;
510 DEBUG("WS[0x%02X]", idx)do if (atom_debug) { printk("\0017" "WS[0x%02X]", idx); } while
(0)
;
511 switch (idx) {
512 case ATOM_WS_QUOTIENT0x40:
513 gctx->divmul[0] = val;
514 break;
515 case ATOM_WS_REMAINDER0x41:
516 gctx->divmul[1] = val;
517 break;
518 case ATOM_WS_DATAPTR0x42:
519 gctx->data_block = val;
520 break;
521 case ATOM_WS_SHIFT0x43:
522 gctx->shift = val;
523 break;
524 case ATOM_WS_OR_MASK0x44:
525 case ATOM_WS_AND_MASK0x45:
526 break;
527 case ATOM_WS_FB_WINDOW0x46:
528 gctx->fb_base = val;
529 break;
530 case ATOM_WS_ATTRIBUTES0x47:
531 gctx->io_attr = val;
532 break;
533 case ATOM_WS_REGPTR0x48:
534 gctx->reg_block = val;
535 break;
536 default:
537 ctx->ws[idx] = val;
538 }
539 break;
540 case ATOM_ARG_FB3:
541 idx = U8(*ptr)get_u8(ctx->ctx->bios, (*ptr));
542 (*ptr)++;
543 if ((gctx->fb_base + (idx * 4)) > gctx->scratch_size_bytes) {
544 DRM_ERROR("ATOM: fb write beyond scratch region: %d vs. %d\n",__drm_err("ATOM: fb write beyond scratch region: %d vs. %d\n"
, gctx->fb_base + (idx * 4), gctx->scratch_size_bytes)
545 gctx->fb_base + (idx * 4), gctx->scratch_size_bytes)__drm_err("ATOM: fb write beyond scratch region: %d vs. %d\n"
, gctx->fb_base + (idx * 4), gctx->scratch_size_bytes)
;
546 } else
547 gctx->scratch[(gctx->fb_base / 4) + idx] = val;
548 DEBUG("FB[0x%02X]", idx)do if (atom_debug) { printk("\0017" "FB[0x%02X]", idx); } while
(0)
;
549 break;
550 case ATOM_ARG_PLL6:
551 idx = U8(*ptr)get_u8(ctx->ctx->bios, (*ptr));
552 (*ptr)++;
553 DEBUG("PLL[0x%02X]", idx)do if (atom_debug) { printk("\0017" "PLL[0x%02X]", idx); } while
(0)
;
554 gctx->card->pll_write(gctx->card, idx, val);
555 break;
556 case ATOM_ARG_MC7:
557 idx = U8(*ptr)get_u8(ctx->ctx->bios, (*ptr));
558 (*ptr)++;
559 DEBUG("MC[0x%02X]", idx)do if (atom_debug) { printk("\0017" "MC[0x%02X]", idx); } while
(0)
;
560 gctx->card->mc_write(gctx->card, idx, val);
561 return;
562 }
563 switch (align) {
564 case ATOM_SRC_DWORD0:
565 DEBUG(".[31:0] <- 0x%08X\n", old_val)do if (atom_debug) { printk("\0017" ".[31:0] <- 0x%08X\n",
old_val); } while (0)
;
566 break;
567 case ATOM_SRC_WORD01:
568 DEBUG(".[15:0] <- 0x%04X\n", old_val)do if (atom_debug) { printk("\0017" ".[15:0] <- 0x%04X\n",
old_val); } while (0)
;
569 break;
570 case ATOM_SRC_WORD82:
571 DEBUG(".[23:8] <- 0x%04X\n", old_val)do if (atom_debug) { printk("\0017" ".[23:8] <- 0x%04X\n",
old_val); } while (0)
;
572 break;
573 case ATOM_SRC_WORD163:
574 DEBUG(".[31:16] <- 0x%04X\n", old_val)do if (atom_debug) { printk("\0017" ".[31:16] <- 0x%04X\n"
, old_val); } while (0)
;
575 break;
576 case ATOM_SRC_BYTE04:
577 DEBUG(".[7:0] <- 0x%02X\n", old_val)do if (atom_debug) { printk("\0017" ".[7:0] <- 0x%02X\n", old_val
); } while (0)
;
578 break;
579 case ATOM_SRC_BYTE85:
580 DEBUG(".[15:8] <- 0x%02X\n", old_val)do if (atom_debug) { printk("\0017" ".[15:8] <- 0x%02X\n",
old_val); } while (0)
;
581 break;
582 case ATOM_SRC_BYTE166:
583 DEBUG(".[23:16] <- 0x%02X\n", old_val)do if (atom_debug) { printk("\0017" ".[23:16] <- 0x%02X\n"
, old_val); } while (0)
;
584 break;
585 case ATOM_SRC_BYTE247:
586 DEBUG(".[31:24] <- 0x%02X\n", old_val)do if (atom_debug) { printk("\0017" ".[31:24] <- 0x%02X\n"
, old_val); } while (0)
;
587 break;
588 }
589}
590
591static void atom_op_add(atom_exec_context *ctx, int *ptr, int arg)
592{
593 uint8_t attr = U8((*ptr)++)get_u8(ctx->ctx->bios, ((*ptr)++));
594 uint32_t dst, src, saved;
595 int dptr = *ptr;
596 SDEBUG(" dst: ")do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" dst: "); } while (0)
;
597 dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
598 SDEBUG(" src: ")do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" src: "); } while (0)
;
599 src = atom_get_src(ctx, attr, ptr);
600 dst += src;
601 SDEBUG(" dst: ")do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" dst: "); } while (0)
;
602 atom_put_dst(ctx, arg, attr, &dptr, dst, saved);
603}
604
605static void atom_op_and(atom_exec_context *ctx, int *ptr, int arg)
606{
607 uint8_t attr = U8((*ptr)++)get_u8(ctx->ctx->bios, ((*ptr)++));
608 uint32_t dst, src, saved;
609 int dptr = *ptr;
610 SDEBUG(" dst: ")do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" dst: "); } while (0)
;
611 dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
612 SDEBUG(" src: ")do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" src: "); } while (0)
;
613 src = atom_get_src(ctx, attr, ptr);
614 dst &= src;
615 SDEBUG(" dst: ")do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" dst: "); } while (0)
;
616 atom_put_dst(ctx, arg, attr, &dptr, dst, saved);
617}
618
619static void atom_op_beep(atom_exec_context *ctx, int *ptr, int arg)
620{
621 printk("ATOM BIOS beeped!\n");
622}
623
624static void atom_op_calltable(atom_exec_context *ctx, int *ptr, int arg)
625{
626 int idx = U8((*ptr)++)get_u8(ctx->ctx->bios, ((*ptr)++));
627 int r = 0;
628
629 if (idx < ATOM_TABLE_NAMES_CNT74)
630 SDEBUG(" table: %d (%s)\n", idx, atom_table_names[idx])do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" table: %d (%s)\n", idx, atom_table_names[idx]);
} while (0)
;
631 else
632 SDEBUG(" table: %d\n", idx)do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" table: %d\n", idx); } while (0)
;
633 if (U16(ctx->ctx->cmd_table + 4 + 2 * idx)get_u16(ctx->ctx->bios, (ctx->ctx->cmd_table + 4 +
2 * idx))
)
634 r = atom_execute_table_locked(ctx->ctx, idx, ctx->ps + ctx->ps_shift);
635 if (r) {
636 ctx->abort = true1;
637 }
638}
639
640static void atom_op_clear(atom_exec_context *ctx, int *ptr, int arg)
641{
642 uint8_t attr = U8((*ptr)++)get_u8(ctx->ctx->bios, ((*ptr)++));
643 uint32_t saved;
644 int dptr = *ptr;
645 attr &= 0x38;
646 attr |= atom_def_dst[attr >> 3] << 6;
647 atom_get_dst(ctx, arg, attr, ptr, &saved, 0);
648 SDEBUG(" dst: ")do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" dst: "); } while (0)
;
649 atom_put_dst(ctx, arg, attr, &dptr, 0, saved);
650}
651
652static void atom_op_compare(atom_exec_context *ctx, int *ptr, int arg)
653{
654 uint8_t attr = U8((*ptr)++)get_u8(ctx->ctx->bios, ((*ptr)++));
655 uint32_t dst, src;
656 SDEBUG(" src1: ")do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" src1: "); } while (0)
;
657 dst = atom_get_dst(ctx, arg, attr, ptr, NULL((void *)0), 1);
658 SDEBUG(" src2: ")do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" src2: "); } while (0)
;
659 src = atom_get_src(ctx, attr, ptr);
660 ctx->ctx->cs_equal = (dst == src);
661 ctx->ctx->cs_above = (dst > src);
662 SDEBUG(" result: %s %s\n", ctx->ctx->cs_equal ? "EQ" : "NE",do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" result: %s %s\n", ctx->ctx->cs_equal ? "EQ"
: "NE", ctx->ctx->cs_above ? "GT" : "LE"); } while (0)
663 ctx->ctx->cs_above ? "GT" : "LE")do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" result: %s %s\n", ctx->ctx->cs_equal ? "EQ"
: "NE", ctx->ctx->cs_above ? "GT" : "LE"); } while (0)
;
664}
665
666static void atom_op_delay(atom_exec_context *ctx, int *ptr, int arg)
667{
668 unsigned count = U8((*ptr)++)get_u8(ctx->ctx->bios, ((*ptr)++));
669 SDEBUG(" count: %d\n", count)do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" count: %d\n", count); } while (0)
;
670 if (arg == ATOM_UNIT_MICROSEC0)
671 udelay(count);
672 else if (!drm_can_sleep())
673 mdelay(count);
674 else
675 drm_msleep(count)mdelay(count);
676}
677
678static void atom_op_div(atom_exec_context *ctx, int *ptr, int arg)
679{
680 uint8_t attr = U8((*ptr)++)get_u8(ctx->ctx->bios, ((*ptr)++));
681 uint32_t dst, src;
682 SDEBUG(" src1: ")do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" src1: "); } while (0)
;
683 dst = atom_get_dst(ctx, arg, attr, ptr, NULL((void *)0), 1);
684 SDEBUG(" src2: ")do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" src2: "); } while (0)
;
685 src = atom_get_src(ctx, attr, ptr);
686 if (src != 0) {
687 ctx->ctx->divmul[0] = dst / src;
688 ctx->ctx->divmul[1] = dst % src;
689 } else {
690 ctx->ctx->divmul[0] = 0;
691 ctx->ctx->divmul[1] = 0;
692 }
693}
694
695static void atom_op_eot(atom_exec_context *ctx, int *ptr, int arg)
696{
697 /* functionally, a nop */
698}
699
700static void atom_op_jump(atom_exec_context *ctx, int *ptr, int arg)
701{
702 int execute = 0, target = U16(*ptr)get_u16(ctx->ctx->bios, (*ptr));
703 unsigned long cjiffies;
704
705 (*ptr) += 2;
706 switch (arg) {
707 case ATOM_COND_ABOVE0:
708 execute = ctx->ctx->cs_above;
709 break;
710 case ATOM_COND_ABOVEOREQUAL1:
711 execute = ctx->ctx->cs_above || ctx->ctx->cs_equal;
712 break;
713 case ATOM_COND_ALWAYS2:
714 execute = 1;
715 break;
716 case ATOM_COND_BELOW3:
717 execute = !(ctx->ctx->cs_above || ctx->ctx->cs_equal);
718 break;
719 case ATOM_COND_BELOWOREQUAL4:
720 execute = !ctx->ctx->cs_above;
721 break;
722 case ATOM_COND_EQUAL5:
723 execute = ctx->ctx->cs_equal;
724 break;
725 case ATOM_COND_NOTEQUAL6:
726 execute = !ctx->ctx->cs_equal;
727 break;
728 }
729 if (arg != ATOM_COND_ALWAYS2)
730 SDEBUG(" taken: %s\n", str_yes_no(execute))do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" taken: %s\n", str_yes_no(execute)); } while (0)
;
731 SDEBUG(" target: 0x%04X\n", target)do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" target: 0x%04X\n", target); } while (0)
;
732 if (execute) {
733 if (ctx->last_jump == (ctx->start + target)) {
734 cjiffies = jiffies;
735 if (time_after(cjiffies, ctx->last_jump_jiffies)) {
736 cjiffies -= ctx->last_jump_jiffies;
737 if ((jiffies_to_msecs(cjiffies) > 5000)) {
738 DRM_ERROR("atombios stuck in loop for more than 5secs aborting\n")__drm_err("atombios stuck in loop for more than 5secs aborting\n"
)
;
739 ctx->abort = true1;
740 }
741 } else {
742 /* jiffies wrap around we will just wait a little longer */
743 ctx->last_jump_jiffies = jiffies;
744 }
745 } else {
746 ctx->last_jump = ctx->start + target;
747 ctx->last_jump_jiffies = jiffies;
748 }
749 *ptr = ctx->start + target;
750 }
751}
752
753static void atom_op_mask(atom_exec_context *ctx, int *ptr, int arg)
754{
755 uint8_t attr = U8((*ptr)++)get_u8(ctx->ctx->bios, ((*ptr)++));
756 uint32_t dst, mask, src, saved;
757 int dptr = *ptr;
758 SDEBUG(" dst: ")do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" dst: "); } while (0)
;
759 dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
760 mask = atom_get_src_direct(ctx, ((attr >> 3) & 7), ptr);
761 SDEBUG(" mask: 0x%08x", mask)do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" mask: 0x%08x", mask); } while (0)
;
762 SDEBUG(" src: ")do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" src: "); } while (0)
;
763 src = atom_get_src(ctx, attr, ptr);
764 dst &= mask;
765 dst |= src;
766 SDEBUG(" dst: ")do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" dst: "); } while (0)
;
767 atom_put_dst(ctx, arg, attr, &dptr, dst, saved);
768}
769
770static void atom_op_move(atom_exec_context *ctx, int *ptr, int arg)
771{
772 uint8_t attr = U8((*ptr)++)get_u8(ctx->ctx->bios, ((*ptr)++));
773 uint32_t src, saved;
774 int dptr = *ptr;
775 if (((attr >> 3) & 7) != ATOM_SRC_DWORD0)
776 atom_get_dst(ctx, arg, attr, ptr, &saved, 0);
777 else {
778 atom_skip_dst(ctx, arg, attr, ptr);
779 saved = 0xCDCDCDCD;
780 }
781 SDEBUG(" src: ")do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" src: "); } while (0)
;
782 src = atom_get_src(ctx, attr, ptr);
783 SDEBUG(" dst: ")do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" dst: "); } while (0)
;
784 atom_put_dst(ctx, arg, attr, &dptr, src, saved);
785}
786
787static void atom_op_mul(atom_exec_context *ctx, int *ptr, int arg)
788{
789 uint8_t attr = U8((*ptr)++)get_u8(ctx->ctx->bios, ((*ptr)++));
790 uint32_t dst, src;
791 SDEBUG(" src1: ")do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" src1: "); } while (0)
;
792 dst = atom_get_dst(ctx, arg, attr, ptr, NULL((void *)0), 1);
793 SDEBUG(" src2: ")do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" src2: "); } while (0)
;
794 src = atom_get_src(ctx, attr, ptr);
795 ctx->ctx->divmul[0] = dst * src;
796}
797
798static void atom_op_nop(atom_exec_context *ctx, int *ptr, int arg)
799{
800 /* nothing */
801}
802
803static void atom_op_or(atom_exec_context *ctx, int *ptr, int arg)
804{
805 uint8_t attr = U8((*ptr)++)get_u8(ctx->ctx->bios, ((*ptr)++));
806 uint32_t dst, src, saved;
807 int dptr = *ptr;
808 SDEBUG(" dst: ")do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" dst: "); } while (0)
;
809 dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
810 SDEBUG(" src: ")do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" src: "); } while (0)
;
811 src = atom_get_src(ctx, attr, ptr);
812 dst |= src;
813 SDEBUG(" dst: ")do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" dst: "); } while (0)
;
814 atom_put_dst(ctx, arg, attr, &dptr, dst, saved);
815}
816
817static void atom_op_postcard(atom_exec_context *ctx, int *ptr, int arg)
818{
819 uint8_t val = U8((*ptr)++)get_u8(ctx->ctx->bios, ((*ptr)++));
820 SDEBUG("POST card output: 0x%02X\n", val)do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk("POST card output: 0x%02X\n", val); } while (0)
;
821}
822
823static void atom_op_repeat(atom_exec_context *ctx, int *ptr, int arg)
824{
825 pr_info("unimplemented!\n")do { } while(0);
826}
827
828static void atom_op_restorereg(atom_exec_context *ctx, int *ptr, int arg)
829{
830 pr_info("unimplemented!\n")do { } while(0);
831}
832
833static void atom_op_savereg(atom_exec_context *ctx, int *ptr, int arg)
834{
835 pr_info("unimplemented!\n")do { } while(0);
836}
837
838static void atom_op_setdatablock(atom_exec_context *ctx, int *ptr, int arg)
839{
840 int idx = U8(*ptr)get_u8(ctx->ctx->bios, (*ptr));
841 (*ptr)++;
842 SDEBUG(" block: %d\n", idx)do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" block: %d\n", idx); } while (0)
;
843 if (!idx)
844 ctx->ctx->data_block = 0;
845 else if (idx == 255)
846 ctx->ctx->data_block = ctx->start;
847 else
848 ctx->ctx->data_block = U16(ctx->ctx->data_table + 4 + 2 * idx)get_u16(ctx->ctx->bios, (ctx->ctx->data_table + 4
+ 2 * idx))
;
849 SDEBUG(" base: 0x%04X\n", ctx->ctx->data_block)do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" base: 0x%04X\n", ctx->ctx->data_block); }
while (0)
;
850}
851
852static void atom_op_setfbbase(atom_exec_context *ctx, int *ptr, int arg)
853{
854 uint8_t attr = U8((*ptr)++)get_u8(ctx->ctx->bios, ((*ptr)++));
855 SDEBUG(" fb_base: ")do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" fb_base: "); } while (0)
;
856 ctx->ctx->fb_base = atom_get_src(ctx, attr, ptr);
857}
858
859static void atom_op_setport(atom_exec_context *ctx, int *ptr, int arg)
860{
861 int port;
862 switch (arg) {
863 case ATOM_PORT_ATI0:
864 port = U16(*ptr)get_u16(ctx->ctx->bios, (*ptr));
865 if (port < ATOM_IO_NAMES_CNT5)
866 SDEBUG(" port: %d (%s)\n", port, atom_io_names[port])do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" port: %d (%s)\n", port, atom_io_names[port]); }
while (0)
;
867 else
868 SDEBUG(" port: %d\n", port)do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" port: %d\n", port); } while (0)
;
869 if (!port)
870 ctx->ctx->io_mode = ATOM_IO_MM0;
871 else
872 ctx->ctx->io_mode = ATOM_IO_IIO0x80 | port;
873 (*ptr) += 2;
874 break;
875 case ATOM_PORT_PCI1:
876 ctx->ctx->io_mode = ATOM_IO_PCI1;
877 (*ptr)++;
878 break;
879 case ATOM_PORT_SYSIO2:
880 ctx->ctx->io_mode = ATOM_IO_SYSIO2;
881 (*ptr)++;
882 break;
883 }
884}
885
886static void atom_op_setregblock(atom_exec_context *ctx, int *ptr, int arg)
887{
888 ctx->ctx->reg_block = U16(*ptr)get_u16(ctx->ctx->bios, (*ptr));
889 (*ptr) += 2;
890 SDEBUG(" base: 0x%04X\n", ctx->ctx->reg_block)do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" base: 0x%04X\n", ctx->ctx->reg_block); } while
(0)
;
891}
892
893static void atom_op_shift_left(atom_exec_context *ctx, int *ptr, int arg)
894{
895 uint8_t attr = U8((*ptr)++)get_u8(ctx->ctx->bios, ((*ptr)++)), shift;
896 uint32_t saved, dst;
897 int dptr = *ptr;
898 attr &= 0x38;
899 attr |= atom_def_dst[attr >> 3] << 6;
900 SDEBUG(" dst: ")do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" dst: "); } while (0)
;
901 dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
902 shift = atom_get_src_direct(ctx, ATOM_SRC_BYTE04, ptr);
903 SDEBUG(" shift: %d\n", shift)do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" shift: %d\n", shift); } while (0)
;
904 dst <<= shift;
905 SDEBUG(" dst: ")do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" dst: "); } while (0)
;
906 atom_put_dst(ctx, arg, attr, &dptr, dst, saved);
907}
908
909static void atom_op_shift_right(atom_exec_context *ctx, int *ptr, int arg)
910{
911 uint8_t attr = U8((*ptr)++)get_u8(ctx->ctx->bios, ((*ptr)++)), shift;
912 uint32_t saved, dst;
913 int dptr = *ptr;
914 attr &= 0x38;
915 attr |= atom_def_dst[attr >> 3] << 6;
916 SDEBUG(" dst: ")do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" dst: "); } while (0)
;
917 dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
918 shift = atom_get_src_direct(ctx, ATOM_SRC_BYTE04, ptr);
919 SDEBUG(" shift: %d\n", shift)do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" shift: %d\n", shift); } while (0)
;
920 dst >>= shift;
921 SDEBUG(" dst: ")do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" dst: "); } while (0)
;
922 atom_put_dst(ctx, arg, attr, &dptr, dst, saved);
923}
924
925static void atom_op_shl(atom_exec_context *ctx, int *ptr, int arg)
926{
927 uint8_t attr = U8((*ptr)++)get_u8(ctx->ctx->bios, ((*ptr)++)), shift;
928 uint32_t saved, dst;
929 int dptr = *ptr;
930 uint32_t dst_align = atom_dst_to_src[(attr >> 3) & 7][(attr >> 6) & 3];
931 SDEBUG(" dst: ")do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" dst: "); } while (0)
;
932 dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
933 /* op needs to full dst value */
934 dst = saved;
935 shift = atom_get_src(ctx, attr, ptr);
936 SDEBUG(" shift: %d\n", shift)do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" shift: %d\n", shift); } while (0)
;
937 dst <<= shift;
938 dst &= atom_arg_mask[dst_align];
939 dst >>= atom_arg_shift[dst_align];
940 SDEBUG(" dst: ")do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" dst: "); } while (0)
;
941 atom_put_dst(ctx, arg, attr, &dptr, dst, saved);
942}
943
944static void atom_op_shr(atom_exec_context *ctx, int *ptr, int arg)
945{
946 uint8_t attr = U8((*ptr)++)get_u8(ctx->ctx->bios, ((*ptr)++)), shift;
947 uint32_t saved, dst;
948 int dptr = *ptr;
949 uint32_t dst_align = atom_dst_to_src[(attr >> 3) & 7][(attr >> 6) & 3];
950 SDEBUG(" dst: ")do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" dst: "); } while (0)
;
951 dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
Value stored to 'dst' is never read
952 /* op needs to full dst value */
953 dst = saved;
954 shift = atom_get_src(ctx, attr, ptr);
955 SDEBUG(" shift: %d\n", shift)do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" shift: %d\n", shift); } while (0)
;
956 dst >>= shift;
957 dst &= atom_arg_mask[dst_align];
958 dst >>= atom_arg_shift[dst_align];
959 SDEBUG(" dst: ")do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" dst: "); } while (0)
;
960 atom_put_dst(ctx, arg, attr, &dptr, dst, saved);
961}
962
963static void atom_op_sub(atom_exec_context *ctx, int *ptr, int arg)
964{
965 uint8_t attr = U8((*ptr)++)get_u8(ctx->ctx->bios, ((*ptr)++));
966 uint32_t dst, src, saved;
967 int dptr = *ptr;
968 SDEBUG(" dst: ")do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" dst: "); } while (0)
;
969 dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
970 SDEBUG(" src: ")do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" src: "); } while (0)
;
971 src = atom_get_src(ctx, attr, ptr);
972 dst -= src;
973 SDEBUG(" dst: ")do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" dst: "); } while (0)
;
974 atom_put_dst(ctx, arg, attr, &dptr, dst, saved);
975}
976
977static void atom_op_switch(atom_exec_context *ctx, int *ptr, int arg)
978{
979 uint8_t attr = U8((*ptr)++)get_u8(ctx->ctx->bios, ((*ptr)++));
980 uint32_t src, val, target;
981 SDEBUG(" switch: ")do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" switch: "); } while (0)
;
982 src = atom_get_src(ctx, attr, ptr);
983 while (U16(*ptr)get_u16(ctx->ctx->bios, (*ptr)) != ATOM_CASE_END0x5A5A)
984 if (U8(*ptr)get_u8(ctx->ctx->bios, (*ptr)) == ATOM_CASE_MAGIC0x63) {
985 (*ptr)++;
986 SDEBUG(" case: ")do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" case: "); } while (0)
;
987 val =
988 atom_get_src(ctx, (attr & 0x38) | ATOM_ARG_IMM5,
989 ptr);
990 target = U16(*ptr)get_u16(ctx->ctx->bios, (*ptr));
991 if (val == src) {
992 SDEBUG(" target: %04X\n", target)do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" target: %04X\n", target); } while (0)
;
993 *ptr = ctx->start + target;
994 return;
995 }
996 (*ptr) += 2;
997 } else {
998 pr_info("Bad case\n")do { } while(0);
999 return;
1000 }
1001 (*ptr) += 2;
1002}
1003
1004static void atom_op_test(atom_exec_context *ctx, int *ptr, int arg)
1005{
1006 uint8_t attr = U8((*ptr)++)get_u8(ctx->ctx->bios, ((*ptr)++));
1007 uint32_t dst, src;
1008 SDEBUG(" src1: ")do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" src1: "); } while (0)
;
1009 dst = atom_get_dst(ctx, arg, attr, ptr, NULL((void *)0), 1);
1010 SDEBUG(" src2: ")do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" src2: "); } while (0)
;
1011 src = atom_get_src(ctx, attr, ptr);
1012 ctx->ctx->cs_equal = ((dst & src) == 0);
1013 SDEBUG(" result: %s\n", ctx->ctx->cs_equal ? "EQ" : "NE")do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" result: %s\n", ctx->ctx->cs_equal ? "EQ" :
"NE"); } while (0)
;
1014}
1015
1016static void atom_op_xor(atom_exec_context *ctx, int *ptr, int arg)
1017{
1018 uint8_t attr = U8((*ptr)++)get_u8(ctx->ctx->bios, ((*ptr)++));
1019 uint32_t dst, src, saved;
1020 int dptr = *ptr;
1021 SDEBUG(" dst: ")do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" dst: "); } while (0)
;
1022 dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
1023 SDEBUG(" src: ")do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" src: "); } while (0)
;
1024 src = atom_get_src(ctx, attr, ptr);
1025 dst ^= src;
1026 SDEBUG(" dst: ")do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(" dst: "); } while (0)
;
1027 atom_put_dst(ctx, arg, attr, &dptr, dst, saved);
1028}
1029
1030static void atom_op_debug(atom_exec_context *ctx, int *ptr, int arg)
1031{
1032 pr_info("unimplemented!\n")do { } while(0);
1033}
1034
1035static struct {
1036 void (*func) (atom_exec_context *, int *, int);
1037 int arg;
1038} opcode_table[ATOM_OP_CNT123] = {
1039 {
1040 NULL((void *)0), 0}, {
1041 atom_op_move, ATOM_ARG_REG0}, {
1042 atom_op_move, ATOM_ARG_PS1}, {
1043 atom_op_move, ATOM_ARG_WS2}, {
1044 atom_op_move, ATOM_ARG_FB3}, {
1045 atom_op_move, ATOM_ARG_PLL6}, {
1046 atom_op_move, ATOM_ARG_MC7}, {
1047 atom_op_and, ATOM_ARG_REG0}, {
1048 atom_op_and, ATOM_ARG_PS1}, {
1049 atom_op_and, ATOM_ARG_WS2}, {
1050 atom_op_and, ATOM_ARG_FB3}, {
1051 atom_op_and, ATOM_ARG_PLL6}, {
1052 atom_op_and, ATOM_ARG_MC7}, {
1053 atom_op_or, ATOM_ARG_REG0}, {
1054 atom_op_or, ATOM_ARG_PS1}, {
1055 atom_op_or, ATOM_ARG_WS2}, {
1056 atom_op_or, ATOM_ARG_FB3}, {
1057 atom_op_or, ATOM_ARG_PLL6}, {
1058 atom_op_or, ATOM_ARG_MC7}, {
1059 atom_op_shift_left, ATOM_ARG_REG0}, {
1060 atom_op_shift_left, ATOM_ARG_PS1}, {
1061 atom_op_shift_left, ATOM_ARG_WS2}, {
1062 atom_op_shift_left, ATOM_ARG_FB3}, {
1063 atom_op_shift_left, ATOM_ARG_PLL6}, {
1064 atom_op_shift_left, ATOM_ARG_MC7}, {
1065 atom_op_shift_right, ATOM_ARG_REG0}, {
1066 atom_op_shift_right, ATOM_ARG_PS1}, {
1067 atom_op_shift_right, ATOM_ARG_WS2}, {
1068 atom_op_shift_right, ATOM_ARG_FB3}, {
1069 atom_op_shift_right, ATOM_ARG_PLL6}, {
1070 atom_op_shift_right, ATOM_ARG_MC7}, {
1071 atom_op_mul, ATOM_ARG_REG0}, {
1072 atom_op_mul, ATOM_ARG_PS1}, {
1073 atom_op_mul, ATOM_ARG_WS2}, {
1074 atom_op_mul, ATOM_ARG_FB3}, {
1075 atom_op_mul, ATOM_ARG_PLL6}, {
1076 atom_op_mul, ATOM_ARG_MC7}, {
1077 atom_op_div, ATOM_ARG_REG0}, {
1078 atom_op_div, ATOM_ARG_PS1}, {
1079 atom_op_div, ATOM_ARG_WS2}, {
1080 atom_op_div, ATOM_ARG_FB3}, {
1081 atom_op_div, ATOM_ARG_PLL6}, {
1082 atom_op_div, ATOM_ARG_MC7}, {
1083 atom_op_add, ATOM_ARG_REG0}, {
1084 atom_op_add, ATOM_ARG_PS1}, {
1085 atom_op_add, ATOM_ARG_WS2}, {
1086 atom_op_add, ATOM_ARG_FB3}, {
1087 atom_op_add, ATOM_ARG_PLL6}, {
1088 atom_op_add, ATOM_ARG_MC7}, {
1089 atom_op_sub, ATOM_ARG_REG0}, {
1090 atom_op_sub, ATOM_ARG_PS1}, {
1091 atom_op_sub, ATOM_ARG_WS2}, {
1092 atom_op_sub, ATOM_ARG_FB3}, {
1093 atom_op_sub, ATOM_ARG_PLL6}, {
1094 atom_op_sub, ATOM_ARG_MC7}, {
1095 atom_op_setport, ATOM_PORT_ATI0}, {
1096 atom_op_setport, ATOM_PORT_PCI1}, {
1097 atom_op_setport, ATOM_PORT_SYSIO2}, {
1098 atom_op_setregblock, 0}, {
1099 atom_op_setfbbase, 0}, {
1100 atom_op_compare, ATOM_ARG_REG0}, {
1101 atom_op_compare, ATOM_ARG_PS1}, {
1102 atom_op_compare, ATOM_ARG_WS2}, {
1103 atom_op_compare, ATOM_ARG_FB3}, {
1104 atom_op_compare, ATOM_ARG_PLL6}, {
1105 atom_op_compare, ATOM_ARG_MC7}, {
1106 atom_op_switch, 0}, {
1107 atom_op_jump, ATOM_COND_ALWAYS2}, {
1108 atom_op_jump, ATOM_COND_EQUAL5}, {
1109 atom_op_jump, ATOM_COND_BELOW3}, {
1110 atom_op_jump, ATOM_COND_ABOVE0}, {
1111 atom_op_jump, ATOM_COND_BELOWOREQUAL4}, {
1112 atom_op_jump, ATOM_COND_ABOVEOREQUAL1}, {
1113 atom_op_jump, ATOM_COND_NOTEQUAL6}, {
1114 atom_op_test, ATOM_ARG_REG0}, {
1115 atom_op_test, ATOM_ARG_PS1}, {
1116 atom_op_test, ATOM_ARG_WS2}, {
1117 atom_op_test, ATOM_ARG_FB3}, {
1118 atom_op_test, ATOM_ARG_PLL6}, {
1119 atom_op_test, ATOM_ARG_MC7}, {
1120 atom_op_delay, ATOM_UNIT_MILLISEC1}, {
1121 atom_op_delay, ATOM_UNIT_MICROSEC0}, {
1122 atom_op_calltable, 0}, {
1123 atom_op_repeat, 0}, {
1124 atom_op_clear, ATOM_ARG_REG0}, {
1125 atom_op_clear, ATOM_ARG_PS1}, {
1126 atom_op_clear, ATOM_ARG_WS2}, {
1127 atom_op_clear, ATOM_ARG_FB3}, {
1128 atom_op_clear, ATOM_ARG_PLL6}, {
1129 atom_op_clear, ATOM_ARG_MC7}, {
1130 atom_op_nop, 0}, {
1131 atom_op_eot, 0}, {
1132 atom_op_mask, ATOM_ARG_REG0}, {
1133 atom_op_mask, ATOM_ARG_PS1}, {
1134 atom_op_mask, ATOM_ARG_WS2}, {
1135 atom_op_mask, ATOM_ARG_FB3}, {
1136 atom_op_mask, ATOM_ARG_PLL6}, {
1137 atom_op_mask, ATOM_ARG_MC7}, {
1138 atom_op_postcard, 0}, {
1139 atom_op_beep, 0}, {
1140 atom_op_savereg, 0}, {
1141 atom_op_restorereg, 0}, {
1142 atom_op_setdatablock, 0}, {
1143 atom_op_xor, ATOM_ARG_REG0}, {
1144 atom_op_xor, ATOM_ARG_PS1}, {
1145 atom_op_xor, ATOM_ARG_WS2}, {
1146 atom_op_xor, ATOM_ARG_FB3}, {
1147 atom_op_xor, ATOM_ARG_PLL6}, {
1148 atom_op_xor, ATOM_ARG_MC7}, {
1149 atom_op_shl, ATOM_ARG_REG0}, {
1150 atom_op_shl, ATOM_ARG_PS1}, {
1151 atom_op_shl, ATOM_ARG_WS2}, {
1152 atom_op_shl, ATOM_ARG_FB3}, {
1153 atom_op_shl, ATOM_ARG_PLL6}, {
1154 atom_op_shl, ATOM_ARG_MC7}, {
1155 atom_op_shr, ATOM_ARG_REG0}, {
1156 atom_op_shr, ATOM_ARG_PS1}, {
1157 atom_op_shr, ATOM_ARG_WS2}, {
1158 atom_op_shr, ATOM_ARG_FB3}, {
1159 atom_op_shr, ATOM_ARG_PLL6}, {
1160 atom_op_shr, ATOM_ARG_MC7}, {
1161atom_op_debug, 0},};
1162
1163static int atom_execute_table_locked(struct atom_context *ctx, int index, uint32_t * params)
1164{
1165 int base = CU16(ctx->cmd_table + 4 + 2 * index)get_u16(ctx->bios, (ctx->cmd_table + 4 + 2 * index));
1166 int len, ws, ps, ptr;
1167 unsigned char op;
1168 atom_exec_context ectx;
1169 int ret = 0;
1170
1171 if (!base)
1172 return -EINVAL22;
1173
1174 len = CU16(base + ATOM_CT_SIZE_PTR)get_u16(ctx->bios, (base + 0));
1175 ws = CU8(base + ATOM_CT_WS_PTR)get_u8(ctx->bios, (base + 4));
1176 ps = CU8(base + ATOM_CT_PS_PTR)get_u8(ctx->bios, (base + 5)) & ATOM_CT_PS_MASK0x7F;
1177 ptr = base + ATOM_CT_CODE_PTR6;
1178
1179 SDEBUG(">> execute %04X (len %d, WS %d, PS %d)\n", base, len, ws, ps)do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk(">> execute %04X (len %d, WS %d, PS %d)\n", base
, len, ws, ps); } while (0)
;
1180
1181 ectx.ctx = ctx;
1182 ectx.ps_shift = ps / 4;
1183 ectx.start = base;
1184 ectx.ps = params;
1185 ectx.abort = false0;
1186 ectx.last_jump = 0;
1187 if (ws)
1188 ectx.ws = kcalloc(4, ws, GFP_KERNEL(0x0001 | 0x0004));
1189 else
1190 ectx.ws = NULL((void *)0);
1191
1192 debug_depth++;
1193 while (1) {
1194 op = CU8(ptr++)get_u8(ctx->bios, (ptr++));
1195 if (op < ATOM_OP_NAMES_CNT123)
1196 SDEBUG("%s @ 0x%04X\n", atom_op_names[op], ptr - 1)do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk("%s @ 0x%04X\n", atom_op_names[op], ptr - 1); } while
(0)
;
1197 else
1198 SDEBUG("[%d] @ 0x%04X\n", op, ptr - 1)do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk("[%d] @ 0x%04X\n", op, ptr - 1); } while (0)
;
1199 if (ectx.abort) {
1200 DRM_ERROR("atombios stuck executing %04X (len %d, WS %d, PS %d) @ 0x%04X\n",__drm_err("atombios stuck executing %04X (len %d, WS %d, PS %d) @ 0x%04X\n"
, base, len, ws, ps, ptr - 1)
1201 base, len, ws, ps, ptr - 1)__drm_err("atombios stuck executing %04X (len %d, WS %d, PS %d) @ 0x%04X\n"
, base, len, ws, ps, ptr - 1)
;
1202 ret = -EINVAL22;
1203 goto free;
1204 }
1205
1206 if (op < ATOM_OP_CNT123 && op > 0)
1207 opcode_table[op].func(&ectx, &ptr,
1208 opcode_table[op].arg);
1209 else
1210 break;
1211
1212 if (op == ATOM_OP_EOT91)
1213 break;
1214 }
1215 debug_depth--;
1216 SDEBUG("<<\n")do if (atom_debug) { printk("\0017"); debug_print_spaces(debug_depth
); printk("<<\n"); } while (0)
;
1217
1218free:
1219 kfree(ectx.ws);
1220 return ret;
1221}
1222
1223int atom_execute_table_scratch_unlocked(struct atom_context *ctx, int index, uint32_t * params)
1224{
1225 int r;
1226
1227 mutex_lock(&ctx->mutex)rw_enter_write(&ctx->mutex);
1228 /* reset data block */
1229 ctx->data_block = 0;
1230 /* reset reg block */
1231 ctx->reg_block = 0;
1232 /* reset fb window */
1233 ctx->fb_base = 0;
1234 /* reset io mode */
1235 ctx->io_mode = ATOM_IO_MM0;
1236 /* reset divmul */
1237 ctx->divmul[0] = 0;
1238 ctx->divmul[1] = 0;
1239 r = atom_execute_table_locked(ctx, index, params);
1240 mutex_unlock(&ctx->mutex)rw_exit_write(&ctx->mutex);
1241 return r;
1242}
1243
1244int atom_execute_table(struct atom_context *ctx, int index, uint32_t * params)
1245{
1246 int r;
1247 mutex_lock(&ctx->scratch_mutex)rw_enter_write(&ctx->scratch_mutex);
1248 r = atom_execute_table_scratch_unlocked(ctx, index, params);
1249 mutex_unlock(&ctx->scratch_mutex)rw_exit_write(&ctx->scratch_mutex);
1250 return r;
1251}
1252
1253static int atom_iio_len[] = { 1, 2, 3, 3, 3, 3, 4, 4, 4, 3 };
1254
1255static void atom_index_iio(struct atom_context *ctx, int base)
1256{
1257 ctx->iio = kzalloc(2 * 256, GFP_KERNEL(0x0001 | 0x0004));
1258 if (!ctx->iio)
1259 return;
1260 while (CU8(base)get_u8(ctx->bios, (base)) == ATOM_IIO_START1) {
1261 ctx->iio[CU8(base + 1)get_u8(ctx->bios, (base + 1))] = base + 2;
1262 base += 2;
1263 while (CU8(base)get_u8(ctx->bios, (base)) != ATOM_IIO_END9)
1264 base += atom_iio_len[CU8(base)get_u8(ctx->bios, (base))];
1265 base += 3;
1266 }
1267}
1268
1269struct atom_context *atom_parse(struct card_info *card, void *bios)
1270{
1271 int base;
1272 struct atom_context *ctx =
1273 kzalloc(sizeof(struct atom_context), GFP_KERNEL(0x0001 | 0x0004));
1274 char *str;
1275 char name[512];
1276 int i;
1277
1278 if (!ctx)
1279 return NULL((void *)0);
1280
1281 ctx->card = card;
1282 ctx->bios = bios;
1283
1284 if (CU16(0)get_u16(ctx->bios, (0)) != ATOM_BIOS_MAGIC0xAA55) {
1285 pr_info("Invalid BIOS magic\n")do { } while(0);
1286 kfree(ctx);
1287 return NULL((void *)0);
1288 }
1289 if (strncmp
1290 (CSTR(ATOM_ATI_MAGIC_PTR)(((char *)(ctx->bios))+(0x30)), ATOM_ATI_MAGIC" 761295520",
1291 strlen(ATOM_ATI_MAGIC" 761295520"))) {
1292 pr_info("Invalid ATI magic\n")do { } while(0);
1293 kfree(ctx);
1294 return NULL((void *)0);
1295 }
1296
1297 base = CU16(ATOM_ROM_TABLE_PTR)get_u16(ctx->bios, (0x48));
1298 if (strncmp
1299 (CSTR(base + ATOM_ROM_MAGIC_PTR)(((char *)(ctx->bios))+(base + 4)), ATOM_ROM_MAGIC"ATOM",
1300 strlen(ATOM_ROM_MAGIC"ATOM"))) {
1301 pr_info("Invalid ATOM magic\n")do { } while(0);
1302 kfree(ctx);
1303 return NULL((void *)0);
1304 }
1305
1306 ctx->cmd_table = CU16(base + ATOM_ROM_CMD_PTR)get_u16(ctx->bios, (base + 0x1E));
1307 ctx->data_table = CU16(base + ATOM_ROM_DATA_PTR)get_u16(ctx->bios, (base + 0x20));
1308 atom_index_iio(ctx, CU16(ctx->data_table + ATOM_DATA_IIO_PTR)get_u16(ctx->bios, (ctx->data_table + 0x32)) + 4);
1309 if (!ctx->iio) {
1310 atom_destroy(ctx);
1311 return NULL((void *)0);
1312 }
1313
1314 str = CSTR(CU16(base + ATOM_ROM_MSG_PTR))(((char *)(ctx->bios))+(get_u16(ctx->bios, (base + 0x10
))))
;
1315 while (*str && ((*str == '\n') || (*str == '\r')))
1316 str++;
1317 /* name string isn't always 0 terminated */
1318 for (i = 0; i < 511; i++) {
1319 name[i] = str[i];
1320 if (name[i] < '.' || name[i] > 'z') {
1321 name[i] = 0;
1322 break;
1323 }
1324 }
1325 pr_info("ATOM BIOS: %s\n", name)do { } while(0);
1326
1327 return ctx;
1328}
1329
1330int atom_asic_init(struct atom_context *ctx)
1331{
1332 struct radeon_device *rdev = ctx->card->dev->dev_private;
1333 int hwi = CU16(ctx->data_table + ATOM_DATA_FWI_PTR)get_u16(ctx->bios, (ctx->data_table + 0xC));
1334 uint32_t ps[16];
1335 int ret;
1336
1337 memset(ps, 0, 64)__builtin_memset((ps), (0), (64));
1338
1339 ps[0] = cpu_to_le32(CU32(hwi + ATOM_FWI_DEFSCLK_PTR))((__uint32_t)(get_u32(ctx->bios, (hwi + 8))));
1340 ps[1] = cpu_to_le32(CU32(hwi + ATOM_FWI_DEFMCLK_PTR))((__uint32_t)(get_u32(ctx->bios, (hwi + 0xC))));
1341 if (!ps[0] || !ps[1])
1342 return 1;
1343
1344 if (!CU16(ctx->cmd_table + 4 + 2 * ATOM_CMD_INIT)get_u16(ctx->bios, (ctx->cmd_table + 4 + 2 * 0)))
1345 return 1;
1346 ret = atom_execute_table(ctx, ATOM_CMD_INIT0, ps);
1347 if (ret)
1348 return ret;
1349
1350 memset(ps, 0, 64)__builtin_memset((ps), (0), (64));
1351
1352 if (rdev->family < CHIP_R600) {
1353 if (CU16(ctx->cmd_table + 4 + 2 * ATOM_CMD_SPDFANCNTL)get_u16(ctx->bios, (ctx->cmd_table + 4 + 2 * 0x39)))
1354 atom_execute_table(ctx, ATOM_CMD_SPDFANCNTL0x39, ps);
1355 }
1356 return ret;
1357}
1358
1359void atom_destroy(struct atom_context *ctx)
1360{
1361 kfree(ctx->iio);
1362 kfree(ctx);
1363}
1364
1365bool_Bool atom_parse_data_header(struct atom_context *ctx, int index,
1366 uint16_t * size, uint8_t * frev, uint8_t * crev,
1367 uint16_t * data_start)
1368{
1369 int offset = index * 2 + 4;
1370 int idx = CU16(ctx->data_table + offset)get_u16(ctx->bios, (ctx->data_table + offset));
1371 u16 *mdt = (u16 *)(ctx->bios + ctx->data_table + 4);
1372
1373 if (!mdt[index])
1374 return false0;
1375
1376 if (size)
1377 *size = CU16(idx)get_u16(ctx->bios, (idx));
1378 if (frev)
1379 *frev = CU8(idx + 2)get_u8(ctx->bios, (idx + 2));
1380 if (crev)
1381 *crev = CU8(idx + 3)get_u8(ctx->bios, (idx + 3));
1382 *data_start = idx;
1383 return true1;
1384}
1385
1386bool_Bool atom_parse_cmd_header(struct atom_context *ctx, int index, uint8_t * frev,
1387 uint8_t * crev)
1388{
1389 int offset = index * 2 + 4;
1390 int idx = CU16(ctx->cmd_table + offset)get_u16(ctx->bios, (ctx->cmd_table + offset));
1391 u16 *mct = (u16 *)(ctx->bios + ctx->cmd_table + 4);
1392
1393 if (!mct[index])
1394 return false0;
1395
1396 if (frev)
1397 *frev = CU8(idx + 2)get_u8(ctx->bios, (idx + 2));
1398 if (crev)
1399 *crev = CU8(idx + 3)get_u8(ctx->bios, (idx + 3));
1400 return true1;
1401}
1402
1403int atom_allocate_fb_scratch(struct atom_context *ctx)
1404{
1405 int index = GetIndexIntoMasterTable(DATA, VRAM_UsageByFirmware)(__builtin_offsetof(ATOM_MASTER_LIST_OF_DATA_TABLES, VRAM_UsageByFirmware
)/sizeof(USHORT))
;
1406 uint16_t data_offset;
1407 int usage_bytes = 0;
1408 struct _ATOM_VRAM_USAGE_BY_FIRMWARE *firmware_usage;
1409
1410 if (atom_parse_data_header(ctx, index, NULL((void *)0), NULL((void *)0), NULL((void *)0), &data_offset)) {
1411 firmware_usage = (struct _ATOM_VRAM_USAGE_BY_FIRMWARE *)(ctx->bios + data_offset);
1412
1413 DRM_DEBUG("atom firmware requested %08x %dkb\n",___drm_dbg(((void *)0), DRM_UT_CORE, "atom firmware requested %08x %dkb\n"
, ((__uint32_t)(firmware_usage->asFirmwareVramReserveInfo[
0].ulStartAddrUsedByFirmware)), ((__uint16_t)(firmware_usage->
asFirmwareVramReserveInfo[0].usFirmwareUseInKb)))
1414 le32_to_cpu(firmware_usage->asFirmwareVramReserveInfo[0].ulStartAddrUsedByFirmware),___drm_dbg(((void *)0), DRM_UT_CORE, "atom firmware requested %08x %dkb\n"
, ((__uint32_t)(firmware_usage->asFirmwareVramReserveInfo[
0].ulStartAddrUsedByFirmware)), ((__uint16_t)(firmware_usage->
asFirmwareVramReserveInfo[0].usFirmwareUseInKb)))
1415 le16_to_cpu(firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb))___drm_dbg(((void *)0), DRM_UT_CORE, "atom firmware requested %08x %dkb\n"
, ((__uint32_t)(firmware_usage->asFirmwareVramReserveInfo[
0].ulStartAddrUsedByFirmware)), ((__uint16_t)(firmware_usage->
asFirmwareVramReserveInfo[0].usFirmwareUseInKb)))
;
1416
1417 usage_bytes = le16_to_cpu(firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb)((__uint16_t)(firmware_usage->asFirmwareVramReserveInfo[0]
.usFirmwareUseInKb))
* 1024;
1418 }
1419 ctx->scratch_size_bytes = 0;
1420 if (usage_bytes == 0)
1421 usage_bytes = 20 * 1024;
1422 /* allocate some scratch memory */
1423 ctx->scratch = kzalloc(usage_bytes, GFP_KERNEL(0x0001 | 0x0004));
1424 if (!ctx->scratch)
1425 return -ENOMEM12;
1426 ctx->scratch_size_bytes = usage_bytes;
1427 return 0;
1428}