vga: bugfixes for ati and sm501, vgabios cleanup.

-----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2.0.22 (GNU/Linux)
 
 iQIcBAABCgAGBQJe/KXUAAoJEEy22O7T6HE4ndwP/3fpLGI2hwHfV/JF1b5LZqkb
 +Ub4Ys5OaFER5BSnPgDrow+L0ssh2jFbyRl44vglTxNLAbURtdh3Uh1sJyc5Dsqa
 geiaQ/cgSNQ5Eme1jkHQvNhHZk8/SNLgeSG30DZk4tBCbfhDSlQbjJwLFrvworeY
 tSw0rXyxu/tTCeA0lIdrDtdssBI6i5hE1zpHZOTYQkect3eWQ8Xz2OQ/zrWHJg9T
 PEjPCMXZvShmu19p7/UQjg4RptlBcIbQJnrVP2l74uQQoU04s8hcqylt47EDUrAk
 CYVdK/7sKzBeL75NVJLlWAqWPHxbtarwSTxaH0cqiZ8Kpm/uyMwF3zM9btFpOV2W
 Z7BftHYGYWtnKLMQMETDH/XAus1g7GMPsQHchuEg11L7++tzc2mYFvvLU5/yJ2Nn
 OIseDmkK/1KHTG36tADvoNRbW79cIpJ3zIvQEMIOprXJdPaSdU2EPuMaxgjtRsXl
 zSPahL+9JvMXTHCXWo0DNRhzT6v5AowmeiLoI9p+g4FSrYk2ECTMkHvwJ3Lpg0+1
 LN3meKWsXZxTo8OyfQqSFvNQYyOIxYncfwArXsG+Cdk5HoqpRVvZRo1TuCVC3wh7
 Pk68LW6sYxBDhLetBlMQFUD06IwV7nl0+CIB4tKIlIXBU2SSnJfLN+3asZk6lRCY
 1CPoLhkv9sVBWK6B2R0b
 =is9s
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/kraxel/tags/vga-20200701-pull-request' into staging

vga: bugfixes for ati and sm501, vgabios cleanup.

# gpg: Signature made Wed 01 Jul 2020 16:03:48 BST
# gpg:                using RSA key 4CB6D8EED3E87138
# gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>" [full]
# gpg:                 aka "Gerd Hoffmann <gerd@kraxel.org>" [full]
# gpg:                 aka "Gerd Hoffmann (private) <kraxel@gmail.com>" [full]
# Primary key fingerprint: A032 8CFF B93A 17A7 9901  FE7D 4CB6 D8EE D3E8 7138

* remotes/kraxel/tags/vga-20200701-pull-request:
  configure: vgabios cleanups
  ati-vga: Add dummy MEM_SDRAM_MODE_REG
  ati-vga: Do not assert on error
  ati-vga: Support unaligned access to hardware cursor registers
  sm501: Fix and optimize overlap check
  sm501: Convert debug printfs to traces
  sm501: Do not allow guest to set invalid format
  sm501: Use stn_he_p/ldn_he_p instead of switch/case
  sm501: Optimise 1 pixel 2d ops
  sm501: Introduce variable for commonly used value for better readability
  sm501: Ignore no-op blits
  sm501: Drop unneded variable
  sm501: Fix bounds checks

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2020-07-02 12:27:01 +01:00
commit d0c8b957ae
6 changed files with 155 additions and 114 deletions

6
configure vendored
View File

