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:
commit
d0c8b957ae
6
configure
vendored
6
configure
vendored
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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},
|
||||
|
@ -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
|
||||
|
@ -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",
|
||||
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user