cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

sm501.c (70356B)


      1/*
      2 * QEMU SM501 Device
      3 *
      4 * Copyright (c) 2008 Shin-ichiro KAWASAKI
      5 * Copyright (c) 2016-2020 BALATON Zoltan
      6 *
      7 * Permission is hereby granted, free of charge, to any person obtaining a copy
      8 * of this software and associated documentation files (the "Software"), to deal
      9 * in the Software without restriction, including without limitation the rights
     10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     11 * copies of the Software, and to permit persons to whom the Software is
     12 * furnished to do so, subject to the following conditions:
     13 *
     14 * The above copyright notice and this permission notice shall be included in
     15 * all copies or substantial portions of the Software.
     16 *
     17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
     20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     23 * THE SOFTWARE.
     24 */
     25
     26#include "qemu/osdep.h"
     27#include "qemu/units.h"
     28#include "qapi/error.h"
     29#include "qemu/log.h"
     30#include "qemu/module.h"
     31#include "hw/char/serial.h"
     32#include "ui/console.h"
     33#include "hw/sysbus.h"
     34#include "migration/vmstate.h"
     35#include "hw/pci/pci.h"
     36#include "hw/qdev-properties.h"
     37#include "hw/i2c/i2c.h"
     38#include "hw/display/i2c-ddc.h"
     39#include "qemu/range.h"
     40#include "ui/pixel_ops.h"
     41#include "qemu/bswap.h"
     42#include "trace.h"
     43#include "qom/object.h"
     44
     45#define MMIO_BASE_OFFSET 0x3e00000
     46#define MMIO_SIZE 0x200000
     47#define DC_PALETTE_ENTRIES (0x400 * 3)
     48
     49/* SM501 register definitions taken from "linux/include/linux/sm501-regs.h" */
     50
     51/* System Configuration area */
     52/* System config base */
     53#define SM501_SYS_CONFIG                (0x000000)
     54
     55/* config 1 */
     56#define SM501_SYSTEM_CONTROL            (0x000000)
     57
     58#define SM501_SYSCTRL_PANEL_TRISTATE    (1 << 0)
     59#define SM501_SYSCTRL_MEM_TRISTATE      (1 << 1)
     60#define SM501_SYSCTRL_CRT_TRISTATE      (1 << 2)
     61
     62#define SM501_SYSCTRL_PCI_SLAVE_BURST_MASK (3 << 4)
     63#define SM501_SYSCTRL_PCI_SLAVE_BURST_1 (0 << 4)
     64#define SM501_SYSCTRL_PCI_SLAVE_BURST_2 (1 << 4)
     65#define SM501_SYSCTRL_PCI_SLAVE_BURST_4 (2 << 4)
     66#define SM501_SYSCTRL_PCI_SLAVE_BURST_8 (3 << 4)
     67
     68#define SM501_SYSCTRL_PCI_CLOCK_RUN_EN  (1 << 6)
     69#define SM501_SYSCTRL_PCI_RETRY_DISABLE (1 << 7)
     70#define SM501_SYSCTRL_PCI_SUBSYS_LOCK   (1 << 11)
     71#define SM501_SYSCTRL_PCI_BURST_READ_EN (1 << 15)
     72
     73/* miscellaneous control */
     74
     75#define SM501_MISC_CONTROL              (0x000004)
     76
     77#define SM501_MISC_BUS_SH               (0x0)
     78#define SM501_MISC_BUS_PCI              (0x1)
     79#define SM501_MISC_BUS_XSCALE           (0x2)
     80#define SM501_MISC_BUS_NEC              (0x6)
     81#define SM501_MISC_BUS_MASK             (0x7)
     82
     83#define SM501_MISC_VR_62MB              (1 << 3)
     84#define SM501_MISC_CDR_RESET            (1 << 7)
     85#define SM501_MISC_USB_LB               (1 << 8)
     86#define SM501_MISC_USB_SLAVE            (1 << 9)
     87#define SM501_MISC_BL_1                 (1 << 10)
     88#define SM501_MISC_MC                   (1 << 11)
     89#define SM501_MISC_DAC_POWER            (1 << 12)
     90#define SM501_MISC_IRQ_INVERT           (1 << 16)
     91#define SM501_MISC_SH                   (1 << 17)
     92
     93#define SM501_MISC_HOLD_EMPTY           (0 << 18)
     94#define SM501_MISC_HOLD_8               (1 << 18)
     95#define SM501_MISC_HOLD_16              (2 << 18)
     96#define SM501_MISC_HOLD_24              (3 << 18)
     97#define SM501_MISC_HOLD_32              (4 << 18)
     98#define SM501_MISC_HOLD_MASK            (7 << 18)
     99
    100#define SM501_MISC_FREQ_12              (1 << 24)
    101#define SM501_MISC_PNL_24BIT            (1 << 25)
    102#define SM501_MISC_8051_LE              (1 << 26)
    103
    104
    105
    106#define SM501_GPIO31_0_CONTROL          (0x000008)
    107#define SM501_GPIO63_32_CONTROL         (0x00000C)
    108#define SM501_DRAM_CONTROL              (0x000010)
    109
    110/* command list */
    111#define SM501_ARBTRTN_CONTROL           (0x000014)
    112
    113/* command list */
    114#define SM501_COMMAND_LIST_STATUS       (0x000024)
    115
    116/* interrupt debug */
    117#define SM501_RAW_IRQ_STATUS            (0x000028)
    118#define SM501_RAW_IRQ_CLEAR             (0x000028)
    119#define SM501_IRQ_STATUS                (0x00002C)
    120#define SM501_IRQ_MASK                  (0x000030)
    121#define SM501_DEBUG_CONTROL             (0x000034)
    122
    123/* power management */
    124#define SM501_POWERMODE_P2X_SRC         (1 << 29)
    125#define SM501_POWERMODE_V2X_SRC         (1 << 20)
    126#define SM501_POWERMODE_M_SRC           (1 << 12)
    127#define SM501_POWERMODE_M1_SRC          (1 << 4)
    128
    129#define SM501_CURRENT_GATE              (0x000038)
    130#define SM501_CURRENT_CLOCK             (0x00003C)
    131#define SM501_POWER_MODE_0_GATE         (0x000040)
    132#define SM501_POWER_MODE_0_CLOCK        (0x000044)
    133#define SM501_POWER_MODE_1_GATE         (0x000048)
    134#define SM501_POWER_MODE_1_CLOCK        (0x00004C)
    135#define SM501_SLEEP_MODE_GATE           (0x000050)
    136#define SM501_POWER_MODE_CONTROL        (0x000054)
    137
    138/* power gates for units within the 501 */
    139#define SM501_GATE_HOST                 (0)
    140#define SM501_GATE_MEMORY               (1)
    141#define SM501_GATE_DISPLAY              (2)
    142#define SM501_GATE_2D_ENGINE            (3)
    143#define SM501_GATE_CSC                  (4)
    144#define SM501_GATE_ZVPORT               (5)
    145#define SM501_GATE_GPIO                 (6)
    146#define SM501_GATE_UART0                (7)
    147#define SM501_GATE_UART1                (8)
    148#define SM501_GATE_SSP                  (10)
    149#define SM501_GATE_USB_HOST             (11)
    150#define SM501_GATE_USB_GADGET           (12)
    151#define SM501_GATE_UCONTROLLER          (17)
    152#define SM501_GATE_AC97                 (18)
    153
    154/* panel clock */
    155#define SM501_CLOCK_P2XCLK              (24)
    156/* crt clock */
    157#define SM501_CLOCK_V2XCLK              (16)
    158/* main clock */
    159#define SM501_CLOCK_MCLK                (8)
    160/* SDRAM controller clock */
    161#define SM501_CLOCK_M1XCLK              (0)
    162
    163/* config 2 */
    164#define SM501_PCI_MASTER_BASE           (0x000058)
    165#define SM501_ENDIAN_CONTROL            (0x00005C)
    166#define SM501_DEVICEID                  (0x000060)
    167/* 0x050100A0 */
    168
    169#define SM501_DEVICEID_SM501            (0x05010000)
    170#define SM501_DEVICEID_IDMASK           (0xffff0000)
    171#define SM501_DEVICEID_REVMASK          (0x000000ff)
    172
    173#define SM501_PLLCLOCK_COUNT            (0x000064)
    174#define SM501_MISC_TIMING               (0x000068)
    175#define SM501_CURRENT_SDRAM_CLOCK       (0x00006C)
    176
    177#define SM501_PROGRAMMABLE_PLL_CONTROL  (0x000074)
    178
    179/* GPIO base */
    180#define SM501_GPIO                      (0x010000)
    181#define SM501_GPIO_DATA_LOW             (0x00)
    182#define SM501_GPIO_DATA_HIGH            (0x04)
    183#define SM501_GPIO_DDR_LOW              (0x08)
    184#define SM501_GPIO_DDR_HIGH             (0x0C)
    185#define SM501_GPIO_IRQ_SETUP            (0x10)
    186#define SM501_GPIO_IRQ_STATUS           (0x14)
    187#define SM501_GPIO_IRQ_RESET            (0x14)
    188
    189/* I2C controller base */
    190#define SM501_I2C                       (0x010040)
    191#define SM501_I2C_BYTE_COUNT            (0x00)
    192#define SM501_I2C_CONTROL               (0x01)
    193#define SM501_I2C_STATUS                (0x02)
    194#define SM501_I2C_RESET                 (0x02)
    195#define SM501_I2C_SLAVE_ADDRESS         (0x03)
    196#define SM501_I2C_DATA                  (0x04)
    197
    198#define SM501_I2C_CONTROL_START         (1 << 2)
    199#define SM501_I2C_CONTROL_ENABLE        (1 << 0)
    200
    201#define SM501_I2C_STATUS_COMPLETE       (1 << 3)
    202#define SM501_I2C_STATUS_ERROR          (1 << 2)
    203
    204#define SM501_I2C_RESET_ERROR           (1 << 2)
    205
    206/* SSP base */
    207#define SM501_SSP                       (0x020000)
    208
    209/* Uart 0 base */
    210#define SM501_UART0                     (0x030000)
    211
    212/* Uart 1 base */
    213#define SM501_UART1                     (0x030020)
    214
    215/* USB host port base */
    216#define SM501_USB_HOST                  (0x040000)
    217
    218/* USB slave/gadget base */
    219#define SM501_USB_GADGET                (0x060000)
    220
    221/* USB slave/gadget data port base */
    222#define SM501_USB_GADGET_DATA           (0x070000)
    223
    224/* Display controller/video engine base */
    225#define SM501_DC                        (0x080000)
    226
    227/* common defines for the SM501 address registers */
    228#define SM501_ADDR_FLIP                 (1 << 31)
    229#define SM501_ADDR_EXT                  (1 << 27)
    230#define SM501_ADDR_CS1                  (1 << 26)
    231#define SM501_ADDR_MASK                 (0x3f << 26)
    232
    233#define SM501_FIFO_MASK                 (0x3 << 16)
    234#define SM501_FIFO_1                    (0x0 << 16)
    235#define SM501_FIFO_3                    (0x1 << 16)
    236#define SM501_FIFO_7                    (0x2 << 16)
    237#define SM501_FIFO_11                   (0x3 << 16)
    238
    239/* common registers for panel and the crt */
    240#define SM501_OFF_DC_H_TOT              (0x000)
    241#define SM501_OFF_DC_V_TOT              (0x008)
    242#define SM501_OFF_DC_H_SYNC             (0x004)
    243#define SM501_OFF_DC_V_SYNC             (0x00C)
    244
    245#define SM501_DC_PANEL_CONTROL          (0x000)
    246
    247#define SM501_DC_PANEL_CONTROL_FPEN     (1 << 27)
    248#define SM501_DC_PANEL_CONTROL_BIAS     (1 << 26)
    249#define SM501_DC_PANEL_CONTROL_DATA     (1 << 25)
    250#define SM501_DC_PANEL_CONTROL_VDD      (1 << 24)
    251#define SM501_DC_PANEL_CONTROL_DP       (1 << 23)
    252
    253#define SM501_DC_PANEL_CONTROL_TFT_888  (0 << 21)
    254#define SM501_DC_PANEL_CONTROL_TFT_333  (1 << 21)
    255#define SM501_DC_PANEL_CONTROL_TFT_444  (2 << 21)
    256
    257#define SM501_DC_PANEL_CONTROL_DE       (1 << 20)
    258
    259#define SM501_DC_PANEL_CONTROL_LCD_TFT  (0 << 18)
    260#define SM501_DC_PANEL_CONTROL_LCD_STN8 (1 << 18)
    261#define SM501_DC_PANEL_CONTROL_LCD_STN12 (2 << 18)
    262
    263#define SM501_DC_PANEL_CONTROL_CP       (1 << 14)
    264#define SM501_DC_PANEL_CONTROL_VSP      (1 << 13)
    265#define SM501_DC_PANEL_CONTROL_HSP      (1 << 12)
    266#define SM501_DC_PANEL_CONTROL_CK       (1 << 9)
    267#define SM501_DC_PANEL_CONTROL_TE       (1 << 8)
    268#define SM501_DC_PANEL_CONTROL_VPD      (1 << 7)
    269#define SM501_DC_PANEL_CONTROL_VP       (1 << 6)
    270#define SM501_DC_PANEL_CONTROL_HPD      (1 << 5)
    271#define SM501_DC_PANEL_CONTROL_HP       (1 << 4)
    272#define SM501_DC_PANEL_CONTROL_GAMMA    (1 << 3)
    273#define SM501_DC_PANEL_CONTROL_EN       (1 << 2)
    274
    275#define SM501_DC_PANEL_CONTROL_8BPP     (0 << 0)
    276#define SM501_DC_PANEL_CONTROL_16BPP    (1 << 0)
    277#define SM501_DC_PANEL_CONTROL_32BPP    (2 << 0)
    278
    279
    280#define SM501_DC_PANEL_PANNING_CONTROL  (0x004)
    281#define SM501_DC_PANEL_COLOR_KEY        (0x008)
    282#define SM501_DC_PANEL_FB_ADDR          (0x00C)
    283#define SM501_DC_PANEL_FB_OFFSET        (0x010)
    284#define SM501_DC_PANEL_FB_WIDTH         (0x014)
    285#define SM501_DC_PANEL_FB_HEIGHT        (0x018)
    286#define SM501_DC_PANEL_TL_LOC           (0x01C)
    287#define SM501_DC_PANEL_BR_LOC           (0x020)
    288#define SM501_DC_PANEL_H_TOT            (0x024)
    289#define SM501_DC_PANEL_H_SYNC           (0x028)
    290#define SM501_DC_PANEL_V_TOT            (0x02C)
    291#define SM501_DC_PANEL_V_SYNC           (0x030)
    292#define SM501_DC_PANEL_CUR_LINE         (0x034)
    293
    294#define SM501_DC_VIDEO_CONTROL          (0x040)
    295#define SM501_DC_VIDEO_FB0_ADDR         (0x044)
    296#define SM501_DC_VIDEO_FB_WIDTH         (0x048)
    297#define SM501_DC_VIDEO_FB0_LAST_ADDR    (0x04C)
    298#define SM501_DC_VIDEO_TL_LOC           (0x050)
    299#define SM501_DC_VIDEO_BR_LOC           (0x054)
    300#define SM501_DC_VIDEO_SCALE            (0x058)
    301#define SM501_DC_VIDEO_INIT_SCALE       (0x05C)
    302#define SM501_DC_VIDEO_YUV_CONSTANTS    (0x060)
    303#define SM501_DC_VIDEO_FB1_ADDR         (0x064)
    304#define SM501_DC_VIDEO_FB1_LAST_ADDR    (0x068)
    305
    306#define SM501_DC_VIDEO_ALPHA_CONTROL    (0x080)
    307#define SM501_DC_VIDEO_ALPHA_FB_ADDR    (0x084)
    308#define SM501_DC_VIDEO_ALPHA_FB_OFFSET  (0x088)
    309#define SM501_DC_VIDEO_ALPHA_FB_LAST_ADDR (0x08C)
    310#define SM501_DC_VIDEO_ALPHA_TL_LOC     (0x090)
    311#define SM501_DC_VIDEO_ALPHA_BR_LOC     (0x094)
    312#define SM501_DC_VIDEO_ALPHA_SCALE      (0x098)
    313#define SM501_DC_VIDEO_ALPHA_INIT_SCALE (0x09C)
    314#define SM501_DC_VIDEO_ALPHA_CHROMA_KEY (0x0A0)
    315#define SM501_DC_VIDEO_ALPHA_COLOR_LOOKUP (0x0A4)
    316
    317#define SM501_DC_PANEL_HWC_BASE         (0x0F0)
    318#define SM501_DC_PANEL_HWC_ADDR         (0x0F0)
    319#define SM501_DC_PANEL_HWC_LOC          (0x0F4)
    320#define SM501_DC_PANEL_HWC_COLOR_1_2    (0x0F8)
    321#define SM501_DC_PANEL_HWC_COLOR_3      (0x0FC)
    322
    323#define SM501_HWC_EN                    (1 << 31)
    324
    325#define SM501_OFF_HWC_ADDR              (0x00)
    326#define SM501_OFF_HWC_LOC               (0x04)
    327#define SM501_OFF_HWC_COLOR_1_2         (0x08)
    328#define SM501_OFF_HWC_COLOR_3           (0x0C)
    329
    330#define SM501_DC_ALPHA_CONTROL          (0x100)
    331#define SM501_DC_ALPHA_FB_ADDR          (0x104)
    332#define SM501_DC_ALPHA_FB_OFFSET        (0x108)
    333#define SM501_DC_ALPHA_TL_LOC           (0x10C)
    334#define SM501_DC_ALPHA_BR_LOC           (0x110)
    335#define SM501_DC_ALPHA_CHROMA_KEY       (0x114)
    336#define SM501_DC_ALPHA_COLOR_LOOKUP     (0x118)
    337
    338#define SM501_DC_CRT_CONTROL            (0x200)
    339
    340#define SM501_DC_CRT_CONTROL_TVP        (1 << 15)
    341#define SM501_DC_CRT_CONTROL_CP         (1 << 14)
    342#define SM501_DC_CRT_CONTROL_VSP        (1 << 13)
    343#define SM501_DC_CRT_CONTROL_HSP        (1 << 12)
    344#define SM501_DC_CRT_CONTROL_VS         (1 << 11)
    345#define SM501_DC_CRT_CONTROL_BLANK      (1 << 10)
    346#define SM501_DC_CRT_CONTROL_SEL        (1 << 9)
    347#define SM501_DC_CRT_CONTROL_TE         (1 << 8)
    348#define SM501_DC_CRT_CONTROL_PIXEL_MASK (0xF << 4)
    349#define SM501_DC_CRT_CONTROL_GAMMA      (1 << 3)
    350#define SM501_DC_CRT_CONTROL_ENABLE     (1 << 2)
    351
    352#define SM501_DC_CRT_CONTROL_8BPP       (0 << 0)
    353#define SM501_DC_CRT_CONTROL_16BPP      (1 << 0)
    354#define SM501_DC_CRT_CONTROL_32BPP      (2 << 0)
    355
    356#define SM501_DC_CRT_FB_ADDR            (0x204)
    357#define SM501_DC_CRT_FB_OFFSET          (0x208)
    358#define SM501_DC_CRT_H_TOT              (0x20C)
    359#define SM501_DC_CRT_H_SYNC             (0x210)
    360#define SM501_DC_CRT_V_TOT              (0x214)
    361#define SM501_DC_CRT_V_SYNC             (0x218)
    362#define SM501_DC_CRT_SIGNATURE_ANALYZER (0x21C)
    363#define SM501_DC_CRT_CUR_LINE           (0x220)
    364#define SM501_DC_CRT_MONITOR_DETECT     (0x224)
    365
    366#define SM501_DC_CRT_HWC_BASE           (0x230)
    367#define SM501_DC_CRT_HWC_ADDR           (0x230)
    368#define SM501_DC_CRT_HWC_LOC            (0x234)
    369#define SM501_DC_CRT_HWC_COLOR_1_2      (0x238)
    370#define SM501_DC_CRT_HWC_COLOR_3        (0x23C)
    371
    372#define SM501_DC_PANEL_PALETTE          (0x400)
    373
    374#define SM501_DC_VIDEO_PALETTE          (0x800)
    375
    376#define SM501_DC_CRT_PALETTE            (0xC00)
    377
    378/* Zoom Video port base */
    379#define SM501_ZVPORT                    (0x090000)
    380
    381/* AC97/I2S base */
    382#define SM501_AC97                      (0x0A0000)
    383
    384/* 8051 micro controller base */
    385#define SM501_UCONTROLLER               (0x0B0000)
    386
    387/* 8051 micro controller SRAM base */
    388#define SM501_UCONTROLLER_SRAM          (0x0C0000)
    389
    390/* DMA base */
    391#define SM501_DMA                       (0x0D0000)
    392
    393/* 2d engine base */
    394#define SM501_2D_ENGINE                 (0x100000)
    395#define SM501_2D_SOURCE                 (0x00)
    396#define SM501_2D_DESTINATION            (0x04)
    397#define SM501_2D_DIMENSION              (0x08)
    398#define SM501_2D_CONTROL                (0x0C)
    399#define SM501_2D_PITCH                  (0x10)
    400#define SM501_2D_FOREGROUND             (0x14)
    401#define SM501_2D_BACKGROUND             (0x18)
    402#define SM501_2D_STRETCH                (0x1C)
    403#define SM501_2D_COLOR_COMPARE          (0x20)
    404#define SM501_2D_COLOR_COMPARE_MASK     (0x24)
    405#define SM501_2D_MASK                   (0x28)
    406#define SM501_2D_CLIP_TL                (0x2C)
    407#define SM501_2D_CLIP_BR                (0x30)
    408#define SM501_2D_MONO_PATTERN_LOW       (0x34)
    409#define SM501_2D_MONO_PATTERN_HIGH      (0x38)
    410#define SM501_2D_WINDOW_WIDTH           (0x3C)
    411#define SM501_2D_SOURCE_BASE            (0x40)
    412#define SM501_2D_DESTINATION_BASE       (0x44)
    413#define SM501_2D_ALPHA                  (0x48)
    414#define SM501_2D_WRAP                   (0x4C)
    415#define SM501_2D_STATUS                 (0x50)
    416
    417#define SM501_CSC_Y_SOURCE_BASE         (0xC8)
    418#define SM501_CSC_CONSTANTS             (0xCC)
    419#define SM501_CSC_Y_SOURCE_X            (0xD0)
    420#define SM501_CSC_Y_SOURCE_Y            (0xD4)
    421#define SM501_CSC_U_SOURCE_BASE         (0xD8)
    422#define SM501_CSC_V_SOURCE_BASE         (0xDC)
    423#define SM501_CSC_SOURCE_DIMENSION      (0xE0)
    424#define SM501_CSC_SOURCE_PITCH          (0xE4)
    425#define SM501_CSC_DESTINATION           (0xE8)
    426#define SM501_CSC_DESTINATION_DIMENSION (0xEC)
    427#define SM501_CSC_DESTINATION_PITCH     (0xF0)
    428#define SM501_CSC_SCALE_FACTOR          (0xF4)
    429#define SM501_CSC_DESTINATION_BASE      (0xF8)
    430#define SM501_CSC_CONTROL               (0xFC)
    431
    432/* 2d engine data port base */
    433#define SM501_2D_ENGINE_DATA            (0x110000)
    434
    435/* end of register definitions */
    436
    437#define SM501_HWC_WIDTH                       (64)
    438#define SM501_HWC_HEIGHT                      (64)
    439
    440/* SM501 local memory size taken from "linux/drivers/mfd/sm501.c" */
    441static const uint32_t sm501_mem_local_size[] = {
    442    [0] = 4 * MiB,
    443    [1] = 8 * MiB,
    444    [2] = 16 * MiB,
    445    [3] = 32 * MiB,
    446    [4] = 64 * MiB,
    447    [5] = 2 * MiB,
    448};
    449#define get_local_mem_size(s) sm501_mem_local_size[(s)->local_mem_size_index]
    450
    451typedef struct SM501State {
    452    /* graphic console status */
    453    QemuConsole *con;
    454
    455    /* status & internal resources */
    456    uint32_t local_mem_size_index;
    457    uint8_t *local_mem;
    458    MemoryRegion local_mem_region;
    459    MemoryRegion mmio_region;
    460    MemoryRegion system_config_region;
    461    MemoryRegion i2c_region;
    462    MemoryRegion disp_ctrl_region;
    463    MemoryRegion twoD_engine_region;
    464    uint32_t last_width;
    465    uint32_t last_height;
    466    bool do_full_update; /* perform a full update next time */
    467    I2CBus *i2c_bus;
    468
    469    /* mmio registers */
    470    uint32_t system_control;
    471    uint32_t misc_control;
    472    uint32_t gpio_31_0_control;
    473    uint32_t gpio_63_32_control;
    474    uint32_t dram_control;
    475    uint32_t arbitration_control;
    476    uint32_t irq_mask;
    477    uint32_t misc_timing;
    478    uint32_t power_mode_control;
    479
    480    uint8_t i2c_byte_count;
    481    uint8_t i2c_status;
    482    uint8_t i2c_addr;
    483    uint8_t i2c_data[16];
    484
    485    uint32_t uart0_ier;
    486    uint32_t uart0_lcr;
    487    uint32_t uart0_mcr;
    488    uint32_t uart0_scr;
    489
    490    uint8_t dc_palette[DC_PALETTE_ENTRIES];
    491
    492    uint32_t dc_panel_control;
    493    uint32_t dc_panel_panning_control;
    494    uint32_t dc_panel_fb_addr;
    495    uint32_t dc_panel_fb_offset;
    496    uint32_t dc_panel_fb_width;
    497    uint32_t dc_panel_fb_height;
    498    uint32_t dc_panel_tl_location;
    499    uint32_t dc_panel_br_location;
    500    uint32_t dc_panel_h_total;
    501    uint32_t dc_panel_h_sync;
    502    uint32_t dc_panel_v_total;
    503    uint32_t dc_panel_v_sync;
    504
    505    uint32_t dc_panel_hwc_addr;
    506    uint32_t dc_panel_hwc_location;
    507    uint32_t dc_panel_hwc_color_1_2;
    508    uint32_t dc_panel_hwc_color_3;
    509
    510    uint32_t dc_video_control;
    511
    512    uint32_t dc_crt_control;
    513    uint32_t dc_crt_fb_addr;
    514    uint32_t dc_crt_fb_offset;
    515    uint32_t dc_crt_h_total;
    516    uint32_t dc_crt_h_sync;
    517    uint32_t dc_crt_v_total;
    518    uint32_t dc_crt_v_sync;
    519
    520    uint32_t dc_crt_hwc_addr;
    521    uint32_t dc_crt_hwc_location;
    522    uint32_t dc_crt_hwc_color_1_2;
    523    uint32_t dc_crt_hwc_color_3;
    524
    525    uint32_t twoD_source;
    526    uint32_t twoD_destination;
    527    uint32_t twoD_dimension;
    528    uint32_t twoD_control;
    529    uint32_t twoD_pitch;
    530    uint32_t twoD_foreground;
    531    uint32_t twoD_background;
    532    uint32_t twoD_stretch;
    533    uint32_t twoD_color_compare;
    534    uint32_t twoD_color_compare_mask;
    535    uint32_t twoD_mask;
    536    uint32_t twoD_clip_tl;
    537    uint32_t twoD_clip_br;
    538    uint32_t twoD_mono_pattern_low;
    539    uint32_t twoD_mono_pattern_high;
    540    uint32_t twoD_window_width;
    541    uint32_t twoD_source_base;
    542    uint32_t twoD_destination_base;
    543    uint32_t twoD_alpha;
    544    uint32_t twoD_wrap;
    545} SM501State;
    546
    547static uint32_t get_local_mem_size_index(uint32_t size)
    548{
    549    uint32_t norm_size = 0;
    550    int i, index = 0;
    551
    552    for (i = 0; i < ARRAY_SIZE(sm501_mem_local_size); i++) {
    553        uint32_t new_size = sm501_mem_local_size[i];
    554        if (new_size >= size) {
    555            if (norm_size == 0 || norm_size > new_size) {
    556                norm_size = new_size;
    557                index = i;
    558            }
    559        }
    560    }
    561
    562    return index;
    563}
    564
    565static ram_addr_t get_fb_addr(SM501State *s, int crt)
    566{
    567    return (crt ? s->dc_crt_fb_addr : s->dc_panel_fb_addr) & 0x3FFFFF0;
    568}
    569
    570static inline int get_width(SM501State *s, int crt)
    571{
    572    int width = crt ? s->dc_crt_h_total : s->dc_panel_h_total;
    573    return (width & 0x00000FFF) + 1;
    574}
    575
    576static inline int get_height(SM501State *s, int crt)
    577{
    578    int height = crt ? s->dc_crt_v_total : s->dc_panel_v_total;
    579    return (height & 0x00000FFF) + 1;
    580}
    581
    582static inline int get_bpp(SM501State *s, int crt)
    583{
    584    int bpp = crt ? s->dc_crt_control : s->dc_panel_control;
    585    return 1 << (bpp & 3);
    586}
    587
    588/**
    589 * Check the availability of hardware cursor.
    590 * @param crt  0 for PANEL, 1 for CRT.
    591 */
    592static inline int is_hwc_enabled(SM501State *state, int crt)
    593{
    594    uint32_t addr = crt ? state->dc_crt_hwc_addr : state->dc_panel_hwc_addr;
    595    return addr & SM501_HWC_EN;
    596}
    597
    598/**
    599 * Get the address which holds cursor pattern data.
    600 * @param crt  0 for PANEL, 1 for CRT.
    601 */
    602static inline uint8_t *get_hwc_address(SM501State *state, int crt)
    603{
    604    uint32_t addr = crt ? state->dc_crt_hwc_addr : state->dc_panel_hwc_addr;
    605    return state->local_mem + (addr & 0x03FFFFF0);
    606}
    607
    608/**
    609 * Get the cursor position in y coordinate.
    610 * @param crt  0 for PANEL, 1 for CRT.
    611 */
    612static inline uint32_t get_hwc_y(SM501State *state, int crt)
    613{
    614    uint32_t location = crt ? state->dc_crt_hwc_location
    615                            : state->dc_panel_hwc_location;
    616    return (location & 0x07FF0000) >> 16;
    617}
    618
    619/**
    620 * Get the cursor position in x coordinate.
    621 * @param crt  0 for PANEL, 1 for CRT.
    622 */
    623static inline uint32_t get_hwc_x(SM501State *state, int crt)
    624{
    625    uint32_t location = crt ? state->dc_crt_hwc_location
    626                            : state->dc_panel_hwc_location;
    627    return location & 0x000007FF;
    628}
    629
    630/**
    631 * Get the hardware cursor palette.
    632 * @param crt  0 for PANEL, 1 for CRT.
    633 * @param palette  pointer to a [3 * 3] array to store color values in
    634 */
    635static inline void get_hwc_palette(SM501State *state, int crt, uint8_t *palette)
    636{
    637    int i;
    638    uint32_t color_reg;
    639    uint16_t rgb565;
    640
    641    for (i = 0; i < 3; i++) {
    642        if (i + 1 == 3) {
    643            color_reg = crt ? state->dc_crt_hwc_color_3
    644                            : state->dc_panel_hwc_color_3;
    645        } else {
    646            color_reg = crt ? state->dc_crt_hwc_color_1_2
    647                            : state->dc_panel_hwc_color_1_2;
    648        }
    649
    650        if (i + 1 == 2) {
    651            rgb565 = (color_reg >> 16) & 0xFFFF;
    652        } else {
    653            rgb565 = color_reg & 0xFFFF;
    654        }
    655        palette[i * 3 + 0] = ((rgb565 >> 11) * 527 + 23) >> 6; /* r */
    656        palette[i * 3 + 1] = (((rgb565 >> 5) & 0x3f) * 259 + 33) >> 6; /* g */
    657        palette[i * 3 + 2] = ((rgb565 & 0x1f) * 527 + 23) >> 6; /* b */
    658    }
    659}
    660
    661static inline void hwc_invalidate(SM501State *s, int crt)
    662{
    663    int w = get_width(s, crt);
    664    int h = get_height(s, crt);
    665    int bpp = get_bpp(s, crt);
    666    int start = get_hwc_y(s, crt);
    667    int end = MIN(h, start + SM501_HWC_HEIGHT) + 1;
    668
    669    start *= w * bpp;
    670    end *= w * bpp;
    671
    672    memory_region_set_dirty(&s->local_mem_region,
    673                            get_fb_addr(s, crt) + start, end - start);
    674}
    675
    676static void sm501_2d_operation(SM501State *s)
    677{
    678    int cmd = (s->twoD_control >> 16) & 0x1F;
    679    int rtl = s->twoD_control & BIT(27);
    680    int format = (s->twoD_stretch >> 20) & 3;
    681    int bypp = 1 << format; /* bytes per pixel */
    682    int rop_mode = (s->twoD_control >> 15) & 1; /* 1 for rop2, else rop3 */
    683    /* 1 if rop2 source is the pattern, otherwise the source is the bitmap */
    684    int rop2_source_is_pattern = (s->twoD_control >> 14) & 1;
    685    int rop = s->twoD_control & 0xFF;
    686    unsigned int dst_x = (s->twoD_destination >> 16) & 0x01FFF;
    687    unsigned int dst_y = s->twoD_destination & 0xFFFF;
    688    unsigned int width = (s->twoD_dimension >> 16) & 0x1FFF;
    689    unsigned int height = s->twoD_dimension & 0xFFFF;
    690    uint32_t dst_base = s->twoD_destination_base & 0x03FFFFFF;
    691    unsigned int dst_pitch = (s->twoD_pitch >> 16) & 0x1FFF;
    692    int crt = (s->dc_crt_control & SM501_DC_CRT_CONTROL_SEL) ? 1 : 0;
    693    int fb_len = get_width(s, crt) * get_height(s, crt) * get_bpp(s, crt);
    694    bool overlap = false;
    695
    696    if ((s->twoD_stretch >> 16) & 0xF) {
    697        qemu_log_mask(LOG_UNIMP, "sm501: only XY addressing is supported.\n");
    698        return;
    699    }
    700
    701    if (s->twoD_source_base & BIT(27) || s->twoD_destination_base & BIT(27)) {
    702        qemu_log_mask(LOG_UNIMP, "sm501: only local memory is supported.\n");
    703        return;
    704    }
    705
    706    if (!dst_pitch) {
    707        qemu_log_mask(LOG_GUEST_ERROR, "sm501: Zero dest pitch.\n");
    708        return;
    709    }
    710
    711    if (!width || !height) {
    712        qemu_log_mask(LOG_GUEST_ERROR, "sm501: Zero size 2D op.\n");
    713        return;
    714    }
    715
    716    if (rtl) {
    717        dst_x -= width - 1;
    718        dst_y -= height - 1;
    719    }
    720
    721    if (dst_base >= get_local_mem_size(s) ||
    722        dst_base + (dst_x + width + (dst_y + height) * dst_pitch) * bypp >=
    723        get_local_mem_size(s)) {
    724        qemu_log_mask(LOG_GUEST_ERROR, "sm501: 2D op dest is outside vram.\n");
    725        return;
    726    }
    727
    728    switch (cmd) {
    729    case 0: /* BitBlt */
    730    {
    731        static uint32_t tmp_buf[16384];
    732        unsigned int src_x = (s->twoD_source >> 16) & 0x01FFF;
    733        unsigned int src_y = s->twoD_source & 0xFFFF;
    734        uint32_t src_base = s->twoD_source_base & 0x03FFFFFF;
    735        unsigned int src_pitch = s->twoD_pitch & 0x1FFF;
    736
    737        if (!src_pitch) {
    738            qemu_log_mask(LOG_GUEST_ERROR, "sm501: Zero src pitch.\n");
    739            return;
    740        }
    741
    742        if (rtl) {
    743            src_x -= width - 1;
    744            src_y -= height - 1;
    745        }
    746
    747        if (src_base >= get_local_mem_size(s) ||
    748            src_base + (src_x + width + (src_y + height) * src_pitch) * bypp >=
    749            get_local_mem_size(s)) {
    750            qemu_log_mask(LOG_GUEST_ERROR,
    751                          "sm501: 2D op src is outside vram.\n");
    752            return;
    753        }
    754
    755        if ((rop_mode && rop == 0x5) || (!rop_mode && rop == 0x55)) {
    756            /* Invert dest, is there a way to do this with pixman? */
    757            unsigned int x, y, i;
    758            uint8_t *d = s->local_mem + dst_base;
    759
    760            for (y = 0; y < height; y++) {
    761                i = (dst_x + (dst_y + y) * dst_pitch) * bypp;
    762                for (x = 0; x < width; x++, i += bypp) {
    763                    stn_he_p(&d[i], bypp, ~ldn_he_p(&d[i], bypp));
    764                }
    765            }
    766        } else {
    767            /* Do copy src for unimplemented ops, better than unpainted area */
    768            if ((rop_mode && (rop != 0xc || rop2_source_is_pattern)) ||
    769                (!rop_mode && rop != 0xcc)) {
    770                qemu_log_mask(LOG_UNIMP,
    771                              "sm501: rop%d op %x%s not implemented\n",
    772                              (rop_mode ? 2 : 3), rop,
    773                              (rop2_source_is_pattern ?
    774                                  " with pattern source" : ""));
    775            }
    776            /* Ignore no-op blits, some guests seem to do this */
    777            if (src_base == dst_base && src_pitch == dst_pitch &&
    778                src_x == dst_x && src_y == dst_y) {
    779                break;
    780            }
    781            /* Some clients also do 1 pixel blits, avoid overhead for these */
    782            if (width == 1 && height == 1) {
    783                unsigned int si = (src_x + src_y * src_pitch) * bypp;
    784                unsigned int di = (dst_x + dst_y * dst_pitch) * bypp;
    785                stn_he_p(&s->local_mem[dst_base + di], bypp,
    786                         ldn_he_p(&s->local_mem[src_base + si], bypp));
    787                break;
    788            }
    789            /* If reverse blit do simple check for overlaps */
    790            if (rtl && src_base == dst_base && src_pitch == dst_pitch) {
    791                overlap = (src_x < dst_x + width && src_x + width > dst_x &&
    792                           src_y < dst_y + height && src_y + height > dst_y);
    793            } else if (rtl) {
    794                unsigned int sb, se, db, de;
    795                sb = src_base + (src_x + src_y * src_pitch) * bypp;
    796                se = sb + (width + (height - 1) * src_pitch) * bypp;
    797                db = dst_base + (dst_x + dst_y * dst_pitch) * bypp;
    798                de = db + (width + (height - 1) * dst_pitch) * bypp;
    799                overlap = (db < se && sb < de);
    800            }
    801            if (overlap) {
    802                /* pixman can't do reverse blit: copy via temporary */
    803                int tmp_stride = DIV_ROUND_UP(width * bypp, sizeof(uint32_t));
    804                uint32_t *tmp = tmp_buf;
    805
    806                if (tmp_stride * sizeof(uint32_t) * height > sizeof(tmp_buf)) {
    807                    tmp = g_malloc(tmp_stride * sizeof(uint32_t) * height);
    808                }
    809                pixman_blt((uint32_t *)&s->local_mem[src_base], tmp,
    810                           src_pitch * bypp / sizeof(uint32_t),
    811                           tmp_stride, 8 * bypp, 8 * bypp,
    812                           src_x, src_y, 0, 0, width, height);
    813                pixman_blt(tmp, (uint32_t *)&s->local_mem[dst_base],
    814                           tmp_stride,
    815                           dst_pitch * bypp / sizeof(uint32_t),
    816                           8 * bypp, 8 * bypp,
    817                           0, 0, dst_x, dst_y, width, height);
    818                if (tmp != tmp_buf) {
    819                    g_free(tmp);
    820                }
    821            } else {
    822                pixman_blt((uint32_t *)&s->local_mem[src_base],
    823                           (uint32_t *)&s->local_mem[dst_base],
    824                           src_pitch * bypp / sizeof(uint32_t),
    825                           dst_pitch * bypp / sizeof(uint32_t),
    826                           8 * bypp, 8 * bypp,
    827                           src_x, src_y, dst_x, dst_y, width, height);
    828            }
    829        }
    830        break;
    831    }
    832    case 1: /* Rectangle Fill */
    833    {
    834        uint32_t color = s->twoD_foreground;
    835
    836        if (format == 2) {
    837            color = cpu_to_le32(color);
    838        } else if (format == 1) {
    839            color = cpu_to_le16(color);
    840        }
    841
    842        if (width == 1 && height == 1) {
    843            unsigned int i = (dst_x + dst_y * dst_pitch) * bypp;
    844            stn_he_p(&s->local_mem[dst_base + i], bypp, color);
    845        } else {
    846            pixman_fill((uint32_t *)&s->local_mem[dst_base],
    847                        dst_pitch * bypp / sizeof(uint32_t),
    848                        8 * bypp, dst_x, dst_y, width, height, color);
    849        }
    850        break;
    851    }
    852    default:
    853        qemu_log_mask(LOG_UNIMP, "sm501: not implemented 2D operation: %d\n",
    854                      cmd);
    855        return;
    856    }
    857
    858    if (dst_base >= get_fb_addr(s, crt) &&
    859        dst_base <= get_fb_addr(s, crt) + fb_len) {
    860        int dst_len = MIN(fb_len, ((dst_y + height - 1) * dst_pitch +
    861                          dst_x + width) * bypp);
    862        if (dst_len) {
    863            memory_region_set_dirty(&s->local_mem_region, dst_base, dst_len);
    864        }
    865    }
    866}
    867
    868static uint64_t sm501_system_config_read(void *opaque, hwaddr addr,
    869                                         unsigned size)
    870{
    871    SM501State *s = (SM501State *)opaque;
    872    uint32_t ret = 0;
    873
    874    switch (addr) {
    875    case SM501_SYSTEM_CONTROL:
    876        ret = s->system_control;
    877        break;
    878    case SM501_MISC_CONTROL:
    879        ret = s->misc_control;
    880        break;
    881    case SM501_GPIO31_0_CONTROL:
    882        ret = s->gpio_31_0_control;
    883        break;
    884    case SM501_GPIO63_32_CONTROL:
    885        ret = s->gpio_63_32_control;
    886        break;
    887    case SM501_DEVICEID:
    888        ret = 0x050100A0;
    889        break;
    890    case SM501_DRAM_CONTROL:
    891        ret = (s->dram_control & 0x07F107C0) | s->local_mem_size_index << 13;
    892        break;
    893    case SM501_ARBTRTN_CONTROL:
    894        ret = s->arbitration_control;
    895        break;
    896    case SM501_COMMAND_LIST_STATUS:
    897        ret = 0x00180002; /* FIFOs are empty, everything idle */
    898        break;
    899    case SM501_IRQ_MASK:
    900        ret = s->irq_mask;
    901        break;
    902    case SM501_MISC_TIMING:
    903        /* TODO : simulate gate control */
    904        ret = s->misc_timing;
    905        break;
    906    case SM501_CURRENT_GATE:
    907        /* TODO : simulate gate control */
    908        ret = 0x00021807;
    909        break;
    910    case SM501_CURRENT_CLOCK:
    911        ret = 0x2A1A0A09;
    912        break;
    913    case SM501_POWER_MODE_CONTROL:
    914        ret = s->power_mode_control;
    915        break;
    916    case SM501_ENDIAN_CONTROL:
    917        ret = 0; /* Only default little endian mode is supported */
    918        break;
    919
    920    default:
    921        qemu_log_mask(LOG_UNIMP, "sm501: not implemented system config"
    922                      "register read. addr=%" HWADDR_PRIx "\n", addr);
    923    }
    924    trace_sm501_system_config_read(addr, ret);
    925    return ret;
    926}
    927
    928static void sm501_system_config_write(void *opaque, hwaddr addr,
    929                                      uint64_t value, unsigned size)
    930{
    931    SM501State *s = (SM501State *)opaque;
    932
    933    trace_sm501_system_config_write((uint32_t)addr, (uint32_t)value);
    934    switch (addr) {
    935    case SM501_SYSTEM_CONTROL:
    936        s->system_control &= 0x10DB0000;
    937        s->system_control |= value & 0xEF00B8F7;
    938        break;
    939    case SM501_MISC_CONTROL:
    940        s->misc_control &= 0xEF;
    941        s->misc_control |= value & 0xFF7FFF10;
    942        break;
    943    case SM501_GPIO31_0_CONTROL:
    944        s->gpio_31_0_control = value;
    945        break;
    946    case SM501_GPIO63_32_CONTROL:
    947        s->gpio_63_32_control = value & 0xFF80FFFF;
    948        break;
    949    case SM501_DRAM_CONTROL:
    950        s->local_mem_size_index = (value >> 13) & 0x7;
    951        /* TODO : check validity of size change */
    952        s->dram_control &= 0x80000000;
    953        s->dram_control |= value & 0x7FFFFFC3;
    954        break;
    955    case SM501_ARBTRTN_CONTROL:
    956        s->arbitration_control = value & 0x37777777;
    957        break;
    958    case SM501_IRQ_MASK:
    959        s->irq_mask = value & 0xFFDF3F5F;
    960        break;
    961    case SM501_MISC_TIMING:
    962        s->misc_timing = value & 0xF31F1FFF;
    963        break;
    964    case SM501_POWER_MODE_0_GATE:
    965    case SM501_POWER_MODE_1_GATE:
    966    case SM501_POWER_MODE_0_CLOCK:
    967    case SM501_POWER_MODE_1_CLOCK:
    968        /* TODO : simulate gate & clock control */
    969        break;
    970    case SM501_POWER_MODE_CONTROL:
    971        s->power_mode_control = value & 0x00000003;
    972        break;
    973    case SM501_ENDIAN_CONTROL:
    974        if (value & 0x00000001) {
    975            qemu_log_mask(LOG_UNIMP, "sm501: system config big endian mode not"
    976                          " implemented.\n");
    977        }
    978        break;
    979
    980    default:
    981        qemu_log_mask(LOG_UNIMP, "sm501: not implemented system config"
    982                      "register write. addr=%" HWADDR_PRIx
    983                      ", val=%" PRIx64 "\n", addr, value);
    984    }
    985}
    986
    987static const MemoryRegionOps sm501_system_config_ops = {
    988    .read = sm501_system_config_read,
    989    .write = sm501_system_config_write,
    990    .valid = {
    991        .min_access_size = 4,
    992        .max_access_size = 4,
    993    },
    994    .endianness = DEVICE_LITTLE_ENDIAN,
    995};
    996
    997static uint64_t sm501_i2c_read(void *opaque, hwaddr addr, unsigned size)
    998{
    999    SM501State *s = (SM501State *)opaque;
   1000    uint8_t ret = 0;
   1001
   1002    switch (addr) {
   1003    case SM501_I2C_BYTE_COUNT:
   1004        ret = s->i2c_byte_count;
   1005        break;
   1006    case SM501_I2C_STATUS:
   1007        ret = s->i2c_status;
   1008        break;
   1009    case SM501_I2C_SLAVE_ADDRESS:
   1010        ret = s->i2c_addr;
   1011        break;
   1012    case SM501_I2C_DATA ... SM501_I2C_DATA + 15:
   1013        ret = s->i2c_data[addr - SM501_I2C_DATA];
   1014        break;
   1015    default:
   1016        qemu_log_mask(LOG_UNIMP, "sm501 i2c : not implemented register read."
   1017                      " addr=0x%" HWADDR_PRIx "\n", addr);
   1018    }
   1019    trace_sm501_i2c_read((uint32_t)addr, ret);
   1020    return ret;
   1021}
   1022
   1023static void sm501_i2c_write(void *opaque, hwaddr addr, uint64_t value,
   1024                            unsigned size)
   1025{
   1026    SM501State *s = (SM501State *)opaque;
   1027
   1028    trace_sm501_i2c_write((uint32_t)addr, (uint32_t)value);
   1029    switch (addr) {
   1030    case SM501_I2C_BYTE_COUNT:
   1031        s->i2c_byte_count = value & 0xf;
   1032        break;
   1033    case SM501_I2C_CONTROL:
   1034        if (value & SM501_I2C_CONTROL_ENABLE) {
   1035            if (value & SM501_I2C_CONTROL_START) {
   1036                bool is_recv = s->i2c_addr & 1;
   1037                int res = i2c_start_transfer(s->i2c_bus,
   1038                                             s->i2c_addr >> 1,
   1039                                             is_recv);
   1040                if (res) {
   1041                    s->i2c_status |= SM501_I2C_STATUS_ERROR;
   1042                } else {
   1043                    int i;
   1044                    for (i = 0; i <= s->i2c_byte_count; i++) {
   1045                        if (is_recv) {
   1046                            s->i2c_data[i] = i2c_recv(s->i2c_bus);
   1047                        } else if (i2c_send(s->i2c_bus, s->i2c_data[i]) < 0) {
   1048                            s->i2c_status |= SM501_I2C_STATUS_ERROR;
   1049                            return;
   1050                        }
   1051                    }
   1052                    if (i) {
   1053                        s->i2c_status = SM501_I2C_STATUS_COMPLETE;
   1054                    }
   1055                }
   1056            } else {
   1057                i2c_end_transfer(s->i2c_bus);
   1058                s->i2c_status &= ~SM501_I2C_STATUS_ERROR;
   1059            }
   1060        }
   1061        break;
   1062    case SM501_I2C_RESET:
   1063        if ((value & SM501_I2C_RESET_ERROR) == 0) {
   1064            s->i2c_status &= ~SM501_I2C_STATUS_ERROR;
   1065        }
   1066        break;
   1067    case SM501_I2C_SLAVE_ADDRESS:
   1068        s->i2c_addr = value & 0xff;
   1069        break;
   1070    case SM501_I2C_DATA ... SM501_I2C_DATA + 15:
   1071        s->i2c_data[addr - SM501_I2C_DATA] = value & 0xff;
   1072        break;
   1073    default:
   1074        qemu_log_mask(LOG_UNIMP, "sm501 i2c : not implemented register write. "
   1075                      "addr=0x%" HWADDR_PRIx " val=%" PRIx64 "\n", addr, value);
   1076    }
   1077}
   1078
   1079static const MemoryRegionOps sm501_i2c_ops = {
   1080    .read = sm501_i2c_read,
   1081    .write = sm501_i2c_write,
   1082    .valid = {
   1083        .min_access_size = 1,
   1084        .max_access_size = 1,
   1085    },
   1086    .impl = {
   1087        .min_access_size = 1,
   1088        .max_access_size = 1,
   1089    },
   1090    .endianness = DEVICE_LITTLE_ENDIAN,
   1091};
   1092
   1093static uint32_t sm501_palette_read(void *opaque, hwaddr addr)
   1094{
   1095    SM501State *s = (SM501State *)opaque;
   1096
   1097    trace_sm501_palette_read((uint32_t)addr);
   1098
   1099    /* TODO : consider BYTE/WORD access */
   1100    /* TODO : consider endian */
   1101
   1102    assert(range_covers_byte(0, 0x400 * 3, addr));
   1103    return *(uint32_t *)&s->dc_palette[addr];
   1104}
   1105
   1106static void sm501_palette_write(void *opaque, hwaddr addr,
   1107                                uint32_t value)
   1108{
   1109    SM501State *s = (SM501State *)opaque;
   1110
   1111    trace_sm501_palette_write((uint32_t)addr, value);
   1112
   1113    /* TODO : consider BYTE/WORD access */
   1114    /* TODO : consider endian */
   1115
   1116    assert(range_covers_byte(0, 0x400 * 3, addr));
   1117    *(uint32_t *)&s->dc_palette[addr] = value;
   1118    s->do_full_update = true;
   1119}
   1120
   1121static uint64_t sm501_disp_ctrl_read(void *opaque, hwaddr addr,
   1122                                     unsigned size)
   1123{
   1124    SM501State *s = (SM501State *)opaque;
   1125    uint32_t ret = 0;
   1126
   1127    switch (addr) {
   1128
   1129    case SM501_DC_PANEL_CONTROL:
   1130        ret = s->dc_panel_control;
   1131        break;
   1132    case SM501_DC_PANEL_PANNING_CONTROL:
   1133        ret = s->dc_panel_panning_control;
   1134        break;
   1135    case SM501_DC_PANEL_COLOR_KEY:
   1136        /* Not implemented yet */
   1137        break;
   1138    case SM501_DC_PANEL_FB_ADDR:
   1139        ret = s->dc_panel_fb_addr;
   1140        break;
   1141    case SM501_DC_PANEL_FB_OFFSET:
   1142        ret = s->dc_panel_fb_offset;
   1143        break;
   1144    case SM501_DC_PANEL_FB_WIDTH:
   1145        ret = s->dc_panel_fb_width;
   1146        break;
   1147    case SM501_DC_PANEL_FB_HEIGHT:
   1148        ret = s->dc_panel_fb_height;
   1149        break;
   1150    case SM501_DC_PANEL_TL_LOC:
   1151        ret = s->dc_panel_tl_location;
   1152        break;
   1153    case SM501_DC_PANEL_BR_LOC:
   1154        ret = s->dc_panel_br_location;
   1155        break;
   1156
   1157    case SM501_DC_PANEL_H_TOT:
   1158        ret = s->dc_panel_h_total;
   1159        break;
   1160    case SM501_DC_PANEL_H_SYNC:
   1161        ret = s->dc_panel_h_sync;
   1162        break;
   1163    case SM501_DC_PANEL_V_TOT:
   1164        ret = s->dc_panel_v_total;
   1165        break;
   1166    case SM501_DC_PANEL_V_SYNC:
   1167        ret = s->dc_panel_v_sync;
   1168        break;
   1169
   1170    case SM501_DC_PANEL_HWC_ADDR:
   1171        ret = s->dc_panel_hwc_addr;
   1172        break;
   1173    case SM501_DC_PANEL_HWC_LOC:
   1174        ret = s->dc_panel_hwc_location;
   1175        break;
   1176    case SM501_DC_PANEL_HWC_COLOR_1_2:
   1177        ret = s->dc_panel_hwc_color_1_2;
   1178        break;
   1179    case SM501_DC_PANEL_HWC_COLOR_3:
   1180        ret = s->dc_panel_hwc_color_3;
   1181        break;
   1182
   1183    case SM501_DC_VIDEO_CONTROL:
   1184        ret = s->dc_video_control;
   1185        break;
   1186
   1187    case SM501_DC_CRT_CONTROL:
   1188        ret = s->dc_crt_control;
   1189        break;
   1190    case SM501_DC_CRT_FB_ADDR:
   1191        ret = s->dc_crt_fb_addr;
   1192        break;
   1193    case SM501_DC_CRT_FB_OFFSET:
   1194        ret = s->dc_crt_fb_offset;
   1195        break;
   1196    case SM501_DC_CRT_H_TOT:
   1197        ret = s->dc_crt_h_total;
   1198        break;
   1199    case SM501_DC_CRT_H_SYNC:
   1200        ret = s->dc_crt_h_sync;
   1201        break;
   1202    case SM501_DC_CRT_V_TOT:
   1203        ret = s->dc_crt_v_total;
   1204        break;
   1205    case SM501_DC_CRT_V_SYNC:
   1206        ret = s->dc_crt_v_sync;
   1207        break;
   1208
   1209    case SM501_DC_CRT_HWC_ADDR:
   1210        ret = s->dc_crt_hwc_addr;
   1211        break;
   1212    case SM501_DC_CRT_HWC_LOC:
   1213        ret = s->dc_crt_hwc_location;
   1214        break;
   1215    case SM501_DC_CRT_HWC_COLOR_1_2:
   1216        ret = s->dc_crt_hwc_color_1_2;
   1217        break;
   1218    case SM501_DC_CRT_HWC_COLOR_3:
   1219        ret = s->dc_crt_hwc_color_3;
   1220        break;
   1221
   1222    case SM501_DC_PANEL_PALETTE ... SM501_DC_PANEL_PALETTE + 0x400 * 3 - 4:
   1223        ret = sm501_palette_read(opaque, addr - SM501_DC_PANEL_PALETTE);
   1224        break;
   1225
   1226    default:
   1227        qemu_log_mask(LOG_UNIMP, "sm501: not implemented disp ctrl register "
   1228                      "read. addr=%" HWADDR_PRIx "\n", addr);
   1229    }
   1230    trace_sm501_disp_ctrl_read((uint32_t)addr, ret);
   1231    return ret;
   1232}
   1233
   1234static void sm501_disp_ctrl_write(void *opaque, hwaddr addr,
   1235                                  uint64_t value, unsigned size)
   1236{
   1237    SM501State *s = (SM501State *)opaque;
   1238
   1239    trace_sm501_disp_ctrl_write((uint32_t)addr, (uint32_t)value);
   1240    switch (addr) {
   1241    case SM501_DC_PANEL_CONTROL:
   1242        s->dc_panel_control = value & 0x0FFF73FF;
   1243        break;
   1244    case SM501_DC_PANEL_PANNING_CONTROL:
   1245        s->dc_panel_panning_control = value & 0xFF3FFF3F;
   1246        break;
   1247    case SM501_DC_PANEL_COLOR_KEY:
   1248        /* Not implemented yet */
   1249        break;
   1250    case SM501_DC_PANEL_FB_ADDR:
   1251        s->dc_panel_fb_addr = value & 0x8FFFFFF0;
   1252        if (value & 0x8000000) {
   1253            qemu_log_mask(LOG_UNIMP, "Panel external memory not supported\n");
   1254        }
   1255        s->do_full_update = true;
   1256        break;
   1257    case SM501_DC_PANEL_FB_OFFSET:
   1258        s->dc_panel_fb_offset = value & 0x3FF03FF0;
   1259        break;
   1260    case SM501_DC_PANEL_FB_WIDTH:
   1261        s->dc_panel_fb_width = value & 0x0FFF0FFF;
   1262        break;
   1263    case SM501_DC_PANEL_FB_HEIGHT:
   1264        s->dc_panel_fb_height = value & 0x0FFF0FFF;
   1265        break;
   1266    case SM501_DC_PANEL_TL_LOC:
   1267        s->dc_panel_tl_location = value & 0x07FF07FF;
   1268        break;
   1269    case SM501_DC_PANEL_BR_LOC:
   1270        s->dc_panel_br_location = value & 0x07FF07FF;
   1271        break;
   1272
   1273    case SM501_DC_PANEL_H_TOT:
   1274        s->dc_panel_h_total = value & 0x0FFF0FFF;
   1275        break;
   1276    case SM501_DC_PANEL_H_SYNC:
   1277        s->dc_panel_h_sync = value & 0x00FF0FFF;
   1278        break;
   1279    case SM501_DC_PANEL_V_TOT:
   1280        s->dc_panel_v_total = value & 0x0FFF0FFF;
   1281        break;
   1282    case SM501_DC_PANEL_V_SYNC:
   1283        s->dc_panel_v_sync = value & 0x003F0FFF;
   1284        break;
   1285
   1286    case SM501_DC_PANEL_HWC_ADDR:
   1287        value &= 0x8FFFFFF0;
   1288        if (value != s->dc_panel_hwc_addr) {
   1289            hwc_invalidate(s, 0);
   1290            s->dc_panel_hwc_addr = value;
   1291        }
   1292        break;
   1293    case SM501_DC_PANEL_HWC_LOC:
   1294        value &= 0x0FFF0FFF;
   1295        if (value != s->dc_panel_hwc_location) {
   1296            hwc_invalidate(s, 0);
   1297            s->dc_panel_hwc_location = value;
   1298        }
   1299        break;
   1300    case SM501_DC_PANEL_HWC_COLOR_1_2:
   1301        s->dc_panel_hwc_color_1_2 = value;
   1302        break;
   1303    case SM501_DC_PANEL_HWC_COLOR_3:
   1304        s->dc_panel_hwc_color_3 = value & 0x0000FFFF;
   1305        break;
   1306
   1307    case SM501_DC_VIDEO_CONTROL:
   1308        s->dc_video_control = value & 0x00037FFF;
   1309        break;
   1310
   1311    case SM501_DC_CRT_CONTROL:
   1312        s->dc_crt_control = value & 0x0003FFFF;
   1313        break;
   1314    case SM501_DC_CRT_FB_ADDR:
   1315        s->dc_crt_fb_addr = value & 0x8FFFFFF0;
   1316        if (value & 0x8000000) {
   1317            qemu_log_mask(LOG_UNIMP, "CRT external memory not supported\n");
   1318        }
   1319        s->do_full_update = true;
   1320        break;
   1321    case SM501_DC_CRT_FB_OFFSET:
   1322        s->dc_crt_fb_offset = value & 0x3FF03FF0;
   1323        break;
   1324    case SM501_DC_CRT_H_TOT:
   1325        s->dc_crt_h_total = value & 0x0FFF0FFF;
   1326        break;
   1327    case SM501_DC_CRT_H_SYNC:
   1328        s->dc_crt_h_sync = value & 0x00FF0FFF;
   1329        break;
   1330    case SM501_DC_CRT_V_TOT:
   1331        s->dc_crt_v_total = value & 0x0FFF0FFF;
   1332        break;
   1333    case SM501_DC_CRT_V_SYNC:
   1334        s->dc_crt_v_sync = value & 0x003F0FFF;
   1335        break;
   1336
   1337    case SM501_DC_CRT_HWC_ADDR:
   1338        value &= 0x8FFFFFF0;
   1339        if (value != s->dc_crt_hwc_addr) {
   1340            hwc_invalidate(s, 1);
   1341            s->dc_crt_hwc_addr = value;
   1342        }
   1343        break;
   1344    case SM501_DC_CRT_HWC_LOC:
   1345        value &= 0x0FFF0FFF;
   1346        if (value != s->dc_crt_hwc_location) {
   1347            hwc_invalidate(s, 1);
   1348            s->dc_crt_hwc_location = value;
   1349        }
   1350        break;
   1351    case SM501_DC_CRT_HWC_COLOR_1_2:
   1352        s->dc_crt_hwc_color_1_2 = value;
   1353        break;
   1354    case SM501_DC_CRT_HWC_COLOR_3:
   1355        s->dc_crt_hwc_color_3 = value & 0x0000FFFF;
   1356        break;
   1357
   1358    case SM501_DC_PANEL_PALETTE ... SM501_DC_PANEL_PALETTE + 0x400 * 3 - 4:
   1359        sm501_palette_write(opaque, addr - SM501_DC_PANEL_PALETTE, value);
   1360        break;
   1361
   1362    default:
   1363        qemu_log_mask(LOG_UNIMP, "sm501: not implemented disp ctrl register "
   1364                      "write. addr=%" HWADDR_PRIx
   1365                      ", val=%" PRIx64 "\n", addr, value);
   1366    }
   1367}
   1368
   1369static const MemoryRegionOps sm501_disp_ctrl_ops = {
   1370    .read = sm501_disp_ctrl_read,
   1371    .write = sm501_disp_ctrl_write,
   1372    .valid = {
   1373        .min_access_size = 4,
   1374        .max_access_size = 4,
   1375    },
   1376    .endianness = DEVICE_LITTLE_ENDIAN,
   1377};
   1378
   1379static uint64_t sm501_2d_engine_read(void *opaque, hwaddr addr,
   1380                                     unsigned size)
   1381{
   1382    SM501State *s = (SM501State *)opaque;
   1383    uint32_t ret = 0;
   1384
   1385    switch (addr) {
   1386    case SM501_2D_SOURCE:
   1387        ret = s->twoD_source;
   1388        break;
   1389    case SM501_2D_DESTINATION:
   1390        ret = s->twoD_destination;
   1391        break;
   1392    case SM501_2D_DIMENSION:
   1393        ret = s->twoD_dimension;
   1394        break;
   1395    case SM501_2D_CONTROL:
   1396        ret = s->twoD_control;
   1397        break;
   1398    case SM501_2D_PITCH:
   1399        ret = s->twoD_pitch;
   1400        break;
   1401    case SM501_2D_FOREGROUND:
   1402        ret = s->twoD_foreground;
   1403        break;
   1404    case SM501_2D_BACKGROUND:
   1405        ret = s->twoD_background;
   1406        break;
   1407    case SM501_2D_STRETCH:
   1408        ret = s->twoD_stretch;
   1409        break;
   1410    case SM501_2D_COLOR_COMPARE:
   1411        ret = s->twoD_color_compare;
   1412        break;
   1413    case SM501_2D_COLOR_COMPARE_MASK:
   1414        ret = s->twoD_color_compare_mask;
   1415        break;
   1416    case SM501_2D_MASK:
   1417        ret = s->twoD_mask;
   1418        break;
   1419    case SM501_2D_CLIP_TL:
   1420        ret = s->twoD_clip_tl;
   1421        break;
   1422    case SM501_2D_CLIP_BR:
   1423        ret = s->twoD_clip_br;
   1424        break;
   1425    case SM501_2D_MONO_PATTERN_LOW:
   1426        ret = s->twoD_mono_pattern_low;
   1427        break;
   1428    case SM501_2D_MONO_PATTERN_HIGH:
   1429        ret = s->twoD_mono_pattern_high;
   1430        break;
   1431    case SM501_2D_WINDOW_WIDTH:
   1432        ret = s->twoD_window_width;
   1433        break;
   1434    case SM501_2D_SOURCE_BASE:
   1435        ret = s->twoD_source_base;
   1436        break;
   1437    case SM501_2D_DESTINATION_BASE:
   1438        ret = s->twoD_destination_base;
   1439        break;
   1440    case SM501_2D_ALPHA:
   1441        ret = s->twoD_alpha;
   1442        break;
   1443    case SM501_2D_WRAP:
   1444        ret = s->twoD_wrap;
   1445        break;
   1446    case SM501_2D_STATUS:
   1447        ret = 0; /* Should return interrupt status */
   1448        break;
   1449    default:
   1450        qemu_log_mask(LOG_UNIMP, "sm501: not implemented disp ctrl register "
   1451                      "read. addr=%" HWADDR_PRIx "\n", addr);
   1452    }
   1453    trace_sm501_2d_engine_read((uint32_t)addr, ret);
   1454    return ret;
   1455}
   1456
   1457static void sm501_2d_engine_write(void *opaque, hwaddr addr,
   1458                                  uint64_t value, unsigned size)
   1459{
   1460    SM501State *s = (SM501State *)opaque;
   1461
   1462    trace_sm501_2d_engine_write((uint32_t)addr, (uint32_t)value);
   1463    switch (addr) {
   1464    case SM501_2D_SOURCE:
   1465        s->twoD_source = value;
   1466        break;
   1467    case SM501_2D_DESTINATION:
   1468        s->twoD_destination = value;
   1469        break;
   1470    case SM501_2D_DIMENSION:
   1471        s->twoD_dimension = value;
   1472        break;
   1473    case SM501_2D_CONTROL:
   1474        s->twoD_control = value;
   1475
   1476        /* do 2d operation if start flag is set. */
   1477        if (value & 0x80000000) {
   1478            sm501_2d_operation(s);
   1479            s->twoD_control &= ~0x80000000; /* start flag down */
   1480        }
   1481
   1482        break;
   1483    case SM501_2D_PITCH:
   1484        s->twoD_pitch = value;
   1485        break;
   1486    case SM501_2D_FOREGROUND:
   1487        s->twoD_foreground = value;
   1488        break;
   1489    case SM501_2D_BACKGROUND:
   1490        s->twoD_background = value;
   1491        break;
   1492    case SM501_2D_STRETCH:
   1493        if (((value >> 20) & 3) == 3) {
   1494            value &= ~BIT(20);
   1495        }
   1496        s->twoD_stretch = value;
   1497        break;
   1498    case SM501_2D_COLOR_COMPARE:
   1499        s->twoD_color_compare = value;
   1500        break;
   1501    case SM501_2D_COLOR_COMPARE_MASK:
   1502        s->twoD_color_compare_mask = value;
   1503        break;
   1504    case SM501_2D_MASK:
   1505        s->twoD_mask = value;
   1506        break;
   1507    case SM501_2D_CLIP_TL:
   1508        s->twoD_clip_tl = value;
   1509        break;
   1510    case SM501_2D_CLIP_BR:
   1511        s->twoD_clip_br = value;
   1512        break;
   1513    case SM501_2D_MONO_PATTERN_LOW:
   1514        s->twoD_mono_pattern_low = value;
   1515        break;
   1516    case SM501_2D_MONO_PATTERN_HIGH:
   1517        s->twoD_mono_pattern_high = value;
   1518        break;
   1519    case SM501_2D_WINDOW_WIDTH:
   1520        s->twoD_window_width = value;
   1521        break;
   1522    case SM501_2D_SOURCE_BASE:
   1523        s->twoD_source_base = value;
   1524        break;
   1525    case SM501_2D_DESTINATION_BASE:
   1526        s->twoD_destination_base = value;
   1527        break;
   1528    case SM501_2D_ALPHA:
   1529        s->twoD_alpha = value;
   1530        break;
   1531    case SM501_2D_WRAP:
   1532        s->twoD_wrap = value;
   1533        break;
   1534    case SM501_2D_STATUS:
   1535        /* ignored, writing 0 should clear interrupt status */
   1536        break;
   1537    default:
   1538        qemu_log_mask(LOG_UNIMP, "sm501: not implemented 2d engine register "
   1539                      "write. addr=%" HWADDR_PRIx
   1540                      ", val=%" PRIx64 "\n", addr, value);
   1541    }
   1542}
   1543
   1544static const MemoryRegionOps sm501_2d_engine_ops = {
   1545    .read = sm501_2d_engine_read,
   1546    .write = sm501_2d_engine_write,
   1547    .valid = {
   1548        .min_access_size = 4,
   1549        .max_access_size = 4,
   1550    },
   1551    .endianness = DEVICE_LITTLE_ENDIAN,
   1552};
   1553
   1554/* draw line functions for all console modes */
   1555
   1556typedef void draw_line_func(uint8_t *d, const uint8_t *s,
   1557                            int width, const uint32_t *pal);
   1558
   1559typedef void draw_hwc_line_func(uint8_t *d, const uint8_t *s,
   1560                                int width, const uint8_t *palette,
   1561                                int c_x, int c_y);
   1562
   1563static void draw_line8_32(uint8_t *d, const uint8_t *s, int width,
   1564                          const uint32_t *pal)
   1565{
   1566    uint8_t v, r, g, b;
   1567    do {
   1568        v = ldub_p(s);
   1569        r = (pal[v] >> 16) & 0xff;
   1570        g = (pal[v] >>  8) & 0xff;
   1571        b = (pal[v] >>  0) & 0xff;
   1572        *(uint32_t *)d = rgb_to_pixel32(r, g, b);
   1573        s++;
   1574        d += 4;
   1575    } while (--width != 0);
   1576}
   1577
   1578static void draw_line16_32(uint8_t *d, const uint8_t *s, int width,
   1579                           const uint32_t *pal)
   1580{
   1581    uint16_t rgb565;
   1582    uint8_t r, g, b;
   1583
   1584    do {
   1585        rgb565 = lduw_le_p(s);
   1586        r = (rgb565 >> 8) & 0xf8;
   1587        g = (rgb565 >> 3) & 0xfc;
   1588        b = (rgb565 << 3) & 0xf8;
   1589        *(uint32_t *)d = rgb_to_pixel32(r, g, b);
   1590        s += 2;
   1591        d += 4;
   1592    } while (--width != 0);
   1593}
   1594
   1595static void draw_line32_32(uint8_t *d, const uint8_t *s, int width,
   1596                           const uint32_t *pal)
   1597{
   1598    uint8_t r, g, b;
   1599
   1600    do {
   1601        r = s[2];
   1602        g = s[1];
   1603        b = s[0];
   1604        *(uint32_t *)d = rgb_to_pixel32(r, g, b);
   1605        s += 4;
   1606        d += 4;
   1607    } while (--width != 0);
   1608}
   1609
   1610/**
   1611 * Draw hardware cursor image on the given line.
   1612 */
   1613static void draw_hwc_line_32(uint8_t *d, const uint8_t *s, int width,
   1614                             const uint8_t *palette, int c_x, int c_y)
   1615{
   1616    int i;
   1617    uint8_t r, g, b, v, bitset = 0;
   1618
   1619    /* get cursor position */
   1620    assert(0 <= c_y && c_y < SM501_HWC_HEIGHT);
   1621    s += SM501_HWC_WIDTH * c_y / 4;  /* 4 pixels per byte */
   1622    d += c_x * 4;
   1623
   1624    for (i = 0; i < SM501_HWC_WIDTH && c_x + i < width; i++) {
   1625        /* get pixel value */
   1626        if (i % 4 == 0) {
   1627            bitset = ldub_p(s);
   1628            s++;
   1629        }
   1630        v = bitset & 3;
   1631        bitset >>= 2;
   1632
   1633        /* write pixel */
   1634        if (v) {
   1635            v--;
   1636            r = palette[v * 3 + 0];
   1637            g = palette[v * 3 + 1];
   1638            b = palette[v * 3 + 2];
   1639            *(uint32_t *)d = rgb_to_pixel32(r, g, b);
   1640        }
   1641        d += 4;
   1642    }
   1643}
   1644
   1645static void sm501_update_display(void *opaque)
   1646{
   1647    SM501State *s = (SM501State *)opaque;
   1648    DisplaySurface *surface = qemu_console_surface(s->con);
   1649    DirtyBitmapSnapshot *snap;
   1650    int y, c_x = 0, c_y = 0;
   1651    int crt = (s->dc_crt_control & SM501_DC_CRT_CONTROL_SEL) ? 1 : 0;
   1652    int width = get_width(s, crt);
   1653    int height = get_height(s, crt);
   1654    int src_bpp = get_bpp(s, crt);
   1655    int dst_bpp = surface_bytes_per_pixel(surface);
   1656    draw_line_func *draw_line = NULL;
   1657    draw_hwc_line_func *draw_hwc_line = NULL;
   1658    int full_update = 0;
   1659    int y_start = -1;
   1660    ram_addr_t offset;
   1661    uint32_t *palette;
   1662    uint8_t hwc_palette[3 * 3];
   1663    uint8_t *hwc_src = NULL;
   1664
   1665    assert(dst_bpp == 4); /* Output is always 32-bit RGB */
   1666
   1667    if (!((crt ? s->dc_crt_control : s->dc_panel_control)
   1668          & SM501_DC_CRT_CONTROL_ENABLE)) {
   1669        return;
   1670    }
   1671
   1672    palette = (uint32_t *)(crt ? &s->dc_palette[SM501_DC_CRT_PALETTE -
   1673                                                SM501_DC_PANEL_PALETTE]
   1674                               : &s->dc_palette[0]);
   1675
   1676    /* choose draw_line function */
   1677    switch (src_bpp) {
   1678    case 1:
   1679        draw_line = draw_line8_32;
   1680        break;
   1681    case 2:
   1682        draw_line = draw_line16_32;
   1683        break;
   1684    case 4:
   1685        draw_line = draw_line32_32;
   1686        break;
   1687    default:
   1688        qemu_log_mask(LOG_GUEST_ERROR, "sm501: update display"
   1689                      "invalid control register value.\n");
   1690        return;
   1691    }
   1692
   1693    /* set up to draw hardware cursor */
   1694    if (is_hwc_enabled(s, crt)) {
   1695        /* choose cursor draw line function */
   1696        draw_hwc_line = draw_hwc_line_32;
   1697        hwc_src = get_hwc_address(s, crt);
   1698        c_x = get_hwc_x(s, crt);
   1699        c_y = get_hwc_y(s, crt);
   1700        get_hwc_palette(s, crt, hwc_palette);
   1701    }
   1702
   1703    /* adjust console size */
   1704    if (s->last_width != width || s->last_height != height) {
   1705        qemu_console_resize(s->con, width, height);
   1706        surface = qemu_console_surface(s->con);
   1707        s->last_width = width;
   1708        s->last_height = height;
   1709        full_update = 1;
   1710    }
   1711
   1712    /* someone else requested a full update */
   1713    if (s->do_full_update) {
   1714        s->do_full_update = false;
   1715        full_update = 1;
   1716    }
   1717
   1718    /* draw each line according to conditions */
   1719    offset = get_fb_addr(s, crt);
   1720    snap = memory_region_snapshot_and_clear_dirty(&s->local_mem_region,
   1721              offset, width * height * src_bpp, DIRTY_MEMORY_VGA);
   1722    for (y = 0; y < height; y++, offset += width * src_bpp) {
   1723        int update, update_hwc;
   1724
   1725        /* check if hardware cursor is enabled and we're within its range */
   1726        update_hwc = draw_hwc_line && c_y <= y && y < c_y + SM501_HWC_HEIGHT;
   1727        update = full_update || update_hwc;
   1728        /* check dirty flags for each line */
   1729        update |= memory_region_snapshot_get_dirty(&s->local_mem_region, snap,
   1730                                                   offset, width * src_bpp);
   1731
   1732        /* draw line and change status */
   1733        if (update) {
   1734            uint8_t *d = surface_data(surface);
   1735            d +=  y * width * dst_bpp;
   1736
   1737            /* draw graphics layer */
   1738            draw_line(d, s->local_mem + offset, width, palette);
   1739
   1740            /* draw hardware cursor */
   1741            if (update_hwc) {
   1742                draw_hwc_line(d, hwc_src, width, hwc_palette, c_x, y - c_y);
   1743            }
   1744
   1745            if (y_start < 0) {
   1746                y_start = y;
   1747            }
   1748        } else {
   1749            if (y_start >= 0) {
   1750                /* flush to display */
   1751                dpy_gfx_update(s->con, 0, y_start, width, y - y_start);
   1752                y_start = -1;
   1753            }
   1754        }
   1755    }
   1756    g_free(snap);
   1757
   1758    /* complete flush to display */
   1759    if (y_start >= 0) {
   1760        dpy_gfx_update(s->con, 0, y_start, width, y - y_start);
   1761    }
   1762}
   1763
   1764static const GraphicHwOps sm501_ops = {
   1765    .gfx_update  = sm501_update_display,
   1766};
   1767
   1768static void sm501_reset(SM501State *s)
   1769{
   1770    s->system_control = 0x00100000; /* 2D engine FIFO empty */
   1771    /* Bits 17 (SH), 7 (CDR), 6:5 (Test), 2:0 (Bus) are all supposed
   1772     * to be determined at reset by GPIO lines which set config bits.
   1773     * We hardwire them:
   1774     *  SH = 0 : Hitachi Ready Polarity == Active Low
   1775     *  CDR = 0 : do not reset clock divider
   1776     *  TEST = 0 : Normal mode (not testing the silicon)
   1777     *  BUS = 0 : Hitachi SH3/SH4
   1778     */
   1779    s->misc_control = SM501_MISC_DAC_POWER;
   1780    s->gpio_31_0_control = 0;
   1781    s->gpio_63_32_control = 0;
   1782    s->dram_control = 0;
   1783    s->arbitration_control = 0x05146732;
   1784    s->irq_mask = 0;
   1785    s->misc_timing = 0;
   1786    s->power_mode_control = 0;
   1787    s->i2c_byte_count = 0;
   1788    s->i2c_status = 0;
   1789    s->i2c_addr = 0;
   1790    memset(s->i2c_data, 0, 16);
   1791    s->dc_panel_control = 0x00010000; /* FIFO level 3 */
   1792    s->dc_video_control = 0;
   1793    s->dc_crt_control = 0x00010000;
   1794    s->twoD_source = 0;
   1795    s->twoD_destination = 0;
   1796    s->twoD_dimension = 0;
   1797    s->twoD_control = 0;
   1798    s->twoD_pitch = 0;
   1799    s->twoD_foreground = 0;
   1800    s->twoD_background = 0;
   1801    s->twoD_stretch = 0;
   1802    s->twoD_color_compare = 0;
   1803    s->twoD_color_compare_mask = 0;
   1804    s->twoD_mask = 0;
   1805    s->twoD_clip_tl = 0;
   1806    s->twoD_clip_br = 0;
   1807    s->twoD_mono_pattern_low = 0;
   1808    s->twoD_mono_pattern_high = 0;
   1809    s->twoD_window_width = 0;
   1810    s->twoD_source_base = 0;
   1811    s->twoD_destination_base = 0;
   1812    s->twoD_alpha = 0;
   1813    s->twoD_wrap = 0;
   1814}
   1815
   1816static void sm501_init(SM501State *s, DeviceState *dev,
   1817                       uint32_t local_mem_bytes)
   1818{
   1819    s->local_mem_size_index = get_local_mem_size_index(local_mem_bytes);
   1820
   1821    /* local memory */
   1822    memory_region_init_ram(&s->local_mem_region, OBJECT(dev), "sm501.local",
   1823                           get_local_mem_size(s), &error_fatal);
   1824    memory_region_set_log(&s->local_mem_region, true, DIRTY_MEMORY_VGA);
   1825    s->local_mem = memory_region_get_ram_ptr(&s->local_mem_region);
   1826
   1827    /* i2c */
   1828    s->i2c_bus = i2c_init_bus(dev, "sm501.i2c");
   1829    /* ddc */
   1830    I2CDDCState *ddc = I2CDDC(qdev_new(TYPE_I2CDDC));
   1831    i2c_slave_set_address(I2C_SLAVE(ddc), 0x50);
   1832    qdev_realize_and_unref(DEVICE(ddc), BUS(s->i2c_bus), &error_abort);
   1833
   1834    /* mmio */
   1835    memory_region_init(&s->mmio_region, OBJECT(dev), "sm501.mmio", MMIO_SIZE);
   1836    memory_region_init_io(&s->system_config_region, OBJECT(dev),
   1837                          &sm501_system_config_ops, s,
   1838                          "sm501-system-config", 0x6c);
   1839    memory_region_add_subregion(&s->mmio_region, SM501_SYS_CONFIG,
   1840                                &s->system_config_region);
   1841    memory_region_init_io(&s->i2c_region, OBJECT(dev), &sm501_i2c_ops, s,
   1842                          "sm501-i2c", 0x14);
   1843    memory_region_add_subregion(&s->mmio_region, SM501_I2C, &s->i2c_region);
   1844    memory_region_init_io(&s->disp_ctrl_region, OBJECT(dev),
   1845                          &sm501_disp_ctrl_ops, s,
   1846                          "sm501-disp-ctrl", 0x1000);
   1847    memory_region_add_subregion(&s->mmio_region, SM501_DC,
   1848                                &s->disp_ctrl_region);
   1849    memory_region_init_io(&s->twoD_engine_region, OBJECT(dev),
   1850                          &sm501_2d_engine_ops, s,
   1851                          "sm501-2d-engine", 0x54);
   1852    memory_region_add_subregion(&s->mmio_region, SM501_2D_ENGINE,
   1853                                &s->twoD_engine_region);
   1854
   1855    /* create qemu graphic console */
   1856    s->con = graphic_console_init(dev, 0, &sm501_ops, s);
   1857}
   1858
   1859static const VMStateDescription vmstate_sm501_state = {
   1860    .name = "sm501-state",
   1861    .version_id = 1,
   1862    .minimum_version_id = 1,
   1863    .fields = (VMStateField[]) {
   1864        VMSTATE_UINT32(local_mem_size_index, SM501State),
   1865        VMSTATE_UINT32(system_control, SM501State),
   1866        VMSTATE_UINT32(misc_control, SM501State),
   1867        VMSTATE_UINT32(gpio_31_0_control, SM501State),
   1868        VMSTATE_UINT32(gpio_63_32_control, SM501State),
   1869        VMSTATE_UINT32(dram_control, SM501State),
   1870        VMSTATE_UINT32(arbitration_control, SM501State),
   1871        VMSTATE_UINT32(irq_mask, SM501State),
   1872        VMSTATE_UINT32(misc_timing, SM501State),
   1873        VMSTATE_UINT32(power_mode_control, SM501State),
   1874        VMSTATE_UINT32(uart0_ier, SM501State),
   1875        VMSTATE_UINT32(uart0_lcr, SM501State),
   1876        VMSTATE_UINT32(uart0_mcr, SM501State),
   1877        VMSTATE_UINT32(uart0_scr, SM501State),
   1878        VMSTATE_UINT8_ARRAY(dc_palette, SM501State, DC_PALETTE_ENTRIES),
   1879        VMSTATE_UINT32(dc_panel_control, SM501State),
   1880        VMSTATE_UINT32(dc_panel_panning_control, SM501State),
   1881        VMSTATE_UINT32(dc_panel_fb_addr, SM501State),
   1882        VMSTATE_UINT32(dc_panel_fb_offset, SM501State),
   1883        VMSTATE_UINT32(dc_panel_fb_width, SM501State),
   1884        VMSTATE_UINT32(dc_panel_fb_height, SM501State),
   1885        VMSTATE_UINT32(dc_panel_tl_location, SM501State),
   1886        VMSTATE_UINT32(dc_panel_br_location, SM501State),
   1887        VMSTATE_UINT32(dc_panel_h_total, SM501State),
   1888        VMSTATE_UINT32(dc_panel_h_sync, SM501State),
   1889        VMSTATE_UINT32(dc_panel_v_total, SM501State),
   1890        VMSTATE_UINT32(dc_panel_v_sync, SM501State),
   1891        VMSTATE_UINT32(dc_panel_hwc_addr, SM501State),
   1892        VMSTATE_UINT32(dc_panel_hwc_location, SM501State),
   1893        VMSTATE_UINT32(dc_panel_hwc_color_1_2, SM501State),
   1894        VMSTATE_UINT32(dc_panel_hwc_color_3, SM501State),
   1895        VMSTATE_UINT32(dc_video_control, SM501State),
   1896        VMSTATE_UINT32(dc_crt_control, SM501State),
   1897        VMSTATE_UINT32(dc_crt_fb_addr, SM501State),
   1898        VMSTATE_UINT32(dc_crt_fb_offset, SM501State),
   1899        VMSTATE_UINT32(dc_crt_h_total, SM501State),
   1900        VMSTATE_UINT32(dc_crt_h_sync, SM501State),
   1901        VMSTATE_UINT32(dc_crt_v_total, SM501State),
   1902        VMSTATE_UINT32(dc_crt_v_sync, SM501State),
   1903        VMSTATE_UINT32(dc_crt_hwc_addr, SM501State),
   1904        VMSTATE_UINT32(dc_crt_hwc_location, SM501State),
   1905        VMSTATE_UINT32(dc_crt_hwc_color_1_2, SM501State),
   1906        VMSTATE_UINT32(dc_crt_hwc_color_3, SM501State),
   1907        VMSTATE_UINT32(twoD_source, SM501State),
   1908        VMSTATE_UINT32(twoD_destination, SM501State),
   1909        VMSTATE_UINT32(twoD_dimension, SM501State),
   1910        VMSTATE_UINT32(twoD_control, SM501State),
   1911        VMSTATE_UINT32(twoD_pitch, SM501State),
   1912        VMSTATE_UINT32(twoD_foreground, SM501State),
   1913        VMSTATE_UINT32(twoD_background, SM501State),
   1914        VMSTATE_UINT32(twoD_stretch, SM501State),
   1915        VMSTATE_UINT32(twoD_color_compare, SM501State),
   1916        VMSTATE_UINT32(twoD_color_compare_mask, SM501State),
   1917        VMSTATE_UINT32(twoD_mask, SM501State),
   1918        VMSTATE_UINT32(twoD_clip_tl, SM501State),
   1919        VMSTATE_UINT32(twoD_clip_br, SM501State),
   1920        VMSTATE_UINT32(twoD_mono_pattern_low, SM501State),
   1921        VMSTATE_UINT32(twoD_mono_pattern_high, SM501State),
   1922        VMSTATE_UINT32(twoD_window_width, SM501State),
   1923        VMSTATE_UINT32(twoD_source_base, SM501State),
   1924        VMSTATE_UINT32(twoD_destination_base, SM501State),
   1925        VMSTATE_UINT32(twoD_alpha, SM501State),
   1926        VMSTATE_UINT32(twoD_wrap, SM501State),
   1927        /* Added in version 2 */
   1928        VMSTATE_UINT8(i2c_byte_count, SM501State),
   1929        VMSTATE_UINT8(i2c_status, SM501State),
   1930        VMSTATE_UINT8(i2c_addr, SM501State),
   1931        VMSTATE_UINT8_ARRAY(i2c_data, SM501State, 16),
   1932        VMSTATE_END_OF_LIST()
   1933     }
   1934};
   1935
   1936#define TYPE_SYSBUS_SM501 "sysbus-sm501"
   1937OBJECT_DECLARE_SIMPLE_TYPE(SM501SysBusState, SYSBUS_SM501)
   1938
   1939struct SM501SysBusState {
   1940    /*< private >*/
   1941    SysBusDevice parent_obj;
   1942    /*< public >*/
   1943    SM501State state;
   1944    uint32_t vram_size;
   1945    uint32_t base;
   1946    SerialMM serial;
   1947};
   1948
   1949static void sm501_realize_sysbus(DeviceState *dev, Error **errp)
   1950{
   1951    SM501SysBusState *s = SYSBUS_SM501(dev);
   1952    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
   1953    DeviceState *usb_dev;
   1954    MemoryRegion *mr;
   1955
   1956    sm501_init(&s->state, dev, s->vram_size);
   1957    if (get_local_mem_size(&s->state) != s->vram_size) {
   1958        error_setg(errp, "Invalid VRAM size, nearest valid size is %" PRIu32,
   1959                   get_local_mem_size(&s->state));
   1960        return;
   1961    }
   1962    sysbus_init_mmio(sbd, &s->state.local_mem_region);
   1963    sysbus_init_mmio(sbd, &s->state.mmio_region);
   1964
   1965    /* bridge to usb host emulation module */
   1966    usb_dev = qdev_new("sysbus-ohci");
   1967    qdev_prop_set_uint32(usb_dev, "num-ports", 2);
   1968    qdev_prop_set_uint64(usb_dev, "dma-offset", s->base);
   1969    sysbus_realize_and_unref(SYS_BUS_DEVICE(usb_dev), &error_fatal);
   1970    memory_region_add_subregion(&s->state.mmio_region, SM501_USB_HOST,
   1971                       sysbus_mmio_get_region(SYS_BUS_DEVICE(usb_dev), 0));
   1972    sysbus_pass_irq(sbd, SYS_BUS_DEVICE(usb_dev));
   1973
   1974    /* bridge to serial emulation module */
   1975    sysbus_realize(SYS_BUS_DEVICE(&s->serial), &error_fatal);
   1976    mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->serial), 0);
   1977    memory_region_add_subregion(&s->state.mmio_region, SM501_UART0, mr);
   1978    /* TODO : chain irq to IRL */
   1979}
   1980
   1981static Property sm501_sysbus_properties[] = {
   1982    DEFINE_PROP_UINT32("vram-size", SM501SysBusState, vram_size, 0),
   1983    DEFINE_PROP_UINT32("base", SM501SysBusState, base, 0),
   1984    DEFINE_PROP_END_OF_LIST(),
   1985};
   1986
   1987static void sm501_reset_sysbus(DeviceState *dev)
   1988{
   1989    SM501SysBusState *s = SYSBUS_SM501(dev);
   1990    sm501_reset(&s->state);
   1991}
   1992
   1993static const VMStateDescription vmstate_sm501_sysbus = {
   1994    .name = TYPE_SYSBUS_SM501,
   1995    .version_id = 2,
   1996    .minimum_version_id = 2,
   1997    .fields = (VMStateField[]) {
   1998        VMSTATE_STRUCT(state, SM501SysBusState, 1,
   1999                       vmstate_sm501_state, SM501State),
   2000        VMSTATE_END_OF_LIST()
   2001     }
   2002};
   2003
   2004static void sm501_sysbus_class_init(ObjectClass *klass, void *data)
   2005{
   2006    DeviceClass *dc = DEVICE_CLASS(klass);
   2007
   2008    dc->realize = sm501_realize_sysbus;
   2009    set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
   2010    dc->desc = "SM501 Multimedia Companion";
   2011    device_class_set_props(dc, sm501_sysbus_properties);
   2012    dc->reset = sm501_reset_sysbus;
   2013    dc->vmsd = &vmstate_sm501_sysbus;
   2014}
   2015
   2016static void sm501_sysbus_init(Object *o)
   2017{
   2018    SM501SysBusState *sm501 = SYSBUS_SM501(o);
   2019    SerialMM *smm = &sm501->serial;
   2020
   2021    object_initialize_child(o, "serial", smm, TYPE_SERIAL_MM);
   2022    qdev_set_legacy_instance_id(DEVICE(smm), SM501_UART0, 2);
   2023    qdev_prop_set_uint8(DEVICE(smm), "regshift", 2);
   2024    qdev_prop_set_uint8(DEVICE(smm), "endianness", DEVICE_LITTLE_ENDIAN);
   2025
   2026    object_property_add_alias(o, "chardev",
   2027                              OBJECT(smm), "chardev");
   2028}
   2029
   2030static const TypeInfo sm501_sysbus_info = {
   2031    .name          = TYPE_SYSBUS_SM501,
   2032    .parent        = TYPE_SYS_BUS_DEVICE,
   2033    .instance_size = sizeof(SM501SysBusState),
   2034    .class_init    = sm501_sysbus_class_init,
   2035    .instance_init = sm501_sysbus_init,
   2036};
   2037
   2038#define TYPE_PCI_SM501 "sm501"
   2039OBJECT_DECLARE_SIMPLE_TYPE(SM501PCIState, PCI_SM501)
   2040
   2041struct SM501PCIState {
   2042    /*< private >*/
   2043    PCIDevice parent_obj;
   2044    /*< public >*/
   2045    SM501State state;
   2046    uint32_t vram_size;
   2047};
   2048
   2049static void sm501_realize_pci(PCIDevice *dev, Error **errp)
   2050{
   2051    SM501PCIState *s = PCI_SM501(dev);
   2052
   2053    sm501_init(&s->state, DEVICE(dev), s->vram_size);
   2054    if (get_local_mem_size(&s->state) != s->vram_size) {
   2055        error_setg(errp, "Invalid VRAM size, nearest valid size is %" PRIu32,
   2056                   get_local_mem_size(&s->state));
   2057        return;
   2058    }
   2059    pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY,
   2060                     &s->state.local_mem_region);
   2061    pci_register_bar(dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY,
   2062                     &s->state.mmio_region);
   2063}
   2064
   2065static Property sm501_pci_properties[] = {
   2066    DEFINE_PROP_UINT32("vram-size", SM501PCIState, vram_size, 64 * MiB),
   2067    DEFINE_PROP_END_OF_LIST(),
   2068};
   2069
   2070static void sm501_reset_pci(DeviceState *dev)
   2071{
   2072    SM501PCIState *s = PCI_SM501(dev);
   2073    sm501_reset(&s->state);
   2074    /* Bits 2:0 of misc_control register is 001 for PCI */
   2075    s->state.misc_control |= 1;
   2076}
   2077
   2078static const VMStateDescription vmstate_sm501_pci = {
   2079    .name = TYPE_PCI_SM501,
   2080    .version_id = 2,
   2081    .minimum_version_id = 2,
   2082    .fields = (VMStateField[]) {
   2083        VMSTATE_PCI_DEVICE(parent_obj, SM501PCIState),
   2084        VMSTATE_STRUCT(state, SM501PCIState, 1,
   2085                       vmstate_sm501_state, SM501State),
   2086        VMSTATE_END_OF_LIST()
   2087     }
   2088};
   2089
   2090static void sm501_pci_class_init(ObjectClass *klass, void *data)
   2091{
   2092    DeviceClass *dc = DEVICE_CLASS(klass);
   2093    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
   2094
   2095    k->realize = sm501_realize_pci;
   2096    k->vendor_id = PCI_VENDOR_ID_SILICON_MOTION;
   2097    k->device_id = PCI_DEVICE_ID_SM501;
   2098    k->class_id = PCI_CLASS_DISPLAY_OTHER;
   2099    set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
   2100    dc->desc = "SM501 Display Controller";
   2101    device_class_set_props(dc, sm501_pci_properties);
   2102    dc->reset = sm501_reset_pci;
   2103    dc->hotpluggable = false;
   2104    dc->vmsd = &vmstate_sm501_pci;
   2105}
   2106
   2107static const TypeInfo sm501_pci_info = {
   2108    .name          = TYPE_PCI_SM501,
   2109    .parent        = TYPE_PCI_DEVICE,
   2110    .instance_size = sizeof(SM501PCIState),
   2111    .class_init    = sm501_pci_class_init,
   2112    .interfaces = (InterfaceInfo[]) {
   2113        { INTERFACE_CONVENTIONAL_PCI_DEVICE },
   2114        { },
   2115    },
   2116};
   2117
   2118static void sm501_register_types(void)
   2119{
   2120    type_register_static(&sm501_sysbus_info);
   2121    type_register_static(&sm501_pci_info);
   2122}
   2123
   2124type_init(sm501_register_types)