@ -8486,14 +8486,14 @@ DIRS="tests tests/tcg tests/tcg/lm32 tests/qapi-schema tests/qtest/libqos"
DIRS="$DIRS tests/qtest tests/qemu-iotests tests/vm tests/fp tests/qgraph"
DIRS="$DIRS docs docs/interop fsdev scsi"
DIRS="$DIRS pc-bios/optionrom pc-bios/s390-ccw"
DIRS="$DIRS roms/seabios roms/vgabios"
DIRS="$DIRS roms/seabios"
LINKS="Makefile"
LINKS="$LINKS tests/tcg/lm32/Makefile po/Makefile"
LINKS="$LINKS tests/tcg/Makefile.target tests/fp/Makefile"
LINKS="$LINKS tests/plugin/Makefile"
LINKS="$LINKS pc-bios/optionrom/Makefile pc-bios/keymaps"
LINKS="$LINKS pc-bios/s390-ccw/Makefile"
LINKS="$LINKS roms/seabios/Makefile roms/vgabios/Makefile"
LINKS="$LINKS roms/seabios/Makefile"
LINKS="$LINKS pc-bios/qemu-icon.bmp"
LINKS="$LINKS .gdbinit scripts" # scripts needed by relative path in .gdbinit
LINKS="$LINKS tests/acceptance tests/data"
@ -8526,7 +8526,7 @@ export target_list source_path use_containers
$source_path/tests/tcg/configure.sh)
# temporary config to build submodules
for rom in seabios vgabios ; do
for rom in seabios; do
config_mak=roms/$rom/config.mak
echo "# Automatically generated by configure - do not modify" > $config_mak
echo "SRC_PATH=$source_path/roms/$rom" >> $config_mak

View File

@ -86,8 +86,8 @@ static void ati_vga_switch_mode(ATIVGAState *s)
break;
default:
qemu_log_mask(LOG_UNIMP, "Unsupported bpp value\n");
return;
}
assert(bpp != 0);
DPRINTF("Switching to %dx%d %d %d @ %x\n", h, v, stride, bpp, offs);
vbe_ioport_write_index(&s->vga, 0, VBE_DISPI_INDEX_ENABLE);
vbe_ioport_write_data(&s->vga, 0, VBE_DISPI_DISABLED);
@ -361,6 +361,11 @@ static uint64_t ati_mm_read(void *opaque, hwaddr addr, unsigned int size)
case MC_STATUS:
val = 5;
break;
case MEM_SDRAM_MODE_REG:
if (s->dev_id != PCI_DEVICE_ID_ATI_RAGE128_PF) {
val = BIT(28) | BIT(20);
}
break;
case RBBM_STATUS:
case GUI_STAT:
val = 64; /* free CMDFIFO entries */
@ -389,22 +394,28 @@ static uint64_t ati_mm_read(void *opaque, hwaddr addr, unsigned int size)
case 0xf00 ... 0xfff:
val = pci_default_read_config(&s->dev, addr - 0xf00, size);
break;
case CUR_OFFSET:
val = s->regs.cur_offset;
case CUR_OFFSET ... CUR_OFFSET + 3:
val = ati_reg_read_offs(s->regs.cur_offset, addr - CUR_OFFSET, size);
break;
case CUR_HORZ_VERT_POSN:
val = s->regs.cur_hv_pos;
val |= s->regs.cur_offset & BIT(31);
case CUR_HORZ_VERT_POSN ... CUR_HORZ_VERT_POSN + 3:
val = ati_reg_read_offs(s->regs.cur_hv_pos,
addr - CUR_HORZ_VERT_POSN, size);
if (addr + size > CUR_HORZ_VERT_POSN + 3) {
val |= (s->regs.cur_offset & BIT(31)) >> (4 - size);
}
break;
case CUR_HORZ_VERT_OFF:
val = s->regs.cur_hv_offs;
val |= s->regs.cur_offset & BIT(31);
case CUR_HORZ_VERT_OFF ... CUR_HORZ_VERT_OFF + 3:
val = ati_reg_read_offs(s->regs.cur_hv_offs,
addr - CUR_HORZ_VERT_OFF, size);
if (addr + size > CUR_HORZ_VERT_OFF + 3) {
val |= (s->regs.cur_offset & BIT(31)) >> (4 - size);
}
break;
case CUR_CLR0:
val = s->regs.cur_color0;
case CUR_CLR0 ... CUR_CLR0 + 3:
val = ati_reg_read_offs(s->regs.cur_color0, addr - CUR_CLR0, size);
break;
case CUR_CLR1:
val = s->regs.cur_color1;
case CUR_CLR1 ... CUR_CLR1 + 3:
val = ati_reg_read_offs(s->regs.cur_color1, addr - CUR_CLR1, size);
break;
case DST_OFFSET:
val = s->regs.dst_offset;
@ -679,48 +690,71 @@ static void ati_mm_write(void *opaque, hwaddr addr,
case 0xf00 ... 0xfff:
/* read-only copy of PCI config space so ignore writes */
break;
case CUR_OFFSET:
if (s->regs.cur_offset != (data & 0x87fffff0)) {
s->regs.cur_offset = data & 0x87fffff0;
case CUR_OFFSET ... CUR_OFFSET + 3:
{
uint32_t t = s->regs.cur_offset;
ati_reg_write_offs(&t, addr - CUR_OFFSET, data, size);
t &= 0x87fffff0;
if (s->regs.cur_offset != t) {
s->regs.cur_offset = t;
ati_cursor_define(s);
}
break;
case CUR_HORZ_VERT_POSN:
s->regs.cur_hv_pos = data & 0x3fff0fff;
if (data & BIT(31)) {
s->regs.cur_offset |= data & BIT(31);
}
case CUR_HORZ_VERT_POSN ... CUR_HORZ_VERT_POSN + 3:
{
uint32_t t = s->regs.cur_hv_pos | (s->regs.cur_offset & BIT(31));
ati_reg_write_offs(&t, addr - CUR_HORZ_VERT_POSN, data, size);
s->regs.cur_hv_pos = t & 0x3fff0fff;
if (t & BIT(31)) {
s->regs.cur_offset |= t & BIT(31);
} else if (s->regs.cur_offset & BIT(31)) {
s->regs.cur_offset &= ~BIT(31);
ati_cursor_define(s);
}
if (!s->cursor_guest_mode &&
(s->regs.crtc_gen_cntl & CRTC2_CUR_EN) && !(data & BIT(31))) {
(s->regs.crtc_gen_cntl & CRTC2_CUR_EN) && !(t & BIT(31))) {
dpy_mouse_set(s->vga.con, s->regs.cur_hv_pos >> 16,
s->regs.cur_hv_pos & 0xffff, 1);
}
break;
}
case CUR_HORZ_VERT_OFF:
s->regs.cur_hv_offs = data & 0x3f003f;
if (data & BIT(31)) {
s->regs.cur_offset |= data & BIT(31);
{
uint32_t t = s->regs.cur_hv_offs | (s->regs.cur_offset & BIT(31));
ati_reg_write_offs(&t, addr - CUR_HORZ_VERT_OFF, data, size);
s->regs.cur_hv_offs = t & 0x3f003f;
if (t & BIT(31)) {
s->regs.cur_offset |= t & BIT(31);
} else if (s->regs.cur_offset & BIT(31)) {
s->regs.cur_offset &= ~BIT(31);
ati_cursor_define(s);
}
break;
case CUR_CLR0:
if (s->regs.cur_color0 != (data & 0xffffff)) {
s->regs.cur_color0 = data & 0xffffff;
}
case CUR_CLR0 ... CUR_CLR0 + 3:
{
uint32_t t = s->regs.cur_color0;
ati_reg_write_offs(&t, addr - CUR_CLR0, data, size);
t &= 0xffffff;
if (s->regs.cur_color0 != t) {
s->regs.cur_color0 = t;
ati_cursor_define(s);
}
break;
case CUR_CLR1:
}
case CUR_CLR1 ... CUR_CLR1 + 3:
/*
* Update cursor unconditionally here because some clients set up
* other registers before actually writing cursor data to memory at
* offset so we would miss cursor change unless always updating here
*/
s->regs.cur_color1 = data & 0xffffff;
ati_reg_write_offs(&s->regs.cur_color1, addr - CUR_CLR1, data, size);
s->regs.cur_color1 &= 0xffffff;
ati_cursor_define(s);
break;
case DST_OFFSET:

View File

@ -42,6 +42,7 @@ static struct ati_regdesc ati_reg_names[] = {
{"MC_FB_LOCATION", 0x0148},
{"MC_AGP_LOCATION", 0x014C},
{"MC_STATUS", 0x0150},
{"MEM_SDRAM_MODE_REG", 0x0158},
{"MEM_POWER_MISC", 0x015c},
{"AGP_BASE", 0x0170},
{"AGP_CNTL", 0x0174},

View File

@ -60,6 +60,7 @@
#define MC_FB_LOCATION 0x0148
#define MC_AGP_LOCATION 0x014C
#define MC_STATUS 0x0150
#define MEM_SDRAM_MODE_REG 0x0158
#define MEM_POWER_MISC 0x015c
#define AGP_BASE 0x0170
#define AGP_CNTL 0x0174

View File

@ -39,15 +39,7 @@
#include "qemu/range.h"
#include "ui/pixel_ops.h"
#include "qemu/bswap.h"
/*#define DEBUG_SM501*/
/*#define DEBUG_BITBLT*/
#ifdef DEBUG_SM501
#define SM501_DPRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__)
#else
#define SM501_DPRINTF(fmt, ...) do {} while (0)
#endif
#include "trace.h"
#define MMIO_BASE_OFFSET 0x3e00000
#define MMIO_SIZE 0x200000
@ -684,10 +676,11 @@ static void sm501_2d_operation(SM501State *s)
{
int cmd = (s->twoD_control >> 16) & 0x1F;
int rtl = s->twoD_control & BIT(27);
int format = (s->twoD_stretch >> 20) & 0x3;
int rop_mode = (s->twoD_control >> 15) & 0x1; /* 1 for rop2, else rop3 */
int format = (s->twoD_stretch >> 20) & 3;
int bypp = 1 << format; /* bytes per pixel */
int rop_mode = (s->twoD_control >> 15) & 1; /* 1 for rop2, else rop3 */
/* 1 if rop2 source is the pattern, otherwise the source is the bitmap */
int rop2_source_is_pattern = (s->twoD_control >> 14) & 0x1;
int rop2_source_is_pattern = (s->twoD_control >> 14) & 1;
int rop = s->twoD_control & 0xFF;
unsigned int dst_x = (s->twoD_destination >> 16) & 0x01FFF;
unsigned int dst_y = s->twoD_destination & 0xFFFF;
@ -697,6 +690,7 @@ static void sm501_2d_operation(SM501State *s)
unsigned int dst_pitch = (s->twoD_pitch >> 16) & 0x1FFF;
int crt = (s->dc_crt_control & SM501_DC_CRT_CONTROL_SEL) ? 1 : 0;
int fb_len = get_width(s, crt) * get_height(s, crt) * get_bpp(s, crt);
bool overlap = false;
if ((s->twoD_stretch >> 16) & 0xF) {
qemu_log_mask(LOG_UNIMP, "sm501: only XY addressing is supported.\n");
@ -723,9 +717,9 @@ static void sm501_2d_operation(SM501State *s)
dst_y -= height - 1;
}
if (dst_base >= get_local_mem_size(s) || dst_base +
(dst_x + width + (dst_y + height) * (dst_pitch + width)) *
(1 << format) >= get_local_mem_size(s)) {
if (dst_base >= get_local_mem_size(s) ||
dst_base + (dst_x + width + (dst_y + height) * dst_pitch) * bypp >=
get_local_mem_size(s)) {
qemu_log_mask(LOG_GUEST_ERROR, "sm501: 2D op dest is outside vram.\n");
return;
}
@ -749,9 +743,9 @@ static void sm501_2d_operation(SM501State *s)
src_y -= height - 1;
}
if (src_base >= get_local_mem_size(s) || src_base +
(src_x + width + (src_y + height) * (src_pitch + width)) *
(1 << format) >= get_local_mem_size(s)) {
if (src_base >= get_local_mem_size(s) ||
src_base + (src_x + width + (src_y + height) * src_pitch) * bypp >=
get_local_mem_size(s)) {
qemu_log_mask(LOG_GUEST_ERROR,
"sm501: 2D op src is outside vram.\n");
return;
@ -763,19 +757,9 @@ static void sm501_2d_operation(SM501State *s)
uint8_t *d = s->local_mem + dst_base;
for (y = 0; y < height; y++) {
i = (dst_x + (dst_y + y) * dst_pitch) * (1 << format);
for (x = 0; x < width; x++, i += (1 << format)) {
switch (format) {
case 0:
d[i] = ~d[i];
break;
case 1:
*(uint16_t *)&d[i] = ~*(uint16_t *)&d[i];
break;
case 2:
*(uint32_t *)&d[i] = ~*(uint32_t *)&d[i];
break;
}
i = (dst_x + (dst_y + y) * dst_pitch) * bypp;
for (x = 0; x < width; x++, i += bypp) {
stn_he_p(&d[i], bypp, ~ldn_he_p(&d[i], bypp));
}
}
} else {
@ -788,40 +772,57 @@ static void sm501_2d_operation(SM501State *s)
(rop2_source_is_pattern ?
" with pattern source" : ""));
}
/* Check for overlaps, this could be made more exact */
uint32_t sb, se, db, de;
sb = src_base + src_x + src_y * (width + src_pitch);
se = sb + width + height * (width + src_pitch);
db = dst_base + dst_x + dst_y * (width + dst_pitch);
de = db + width + height * (width + dst_pitch);
if (rtl && ((db >= sb && db <= se) || (de >= sb && de <= se))) {
/* regions may overlap: copy via temporary */
int free_buf = 0, llb = width * (1 << format);
int tmp_stride = DIV_ROUND_UP(llb, sizeof(uint32_t));
/* Ignore no-op blits, some guests seem to do this */
if (src_base == dst_base && src_pitch == dst_pitch &&
src_x == dst_x && src_y == dst_y) {
break;
}
/* Some clients also do 1 pixel blits, avoid overhead for these */
if (width == 1 && height == 1) {
unsigned int si = (src_x + src_y * src_pitch) * bypp;
unsigned int di = (dst_x + dst_y * dst_pitch) * bypp;
stn_he_p(&s->local_mem[dst_base + di], bypp,
ldn_he_p(&s->local_mem[src_base + si], bypp));
break;
}
/* If reverse blit do simple check for overlaps */
if (rtl && src_base == dst_base && src_pitch == dst_pitch) {
overlap = (src_x < dst_x + width && src_x + width > dst_x &&
src_y < dst_y + height && src_y + height > dst_y);
} else if (rtl) {
unsigned int sb, se, db, de;
sb = src_base + (src_x + src_y * src_pitch) * bypp;
se = sb + (width + (height - 1) * src_pitch) * bypp;
db = dst_base + (dst_x + dst_y * dst_pitch) * bypp;
de = db + (width + (height - 1) * dst_pitch) * bypp;
overlap = (db < se && sb < de);
}
if (overlap) {
/* pixman can't do reverse blit: copy via temporary */
int tmp_stride = DIV_ROUND_UP(width * bypp, sizeof(uint32_t));
uint32_t *tmp = tmp_buf;
if (tmp_stride * sizeof(uint32_t) * height > sizeof(tmp_buf)) {
tmp = g_malloc(tmp_stride * sizeof(uint32_t) * height);
free_buf = 1;
}
pixman_blt((uint32_t *)&s->local_mem[src_base], tmp,
src_pitch * (1 << format) / sizeof(uint32_t),
tmp_stride, 8 * (1 << format), 8 * (1 << format),
src_pitch * bypp / sizeof(uint32_t),
tmp_stride, 8 * bypp, 8 * bypp,
src_x, src_y, 0, 0, width, height);
pixman_blt(tmp, (uint32_t *)&s->local_mem[dst_base],
tmp_stride,
dst_pitch * (1 << format) / sizeof(uint32_t),
8 * (1 << format), 8 * (1 << format),
dst_pitch * bypp / sizeof(uint32_t),
8 * bypp, 8 * bypp,
0, 0, dst_x, dst_y, width, height);
if (free_buf) {
if (tmp != tmp_buf) {
g_free(tmp);
}
} else {
pixman_blt((uint32_t *)&s->local_mem[src_base],
(uint32_t *)&s->local_mem[dst_base],
src_pitch * (1 << format) / sizeof(uint32_t),
dst_pitch * (1 << format) / sizeof(uint32_t),
8 * (1 << format), 8 * (1 << format),
src_pitch * bypp / sizeof(uint32_t),
dst_pitch * bypp / sizeof(uint32_t),
8 * bypp, 8 * bypp,
src_x, src_y, dst_x, dst_y, width, height);
}
}
@ -837,9 +838,14 @@ static void sm501_2d_operation(SM501State *s)
color = cpu_to_le16(color);
}
pixman_fill((uint32_t *)&s->local_mem[dst_base],
dst_pitch * (1 << format) / sizeof(uint32_t),
8 * (1 << format), dst_x, dst_y, width, height, color);
if (width == 1 && height == 1) {
unsigned int i = (dst_x + dst_y * dst_pitch) * bypp;
stn_he_p(&s->local_mem[dst_base + i], bypp, color);
} else {
pixman_fill((uint32_t *)&s->local_mem[dst_base],
dst_pitch * bypp / sizeof(uint32_t),
8 * bypp, dst_x, dst_y, width, height, color);
}
break;
}
default:
@ -851,7 +857,7 @@ static void sm501_2d_operation(SM501State *s)
if (dst_base >= get_fb_addr(s, crt) &&
dst_base <= get_fb_addr(s, crt) + fb_len) {
int dst_len = MIN(fb_len, ((dst_y + height - 1) * dst_pitch +
dst_x + width) * (1 << format));
dst_x + width) * bypp);
if (dst_len) {
memory_region_set_dirty(&s->local_mem_region, dst_base, dst_len);
}
@ -863,7 +869,6 @@ static uint64_t sm501_system_config_read(void *opaque, hwaddr addr,
{
SM501State *s = (SM501State *)opaque;
uint32_t ret = 0;
SM501_DPRINTF("sm501 system config regs : read addr=%x\n", (int)addr);
switch (addr) {
case SM501_SYSTEM_CONTROL:
@ -915,7 +920,7 @@ static uint64_t sm501_system_config_read(void *opaque, hwaddr addr,
qemu_log_mask(LOG_UNIMP, "sm501: not implemented system config"
"register read. addr=%" HWADDR_PRIx "\n", addr);
}
trace_sm501_system_config_read(addr, ret);
return ret;
}
@ -923,9 +928,8 @@ static void sm501_system_config_write(void *opaque, hwaddr addr,
uint64_t value, unsigned size)
{
SM501State *s = (SM501State *)opaque;
SM501_DPRINTF("sm501 system config regs : write addr=%x, val=%x\n",
(uint32_t)addr, (uint32_t)value);
trace_sm501_system_config_write((uint32_t)addr, (uint32_t)value);
switch (addr) {
case SM501_SYSTEM_CONTROL:
s->system_control &= 0x10DB0000;
@ -1011,9 +1015,7 @@ static uint64_t sm501_i2c_read(void *opaque, hwaddr addr, unsigned size)
qemu_log_mask(LOG_UNIMP, "sm501 i2c : not implemented register read."
" addr=0x%" HWADDR_PRIx "\n", addr);
}
SM501_DPRINTF("sm501 i2c regs : read addr=%" HWADDR_PRIx " val=%x\n",
addr, ret);
trace_sm501_i2c_read((uint32_t)addr, ret);
return ret;
}
@ -1021,9 +1023,8 @@ static void sm501_i2c_write(void *opaque, hwaddr addr, uint64_t value,
unsigned size)
{
SM501State *s = (SM501State *)opaque;
SM501_DPRINTF("sm501 i2c regs : write addr=%" HWADDR_PRIx
" val=%" PRIx64 "\n", addr, value);
trace_sm501_i2c_write((uint32_t)addr, (uint32_t)value);
switch (addr) {
case SM501_I2C_BYTE_COUNT:
s->i2c_byte_count = value & 0xf;
@ -1037,25 +1038,19 @@ static void sm501_i2c_write(void *opaque, hwaddr addr, uint64_t value,
s->i2c_status |= (res ? SM501_I2C_STATUS_ERROR : 0);
if (!res) {
int i;
SM501_DPRINTF("sm501 i2c : transferring %d bytes to 0x%x\n",
s->i2c_byte_count + 1, s->i2c_addr >> 1);
for (i = 0; i <= s->i2c_byte_count; i++) {
res = i2c_send_recv(s->i2c_bus, &s->i2c_data[i],
!(s->i2c_addr & 1));
if (res) {
SM501_DPRINTF("sm501 i2c : transfer failed"
" i=%d, res=%d\n", i, res);
s->i2c_status |= SM501_I2C_STATUS_ERROR;
return;
}
}
if (i) {
SM501_DPRINTF("sm501 i2c : transferred %d bytes\n", i);
s->i2c_status = SM501_I2C_STATUS_COMPLETE;
}
}
} else {
SM501_DPRINTF("sm501 i2c : end transfer\n");
i2c_end_transfer(s->i2c_bus);
s->i2c_status &= ~SM501_I2C_STATUS_ERROR;
}
@ -1095,7 +1090,8 @@ static const MemoryRegionOps sm501_i2c_ops = {
static uint32_t sm501_palette_read(void *opaque, hwaddr addr)
{
SM501State *s = (SM501State *)opaque;
SM501_DPRINTF("sm501 palette read addr=%x\n", (int)addr);
trace_sm501_palette_read((uint32_t)addr);
/* TODO : consider BYTE/WORD access */
/* TODO : consider endian */
@ -1108,8 +1104,8 @@ static void sm501_palette_write(void *opaque, hwaddr addr,
uint32_t value)
{
SM501State *s = (SM501State *)opaque;
SM501_DPRINTF("sm501 palette write addr=%x, val=%x\n",
(int)addr, value);
trace_sm501_palette_write((uint32_t)addr, value);
/* TODO : consider BYTE/WORD access */
/* TODO : consider endian */
@ -1124,7 +1120,6 @@ static uint64_t sm501_disp_ctrl_read(void *opaque, hwaddr addr,
{
SM501State *s = (SM501State *)opaque;
uint32_t ret = 0;
SM501_DPRINTF("sm501 disp ctrl regs : read addr=%x\n", (int)addr);
switch (addr) {
@ -1229,7 +1224,7 @@ static uint64_t sm501_disp_ctrl_read(void *opaque, hwaddr addr,
qemu_log_mask(LOG_UNIMP, "sm501: not implemented disp ctrl register "
"read. addr=%" HWADDR_PRIx "\n", addr);
}
trace_sm501_disp_ctrl_read((uint32_t)addr, ret);
return ret;
}
@ -1237,9 +1232,8 @@ static void sm501_disp_ctrl_write(void *opaque, hwaddr addr,
uint64_t value, unsigned size)
{
SM501State *s = (SM501State *)opaque;
SM501_DPRINTF("sm501 disp ctrl regs : write addr=%x, val=%x\n",
(unsigned)addr, (unsigned)value);
trace_sm501_disp_ctrl_write((uint32_t)addr, (uint32_t)value);
switch (addr) {
case SM501_DC_PANEL_CONTROL:
s->dc_panel_control = value & 0x0FFF73FF;
@ -1384,7 +1378,6 @@ static uint64_t sm501_2d_engine_read(void *opaque, hwaddr addr,
{
SM501State *s = (SM501State *)opaque;
uint32_t ret = 0;
SM501_DPRINTF("sm501 2d engine regs : read addr=%x\n", (int)addr);
switch (addr) {
case SM501_2D_SOURCE:
@ -1454,7 +1447,7 @@ static uint64_t sm501_2d_engine_read(void *opaque, hwaddr addr,
qemu_log_mask(LOG_UNIMP, "sm501: not implemented disp ctrl register "
"read. addr=%" HWADDR_PRIx "\n", addr);
}
trace_sm501_2d_engine_read((uint32_t)addr, ret);
return ret;
}
@ -1462,9 +1455,8 @@ static void sm501_2d_engine_write(void *opaque, hwaddr addr,
uint64_t value, unsigned size)
{
SM501State *s = (SM501State *)opaque;
SM501_DPRINTF("sm501 2d engine regs : write addr=%x, val=%x\n",
(unsigned)addr, (unsigned)value);
trace_sm501_2d_engine_write((uint32_t)addr, (uint32_t)value);
switch (addr) {
case SM501_2D_SOURCE:
s->twoD_source = value;
@ -1495,6 +1487,9 @@ static void sm501_2d_engine_write(void *opaque, hwaddr addr,
s->twoD_background = value;
break;
case SM501_2D_STRETCH:
if (((value >> 20) & 3) == 3) {
value &= ~BIT(20);
}
s->twoD_stretch = value;
break;
case SM501_2D_COLOR_COMPARE:
@ -1819,8 +1814,6 @@ static void sm501_init(SM501State *s, DeviceState *dev,
uint32_t local_mem_bytes)
{
s->local_mem_size_index = get_local_mem_size_index(local_mem_bytes);
SM501_DPRINTF("sm501 local mem size=%x. index=%d\n", get_local_mem_size(s),
s->local_mem_size_index);
/* local memory */
memory_region_init_ram(&s->local_mem_region, OBJECT(dev), "sm501.local",

View File

@ -161,3 +161,15 @@ cg3_write(uint32_t addr, uint32_t val, unsigned size) "write addr:0x%06"PRIx32"
# dpcd.c
dpcd_read(uint32_t addr, uint8_t val) "read addr:0x%"PRIx32" val:0x%02x"
dpcd_write(uint32_t addr, uint8_t val) "write addr:0x%"PRIx32" val:0x%02x"
# sm501.c
sm501_system_config_read(uint32_t addr, uint32_t val) "addr=0x%x, val=0x%x"
sm501_system_config_write(uint32_t addr, uint32_t val) "addr=0x%x, val=0x%x"
sm501_i2c_read(uint32_t addr, uint8_t val) "addr=0x%x, val=0x%x"
sm501_i2c_write(uint32_t addr, uint32_t val) "addr=0x%x, val=0x%x"
sm501_palette_read(uint32_t addr) "addr=0x%x"
sm501_palette_write(uint32_t addr, uint32_t val) "addr=0x%x, val=0x%x"
sm501_disp_ctrl_read(uint32_t addr, uint32_t val) "addr=0x%x, val=0x%x"
sm501_disp_ctrl_write(uint32_t addr, uint32_t val) "addr=0x%x, val=0x%x"
sm501_2d_engine_read(uint32_t addr, uint32_t val) "addr=0x%x, val=0x%x"
sm501_2d_engine_write(uint32_t addr, uint32_t val) "addr=0x%x, val=0x%x"