Annotation of qemu/hw/sm501.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * QEMU SM501 Device
        !             3:  *
        !             4:  * Copyright (c) 2008 Shin-ichiro KAWASAKI
        !             5:  *
        !             6:  * Permission is hereby granted, free of charge, to any person obtaining a copy
        !             7:  * of this software and associated documentation files (the "Software"), to deal
        !             8:  * in the Software without restriction, including without limitation the rights
        !             9:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        !            10:  * copies of the Software, and to permit persons to whom the Software is
        !            11:  * furnished to do so, subject to the following conditions:
        !            12:  *
        !            13:  * The above copyright notice and this permission notice shall be included in
        !            14:  * all copies or substantial portions of the Software.
        !            15:  *
        !            16:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        !            17:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        !            18:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
        !            19:  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        !            20:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        !            21:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
        !            22:  * THE SOFTWARE.
        !            23:  */
        !            24: 
        !            25: #include <stdio.h>
        !            26: #include <assert.h>
        !            27: #include "hw.h"
        !            28: #include "pc.h"
        !            29: #include "console.h"
        !            30: #include "devices.h"
        !            31: 
        !            32: /*
        !            33:  * Status: 2008/11/02
        !            34:  *   - Minimum implementation for Linux console : mmio regs and CRT layer.
        !            35:  *   - Always updates full screen.
        !            36:  *
        !            37:  * TODO:
        !            38:  *   - Panel support
        !            39:  *   - Hardware cursor support
        !            40:  *   - Touch panel support
        !            41:  *   - USB support
        !            42:  *   - UART support
        !            43:  *   - Performance tuning
        !            44:  */
        !            45: 
        !            46: //#define DEBUG_SM501
        !            47: //#define DEBUG_BITBLT
        !            48: 
        !            49: #ifdef DEBUG_SM501
        !            50: #define SM501_DPRINTF(fmt...) printf(fmt)
        !            51: #else
        !            52: #define SM501_DPRINTF(fmt...) do {} while(0)
        !            53: #endif
        !            54: 
        !            55: 
        !            56: #define MMIO_BASE_OFFSET 0x3e00000
        !            57: 
        !            58: /* SM501 register definitions taken from "linux/include/linux/sm501-regs.h" */
        !            59: 
        !            60: /* System Configuration area */
        !            61: /* System config base */
        !            62: #define SM501_SYS_CONFIG               (0x000000)
        !            63: 
        !            64: /* config 1 */
        !            65: #define SM501_SYSTEM_CONTROL           (0x000000)
        !            66: 
        !            67: #define SM501_SYSCTRL_PANEL_TRISTATE   (1<<0)
        !            68: #define SM501_SYSCTRL_MEM_TRISTATE     (1<<1)
        !            69: #define SM501_SYSCTRL_CRT_TRISTATE     (1<<2)
        !            70: 
        !            71: #define SM501_SYSCTRL_PCI_SLAVE_BURST_MASK (3<<4)
        !            72: #define SM501_SYSCTRL_PCI_SLAVE_BURST_1        (0<<4)
        !            73: #define SM501_SYSCTRL_PCI_SLAVE_BURST_2        (1<<4)
        !            74: #define SM501_SYSCTRL_PCI_SLAVE_BURST_4        (2<<4)
        !            75: #define SM501_SYSCTRL_PCI_SLAVE_BURST_8        (3<<4)
        !            76: 
        !            77: #define SM501_SYSCTRL_PCI_CLOCK_RUN_EN (1<<6)
        !            78: #define SM501_SYSCTRL_PCI_RETRY_DISABLE        (1<<7)
        !            79: #define SM501_SYSCTRL_PCI_SUBSYS_LOCK  (1<<11)
        !            80: #define SM501_SYSCTRL_PCI_BURST_READ_EN        (1<<15)
        !            81: 
        !            82: /* miscellaneous control */
        !            83: 
        !            84: #define SM501_MISC_CONTROL             (0x000004)
        !            85: 
        !            86: #define SM501_MISC_BUS_SH              (0x0)
        !            87: #define SM501_MISC_BUS_PCI             (0x1)
        !            88: #define SM501_MISC_BUS_XSCALE          (0x2)
        !            89: #define SM501_MISC_BUS_NEC             (0x6)
        !            90: #define SM501_MISC_BUS_MASK            (0x7)
        !            91: 
        !            92: #define SM501_MISC_VR_62MB             (1<<3)
        !            93: #define SM501_MISC_CDR_RESET           (1<<7)
        !            94: #define SM501_MISC_USB_LB              (1<<8)
        !            95: #define SM501_MISC_USB_SLAVE           (1<<9)
        !            96: #define SM501_MISC_BL_1                        (1<<10)
        !            97: #define SM501_MISC_MC                  (1<<11)
        !            98: #define SM501_MISC_DAC_POWER           (1<<12)
        !            99: #define SM501_MISC_IRQ_INVERT          (1<<16)
        !           100: #define SM501_MISC_SH                  (1<<17)
        !           101: 
        !           102: #define SM501_MISC_HOLD_EMPTY          (0<<18)
        !           103: #define SM501_MISC_HOLD_8              (1<<18)
        !           104: #define SM501_MISC_HOLD_16             (2<<18)
        !           105: #define SM501_MISC_HOLD_24             (3<<18)
        !           106: #define SM501_MISC_HOLD_32             (4<<18)
        !           107: #define SM501_MISC_HOLD_MASK           (7<<18)
        !           108: 
        !           109: #define SM501_MISC_FREQ_12             (1<<24)
        !           110: #define SM501_MISC_PNL_24BIT           (1<<25)
        !           111: #define SM501_MISC_8051_LE             (1<<26)
        !           112: 
        !           113: 
        !           114: 
        !           115: #define SM501_GPIO31_0_CONTROL         (0x000008)
        !           116: #define SM501_GPIO63_32_CONTROL                (0x00000C)
        !           117: #define SM501_DRAM_CONTROL             (0x000010)
        !           118: 
        !           119: /* command list */
        !           120: #define SM501_ARBTRTN_CONTROL          (0x000014)
        !           121: 
        !           122: /* command list */
        !           123: #define SM501_COMMAND_LIST_STATUS      (0x000024)
        !           124: 
        !           125: /* interrupt debug */
        !           126: #define SM501_RAW_IRQ_STATUS           (0x000028)
        !           127: #define SM501_RAW_IRQ_CLEAR            (0x000028)
        !           128: #define SM501_IRQ_STATUS               (0x00002C)
        !           129: #define SM501_IRQ_MASK                 (0x000030)
        !           130: #define SM501_DEBUG_CONTROL            (0x000034)
        !           131: 
        !           132: /* power management */
        !           133: #define SM501_POWERMODE_P2X_SRC                (1<<29)
        !           134: #define SM501_POWERMODE_V2X_SRC                (1<<20)
        !           135: #define SM501_POWERMODE_M_SRC          (1<<12)
        !           136: #define SM501_POWERMODE_M1_SRC         (1<<4)
        !           137: 
        !           138: #define SM501_CURRENT_GATE             (0x000038)
        !           139: #define SM501_CURRENT_CLOCK            (0x00003C)
        !           140: #define SM501_POWER_MODE_0_GATE                (0x000040)
        !           141: #define SM501_POWER_MODE_0_CLOCK       (0x000044)
        !           142: #define SM501_POWER_MODE_1_GATE                (0x000048)
        !           143: #define SM501_POWER_MODE_1_CLOCK       (0x00004C)
        !           144: #define SM501_SLEEP_MODE_GATE          (0x000050)
        !           145: #define SM501_POWER_MODE_CONTROL       (0x000054)
        !           146: 
        !           147: /* power gates for units within the 501 */
        !           148: #define SM501_GATE_HOST                        (0)
        !           149: #define SM501_GATE_MEMORY              (1)
        !           150: #define SM501_GATE_DISPLAY             (2)
        !           151: #define SM501_GATE_2D_ENGINE           (3)
        !           152: #define SM501_GATE_CSC                 (4)
        !           153: #define SM501_GATE_ZVPORT              (5)
        !           154: #define SM501_GATE_GPIO                        (6)
        !           155: #define SM501_GATE_UART0               (7)
        !           156: #define SM501_GATE_UART1               (8)
        !           157: #define SM501_GATE_SSP                 (10)
        !           158: #define SM501_GATE_USB_HOST            (11)
        !           159: #define SM501_GATE_USB_GADGET          (12)
        !           160: #define SM501_GATE_UCONTROLLER         (17)
        !           161: #define SM501_GATE_AC97                        (18)
        !           162: 
        !           163: /* panel clock */
        !           164: #define SM501_CLOCK_P2XCLK             (24)
        !           165: /* crt clock */
        !           166: #define SM501_CLOCK_V2XCLK             (16)
        !           167: /* main clock */
        !           168: #define SM501_CLOCK_MCLK               (8)
        !           169: /* SDRAM controller clock */
        !           170: #define SM501_CLOCK_M1XCLK             (0)
        !           171: 
        !           172: /* config 2 */
        !           173: #define SM501_PCI_MASTER_BASE          (0x000058)
        !           174: #define SM501_ENDIAN_CONTROL           (0x00005C)
        !           175: #define SM501_DEVICEID                 (0x000060)
        !           176: /* 0x050100A0 */
        !           177: 
        !           178: #define SM501_DEVICEID_SM501           (0x05010000)
        !           179: #define SM501_DEVICEID_IDMASK          (0xffff0000)
        !           180: #define SM501_DEVICEID_REVMASK         (0x000000ff)
        !           181: 
        !           182: #define SM501_PLLCLOCK_COUNT           (0x000064)
        !           183: #define SM501_MISC_TIMING              (0x000068)
        !           184: #define SM501_CURRENT_SDRAM_CLOCK      (0x00006C)
        !           185: 
        !           186: #define SM501_PROGRAMMABLE_PLL_CONTROL (0x000074)
        !           187: 
        !           188: /* GPIO base */
        !           189: #define SM501_GPIO                     (0x010000)
        !           190: #define SM501_GPIO_DATA_LOW            (0x00)
        !           191: #define SM501_GPIO_DATA_HIGH           (0x04)
        !           192: #define SM501_GPIO_DDR_LOW             (0x08)
        !           193: #define SM501_GPIO_DDR_HIGH            (0x0C)
        !           194: #define SM501_GPIO_IRQ_SETUP           (0x10)
        !           195: #define SM501_GPIO_IRQ_STATUS          (0x14)
        !           196: #define SM501_GPIO_IRQ_RESET           (0x14)
        !           197: 
        !           198: /* I2C controller base */
        !           199: #define SM501_I2C                      (0x010040)
        !           200: #define SM501_I2C_BYTE_COUNT           (0x00)
        !           201: #define SM501_I2C_CONTROL              (0x01)
        !           202: #define SM501_I2C_STATUS               (0x02)
        !           203: #define SM501_I2C_RESET                        (0x02)
        !           204: #define SM501_I2C_SLAVE_ADDRESS                (0x03)
        !           205: #define SM501_I2C_DATA                 (0x04)
        !           206: 
        !           207: /* SSP base */
        !           208: #define SM501_SSP                      (0x020000)
        !           209: 
        !           210: /* Uart 0 base */
        !           211: #define SM501_UART0                    (0x030000)
        !           212: 
        !           213: /* Uart 1 base */
        !           214: #define SM501_UART1                    (0x030020)
        !           215: 
        !           216: /* USB host port base */
        !           217: #define SM501_USB_HOST                 (0x040000)
        !           218: 
        !           219: /* USB slave/gadget base */
        !           220: #define SM501_USB_GADGET               (0x060000)
        !           221: 
        !           222: /* USB slave/gadget data port base */
        !           223: #define SM501_USB_GADGET_DATA          (0x070000)
        !           224: 
        !           225: /* Display controller/video engine base */
        !           226: #define SM501_DC                       (0x080000)
        !           227: 
        !           228: /* common defines for the SM501 address registers */
        !           229: #define SM501_ADDR_FLIP                        (1<<31)
        !           230: #define SM501_ADDR_EXT                 (1<<27)
        !           231: #define SM501_ADDR_CS1                 (1<<26)
        !           232: #define SM501_ADDR_MASK                        (0x3f << 26)
        !           233: 
        !           234: #define SM501_FIFO_MASK                        (0x3 << 16)
        !           235: #define SM501_FIFO_1                   (0x0 << 16)
        !           236: #define SM501_FIFO_3                   (0x1 << 16)
        !           237: #define SM501_FIFO_7                   (0x2 << 16)
        !           238: #define SM501_FIFO_11                  (0x3 << 16)
        !           239: 
        !           240: /* common registers for panel and the crt */
        !           241: #define SM501_OFF_DC_H_TOT             (0x000)
        !           242: #define SM501_OFF_DC_V_TOT             (0x008)
        !           243: #define SM501_OFF_DC_H_SYNC            (0x004)
        !           244: #define SM501_OFF_DC_V_SYNC            (0x00C)
        !           245: 
        !           246: #define SM501_DC_PANEL_CONTROL         (0x000)
        !           247: 
        !           248: #define SM501_DC_PANEL_CONTROL_FPEN    (1<<27)
        !           249: #define SM501_DC_PANEL_CONTROL_BIAS    (1<<26)
        !           250: #define SM501_DC_PANEL_CONTROL_DATA    (1<<25)
        !           251: #define SM501_DC_PANEL_CONTROL_VDD     (1<<24)
        !           252: #define SM501_DC_PANEL_CONTROL_DP      (1<<23)
        !           253: 
        !           254: #define SM501_DC_PANEL_CONTROL_TFT_888 (0<<21)
        !           255: #define SM501_DC_PANEL_CONTROL_TFT_333 (1<<21)
        !           256: #define SM501_DC_PANEL_CONTROL_TFT_444 (2<<21)
        !           257: 
        !           258: #define SM501_DC_PANEL_CONTROL_DE      (1<<20)
        !           259: 
        !           260: #define SM501_DC_PANEL_CONTROL_LCD_TFT (0<<18)
        !           261: #define SM501_DC_PANEL_CONTROL_LCD_STN8        (1<<18)
        !           262: #define SM501_DC_PANEL_CONTROL_LCD_STN12 (2<<18)
        !           263: 
        !           264: #define SM501_DC_PANEL_CONTROL_CP      (1<<14)
        !           265: #define SM501_DC_PANEL_CONTROL_VSP     (1<<13)
        !           266: #define SM501_DC_PANEL_CONTROL_HSP     (1<<12)
        !           267: #define SM501_DC_PANEL_CONTROL_CK      (1<<9)
        !           268: #define SM501_DC_PANEL_CONTROL_TE      (1<<8)
        !           269: #define SM501_DC_PANEL_CONTROL_VPD     (1<<7)
        !           270: #define SM501_DC_PANEL_CONTROL_VP      (1<<6)
        !           271: #define SM501_DC_PANEL_CONTROL_HPD     (1<<5)
        !           272: #define SM501_DC_PANEL_CONTROL_HP      (1<<4)
        !           273: #define SM501_DC_PANEL_CONTROL_GAMMA   (1<<3)
        !           274: #define SM501_DC_PANEL_CONTROL_EN      (1<<2)
        !           275: 
        !           276: #define SM501_DC_PANEL_CONTROL_8BPP    (0<<0)
        !           277: #define SM501_DC_PANEL_CONTROL_16BPP   (1<<0)
        !           278: #define SM501_DC_PANEL_CONTROL_32BPP   (2<<0)
        !           279: 
        !           280: 
        !           281: #define SM501_DC_PANEL_PANNING_CONTROL (0x004)
        !           282: #define SM501_DC_PANEL_COLOR_KEY       (0x008)
        !           283: #define SM501_DC_PANEL_FB_ADDR         (0x00C)
        !           284: #define SM501_DC_PANEL_FB_OFFSET       (0x010)
        !           285: #define SM501_DC_PANEL_FB_WIDTH                (0x014)
        !           286: #define SM501_DC_PANEL_FB_HEIGHT       (0x018)
        !           287: #define SM501_DC_PANEL_TL_LOC          (0x01C)
        !           288: #define SM501_DC_PANEL_BR_LOC          (0x020)
        !           289: #define SM501_DC_PANEL_H_TOT           (0x024)
        !           290: #define SM501_DC_PANEL_H_SYNC          (0x028)
        !           291: #define SM501_DC_PANEL_V_TOT           (0x02C)
        !           292: #define SM501_DC_PANEL_V_SYNC          (0x030)
        !           293: #define SM501_DC_PANEL_CUR_LINE                (0x034)
        !           294: 
        !           295: #define SM501_DC_VIDEO_CONTROL         (0x040)
        !           296: #define SM501_DC_VIDEO_FB0_ADDR                (0x044)
        !           297: #define SM501_DC_VIDEO_FB_WIDTH                (0x048)
        !           298: #define SM501_DC_VIDEO_FB0_LAST_ADDR   (0x04C)
        !           299: #define SM501_DC_VIDEO_TL_LOC          (0x050)
        !           300: #define SM501_DC_VIDEO_BR_LOC          (0x054)
        !           301: #define SM501_DC_VIDEO_SCALE           (0x058)
        !           302: #define SM501_DC_VIDEO_INIT_SCALE      (0x05C)
        !           303: #define SM501_DC_VIDEO_YUV_CONSTANTS   (0x060)
        !           304: #define SM501_DC_VIDEO_FB1_ADDR                (0x064)
        !           305: #define SM501_DC_VIDEO_FB1_LAST_ADDR   (0x068)
        !           306: 
        !           307: #define SM501_DC_VIDEO_ALPHA_CONTROL   (0x080)
        !           308: #define SM501_DC_VIDEO_ALPHA_FB_ADDR   (0x084)
        !           309: #define SM501_DC_VIDEO_ALPHA_FB_OFFSET (0x088)
        !           310: #define SM501_DC_VIDEO_ALPHA_FB_LAST_ADDR      (0x08C)
        !           311: #define SM501_DC_VIDEO_ALPHA_TL_LOC    (0x090)
        !           312: #define SM501_DC_VIDEO_ALPHA_BR_LOC    (0x094)
        !           313: #define SM501_DC_VIDEO_ALPHA_SCALE     (0x098)
        !           314: #define SM501_DC_VIDEO_ALPHA_INIT_SCALE        (0x09C)
        !           315: #define SM501_DC_VIDEO_ALPHA_CHROMA_KEY        (0x0A0)
        !           316: #define SM501_DC_VIDEO_ALPHA_COLOR_LOOKUP      (0x0A4)
        !           317: 
        !           318: #define SM501_DC_PANEL_HWC_BASE                (0x0F0)
        !           319: #define SM501_DC_PANEL_HWC_ADDR                (0x0F0)
        !           320: #define SM501_DC_PANEL_HWC_LOC         (0x0F4)
        !           321: #define SM501_DC_PANEL_HWC_COLOR_1_2   (0x0F8)
        !           322: #define SM501_DC_PANEL_HWC_COLOR_3     (0x0FC)
        !           323: 
        !           324: #define SM501_HWC_EN                   (1<<31)
        !           325: 
        !           326: #define SM501_OFF_HWC_ADDR             (0x00)
        !           327: #define SM501_OFF_HWC_LOC              (0x04)
        !           328: #define SM501_OFF_HWC_COLOR_1_2                (0x08)
        !           329: #define SM501_OFF_HWC_COLOR_3          (0x0C)
        !           330: 
        !           331: #define SM501_DC_ALPHA_CONTROL         (0x100)
        !           332: #define SM501_DC_ALPHA_FB_ADDR         (0x104)
        !           333: #define SM501_DC_ALPHA_FB_OFFSET       (0x108)
        !           334: #define SM501_DC_ALPHA_TL_LOC          (0x10C)
        !           335: #define SM501_DC_ALPHA_BR_LOC          (0x110)
        !           336: #define SM501_DC_ALPHA_CHROMA_KEY      (0x114)
        !           337: #define SM501_DC_ALPHA_COLOR_LOOKUP    (0x118)
        !           338: 
        !           339: #define SM501_DC_CRT_CONTROL           (0x200)
        !           340: 
        !           341: #define SM501_DC_CRT_CONTROL_TVP       (1<<15)
        !           342: #define SM501_DC_CRT_CONTROL_CP                (1<<14)
        !           343: #define SM501_DC_CRT_CONTROL_VSP       (1<<13)
        !           344: #define SM501_DC_CRT_CONTROL_HSP       (1<<12)
        !           345: #define SM501_DC_CRT_CONTROL_VS                (1<<11)
        !           346: #define SM501_DC_CRT_CONTROL_BLANK     (1<<10)
        !           347: #define SM501_DC_CRT_CONTROL_SEL       (1<<9)
        !           348: #define SM501_DC_CRT_CONTROL_TE                (1<<8)
        !           349: #define SM501_DC_CRT_CONTROL_PIXEL_MASK (0xF << 4)
        !           350: #define SM501_DC_CRT_CONTROL_GAMMA     (1<<3)
        !           351: #define SM501_DC_CRT_CONTROL_ENABLE    (1<<2)
        !           352: 
        !           353: #define SM501_DC_CRT_CONTROL_8BPP      (0<<0)
        !           354: #define SM501_DC_CRT_CONTROL_16BPP     (1<<0)
        !           355: #define SM501_DC_CRT_CONTROL_32BPP     (2<<0)
        !           356: 
        !           357: #define SM501_DC_CRT_FB_ADDR           (0x204)
        !           358: #define SM501_DC_CRT_FB_OFFSET         (0x208)
        !           359: #define SM501_DC_CRT_H_TOT             (0x20C)
        !           360: #define SM501_DC_CRT_H_SYNC            (0x210)
        !           361: #define SM501_DC_CRT_V_TOT             (0x214)
        !           362: #define SM501_DC_CRT_V_SYNC            (0x218)
        !           363: #define SM501_DC_CRT_SIGNATURE_ANALYZER        (0x21C)
        !           364: #define SM501_DC_CRT_CUR_LINE          (0x220)
        !           365: #define SM501_DC_CRT_MONITOR_DETECT    (0x224)
        !           366: 
        !           367: #define SM501_DC_CRT_HWC_BASE          (0x230)
        !           368: #define SM501_DC_CRT_HWC_ADDR          (0x230)
        !           369: #define SM501_DC_CRT_HWC_LOC           (0x234)
        !           370: #define SM501_DC_CRT_HWC_COLOR_1_2     (0x238)
        !           371: #define SM501_DC_CRT_HWC_COLOR_3       (0x23C)
        !           372: 
        !           373: #define SM501_DC_PANEL_PALETTE         (0x400)
        !           374: 
        !           375: #define SM501_DC_VIDEO_PALETTE         (0x800)
        !           376: 
        !           377: #define SM501_DC_CRT_PALETTE           (0xC00)
        !           378: 
        !           379: /* Zoom Video port base */
        !           380: #define SM501_ZVPORT                   (0x090000)
        !           381: 
        !           382: /* AC97/I2S base */
        !           383: #define SM501_AC97                     (0x0A0000)
        !           384: 
        !           385: /* 8051 micro controller base */
        !           386: #define SM501_UCONTROLLER              (0x0B0000)
        !           387: 
        !           388: /* 8051 micro controller SRAM base */
        !           389: #define SM501_UCONTROLLER_SRAM         (0x0C0000)
        !           390: 
        !           391: /* DMA base */
        !           392: #define SM501_DMA                      (0x0D0000)
        !           393: 
        !           394: /* 2d engine base */
        !           395: #define SM501_2D_ENGINE                        (0x100000)
        !           396: #define SM501_2D_SOURCE                        (0x00)
        !           397: #define SM501_2D_DESTINATION           (0x04)
        !           398: #define SM501_2D_DIMENSION             (0x08)
        !           399: #define SM501_2D_CONTROL               (0x0C)
        !           400: #define SM501_2D_PITCH                 (0x10)
        !           401: #define SM501_2D_FOREGROUND            (0x14)
        !           402: #define SM501_2D_BACKGROUND            (0x18)
        !           403: #define SM501_2D_STRETCH               (0x1C)
        !           404: #define SM501_2D_COLOR_COMPARE         (0x20)
        !           405: #define SM501_2D_COLOR_COMPARE_MASK    (0x24)
        !           406: #define SM501_2D_MASK                  (0x28)
        !           407: #define SM501_2D_CLIP_TL               (0x2C)
        !           408: #define SM501_2D_CLIP_BR               (0x30)
        !           409: #define SM501_2D_MONO_PATTERN_LOW      (0x34)
        !           410: #define SM501_2D_MONO_PATTERN_HIGH     (0x38)
        !           411: #define SM501_2D_WINDOW_WIDTH          (0x3C)
        !           412: #define SM501_2D_SOURCE_BASE           (0x40)
        !           413: #define SM501_2D_DESTINATION_BASE      (0x44)
        !           414: #define SM501_2D_ALPHA                 (0x48)
        !           415: #define SM501_2D_WRAP                  (0x4C)
        !           416: #define SM501_2D_STATUS                        (0x50)
        !           417: 
        !           418: #define SM501_CSC_Y_SOURCE_BASE                (0xC8)
        !           419: #define SM501_CSC_CONSTANTS            (0xCC)
        !           420: #define SM501_CSC_Y_SOURCE_X           (0xD0)
        !           421: #define SM501_CSC_Y_SOURCE_Y           (0xD4)
        !           422: #define SM501_CSC_U_SOURCE_BASE                (0xD8)
        !           423: #define SM501_CSC_V_SOURCE_BASE                (0xDC)
        !           424: #define SM501_CSC_SOURCE_DIMENSION     (0xE0)
        !           425: #define SM501_CSC_SOURCE_PITCH         (0xE4)
        !           426: #define SM501_CSC_DESTINATION          (0xE8)
        !           427: #define SM501_CSC_DESTINATION_DIMENSION        (0xEC)
        !           428: #define SM501_CSC_DESTINATION_PITCH    (0xF0)
        !           429: #define SM501_CSC_SCALE_FACTOR         (0xF4)
        !           430: #define SM501_CSC_DESTINATION_BASE     (0xF8)
        !           431: #define SM501_CSC_CONTROL              (0xFC)
        !           432: 
        !           433: /* 2d engine data port base */
        !           434: #define SM501_2D_ENGINE_DATA           (0x110000)
        !           435: 
        !           436: /* end of register definitions */
        !           437: 
        !           438: 
        !           439: /* SM501 local memory size taken from "linux/drivers/mfd/sm501.c" */
        !           440: static const uint32_t sm501_mem_local_size[] = {
        !           441:        [0]     = 4*1024*1024,
        !           442:        [1]     = 8*1024*1024,
        !           443:        [2]     = 16*1024*1024,
        !           444:        [3]     = 32*1024*1024,
        !           445:        [4]     = 64*1024*1024,
        !           446:        [5]     = 2*1024*1024,
        !           447: };
        !           448: #define get_local_mem_size(s) sm501_mem_local_size[(s)->local_mem_size_index]
        !           449: 
        !           450: typedef struct SM501State {
        !           451:     /* graphic console status */
        !           452:     DisplayState *ds;
        !           453: 
        !           454:     /* status & internal resources */
        !           455:     target_phys_addr_t base;
        !           456:     uint32_t local_mem_size_index;
        !           457:     uint8_t * local_mem;
        !           458:     uint32_t last_width;
        !           459:     uint32_t last_height;
        !           460: 
        !           461:     /* mmio registers */
        !           462:     uint32_t system_control;
        !           463:     uint32_t misc_control;
        !           464:     uint32_t gpio_31_0_control;
        !           465:     uint32_t gpio_63_32_control;
        !           466:     uint32_t dram_control;
        !           467:     uint32_t irq_mask;
        !           468:     uint32_t misc_timing;
        !           469:     uint32_t power_mode_control;
        !           470: 
        !           471:     uint32_t uart0_ier;
        !           472:     uint32_t uart0_lcr;
        !           473:     uint32_t uart0_mcr;
        !           474:     uint32_t uart0_scr;
        !           475: 
        !           476:     uint8_t dc_palette[0x400 * 3];
        !           477: 
        !           478:     uint32_t dc_panel_control;
        !           479:     uint32_t dc_panel_panning_control;
        !           480:     uint32_t dc_panel_fb_addr;
        !           481:     uint32_t dc_panel_fb_offset;
        !           482:     uint32_t dc_panel_fb_width;
        !           483:     uint32_t dc_panel_fb_height;
        !           484:     uint32_t dc_panel_tl_location;
        !           485:     uint32_t dc_panel_br_location;
        !           486:     uint32_t dc_panel_h_total;
        !           487:     uint32_t dc_panel_h_sync;
        !           488:     uint32_t dc_panel_v_total;
        !           489:     uint32_t dc_panel_v_sync;
        !           490: 
        !           491:     uint32_t dc_panel_hwc_addr;
        !           492:     uint32_t dc_panel_hwc_location;
        !           493:     uint32_t dc_panel_hwc_color_1_2;
        !           494:     uint32_t dc_panel_hwc_color_3;
        !           495: 
        !           496:     uint32_t dc_crt_control;
        !           497:     uint32_t dc_crt_fb_addr;
        !           498:     uint32_t dc_crt_fb_offset;
        !           499:     uint32_t dc_crt_h_total;
        !           500:     uint32_t dc_crt_h_sync;
        !           501:     uint32_t dc_crt_v_total;
        !           502:     uint32_t dc_crt_v_sync;
        !           503: 
        !           504:     uint32_t dc_crt_hwc_addr;
        !           505:     uint32_t dc_crt_hwc_location;
        !           506:     uint32_t dc_crt_hwc_color_1_2;
        !           507:     uint32_t dc_crt_hwc_color_3;
        !           508: 
        !           509: } SM501State;
        !           510: 
        !           511: static uint32_t get_local_mem_size_index(uint32_t size)
        !           512: {
        !           513:     uint32_t norm_size = 0;
        !           514:     int i, index = 0;
        !           515: 
        !           516:     for (i = 0; i < ARRAY_SIZE(sm501_mem_local_size); i++) {
        !           517:        uint32_t new_size = sm501_mem_local_size[i];
        !           518:        if (new_size >= size) {
        !           519:            if (norm_size == 0 || norm_size > new_size) {
        !           520:                norm_size = new_size;
        !           521:                index = i;
        !           522:            }
        !           523:        }
        !           524:     }
        !           525: 
        !           526:     return index;
        !           527: }
        !           528: 
        !           529: static uint32_t sm501_system_config_read(void *opaque, target_phys_addr_t addr)
        !           530: {
        !           531:     SM501State * s = (SM501State *)opaque;
        !           532:     uint32_t ret = 0;
        !           533:     SM501_DPRINTF("sm501 system config regs : read addr=%x\n", (int)addr);
        !           534: 
        !           535:     switch(addr) {
        !           536:     case SM501_SYSTEM_CONTROL:
        !           537:        ret = s->system_control;
        !           538:        break;
        !           539:     case SM501_MISC_CONTROL:
        !           540:        ret = s->misc_control;
        !           541:        break;
        !           542:     case SM501_GPIO31_0_CONTROL:
        !           543:        ret = s->gpio_31_0_control;
        !           544:        break;
        !           545:     case SM501_GPIO63_32_CONTROL:
        !           546:        ret = s->gpio_63_32_control;
        !           547:        break;
        !           548:     case SM501_DEVICEID:
        !           549:        ret = 0x050100A0;
        !           550:        break;
        !           551:     case SM501_DRAM_CONTROL:
        !           552:        ret = (s->dram_control & 0x07F107C0) | s->local_mem_size_index << 13;
        !           553:        break;
        !           554:     case SM501_IRQ_MASK:
        !           555:        ret = s->irq_mask;
        !           556:        break;
        !           557:     case SM501_MISC_TIMING:
        !           558:        /* TODO : simulate gate control */
        !           559:        ret = s->misc_timing;
        !           560:        break;
        !           561:     case SM501_CURRENT_GATE:
        !           562:        /* TODO : simulate gate control */
        !           563:        ret = 0x00021807;
        !           564:        break;
        !           565:     case SM501_CURRENT_CLOCK:
        !           566:        ret = 0x2A1A0A09;
        !           567:        break;
        !           568:     case SM501_POWER_MODE_CONTROL:
        !           569:        ret = s->power_mode_control;
        !           570:        break;
        !           571: 
        !           572:     default:
        !           573:        printf("sm501 system config : not implemented register read."
        !           574:               " addr=%x\n", (int)addr);
        !           575:        assert(0);
        !           576:     }
        !           577: 
        !           578:     return ret;
        !           579: }
        !           580: 
        !           581: static void sm501_system_config_write(void *opaque,
        !           582:                                      target_phys_addr_t addr, uint32_t value)
        !           583: {
        !           584:     SM501State * s = (SM501State *)opaque;
        !           585:     SM501_DPRINTF("sm501 system config regs : write addr=%x, val=%x\n",
        !           586:                  addr, value);
        !           587: 
        !           588:     switch(addr) {
        !           589:     case SM501_SYSTEM_CONTROL:
        !           590:        s->system_control = value & 0xE300B8F7;
        !           591:        break;
        !           592:     case SM501_MISC_CONTROL:
        !           593:        s->misc_control = value & 0xFF7FFF20;
        !           594:        break;
        !           595:     case SM501_GPIO31_0_CONTROL:
        !           596:        s->gpio_31_0_control = value;
        !           597:        break;
        !           598:     case SM501_GPIO63_32_CONTROL:
        !           599:        s->gpio_63_32_control = value;
        !           600:        break;
        !           601:     case SM501_DRAM_CONTROL:
        !           602:        s->local_mem_size_index = (value >> 13) & 0x7;
        !           603:        /* rODO : check validity of size change */
        !           604:        s->dram_control |=  value & 0x7FFFFFC3;
        !           605:        break;
        !           606:     case SM501_IRQ_MASK:
        !           607:        s->irq_mask = value;
        !           608:        break;
        !           609:     case SM501_MISC_TIMING:
        !           610:        s->misc_timing = value & 0xF31F1FFF;
        !           611:        break;
        !           612:     case SM501_POWER_MODE_0_GATE:
        !           613:     case SM501_POWER_MODE_1_GATE:
        !           614:     case SM501_POWER_MODE_0_CLOCK:
        !           615:     case SM501_POWER_MODE_1_CLOCK:
        !           616:        /* TODO : simulate gate & clock control */
        !           617:        break;
        !           618:     case SM501_POWER_MODE_CONTROL:
        !           619:        s->power_mode_control = value & 0x00000003;
        !           620:        break;
        !           621: 
        !           622:     default:
        !           623:        printf("sm501 system config : not implemented register write."
        !           624:               " addr=%x, val=%x\n", (int)addr, value);
        !           625:        assert(0);
        !           626:     }
        !           627: }
        !           628: 
        !           629: static CPUReadMemoryFunc *sm501_system_config_readfn[] = {
        !           630:     NULL,
        !           631:     NULL,
        !           632:     &sm501_system_config_read,
        !           633: };
        !           634: 
        !           635: static CPUWriteMemoryFunc *sm501_system_config_writefn[] = {
        !           636:     NULL,
        !           637:     NULL,
        !           638:     &sm501_system_config_write,
        !           639: };
        !           640: 
        !           641: static uint32_t sm501_palette_read(void *opaque, target_phys_addr_t addr)
        !           642: {
        !           643:     SM501State * s = (SM501State *)opaque;
        !           644:     SM501_DPRINTF("sm501 palette read addr=%x\n", (int)addr);
        !           645: 
        !           646:     /* TODO : consider BYTE/WORD access */
        !           647:     /* TODO : consider endian */
        !           648: 
        !           649:     assert(0 <= addr && addr < 0x400 * 3);
        !           650:     return *(uint32_t*)&s->dc_palette[addr];
        !           651: }
        !           652: 
        !           653: static void sm501_palette_write(void *opaque,
        !           654:                                target_phys_addr_t addr, uint32_t value)
        !           655: {
        !           656:     SM501State * s = (SM501State *)opaque;
        !           657:     SM501_DPRINTF("sm501 palette write addr=%x, val=%x\n",
        !           658:                  (int)addr, value);
        !           659: 
        !           660:     /* TODO : consider BYTE/WORD access */
        !           661:     /* TODO : consider endian */
        !           662: 
        !           663:     assert(0 <= addr && addr < 0x400 * 3);
        !           664:     *(uint32_t*)&s->dc_palette[addr] = value;
        !           665: }
        !           666: 
        !           667: static uint32_t sm501_disp_ctrl_read(void *opaque, target_phys_addr_t addr)
        !           668: {
        !           669:     SM501State * s = (SM501State *)opaque;
        !           670:     uint32_t ret = 0;
        !           671:     SM501_DPRINTF("sm501 disp ctrl regs : read addr=%x\n", (int)addr);
        !           672: 
        !           673:     switch(addr) {
        !           674: 
        !           675:     case SM501_DC_PANEL_CONTROL:
        !           676:        ret = s->dc_panel_control;
        !           677:        break;
        !           678:     case SM501_DC_PANEL_PANNING_CONTROL:
        !           679:        ret = s->dc_panel_panning_control;
        !           680:        break;
        !           681:     case SM501_DC_PANEL_FB_ADDR:
        !           682:        ret = s->dc_panel_fb_addr;
        !           683:        break;
        !           684:     case SM501_DC_PANEL_FB_OFFSET:
        !           685:        ret = s->dc_panel_fb_offset;
        !           686:        break;
        !           687:     case SM501_DC_PANEL_FB_WIDTH:
        !           688:        ret = s->dc_panel_fb_width;
        !           689:        break;
        !           690:     case SM501_DC_PANEL_FB_HEIGHT:
        !           691:        ret = s->dc_panel_fb_height;
        !           692:        break;
        !           693:     case SM501_DC_PANEL_TL_LOC:
        !           694:        ret = s->dc_panel_tl_location;
        !           695:        break;
        !           696:     case SM501_DC_PANEL_BR_LOC:
        !           697:        ret = s->dc_panel_br_location;
        !           698:        break;
        !           699: 
        !           700:     case SM501_DC_PANEL_H_TOT:
        !           701:        ret = s->dc_panel_h_total;
        !           702:        break;
        !           703:     case SM501_DC_PANEL_H_SYNC:
        !           704:        ret = s->dc_panel_h_sync;
        !           705:        break;
        !           706:     case SM501_DC_PANEL_V_TOT:
        !           707:        ret = s->dc_panel_v_total;
        !           708:        break;
        !           709:     case SM501_DC_PANEL_V_SYNC:
        !           710:        ret = s->dc_panel_v_sync;
        !           711:        break;
        !           712: 
        !           713:     case SM501_DC_CRT_CONTROL:
        !           714:        ret = s->dc_crt_control;
        !           715:        break;
        !           716:     case SM501_DC_CRT_FB_ADDR:
        !           717:        ret = s->dc_crt_fb_addr;
        !           718:        break;
        !           719:     case SM501_DC_CRT_FB_OFFSET:
        !           720:        ret = s->dc_crt_fb_offset;
        !           721:        break;
        !           722:     case SM501_DC_CRT_H_TOT:
        !           723:        ret = s->dc_crt_h_total;
        !           724:        break;
        !           725:     case SM501_DC_CRT_H_SYNC:
        !           726:        ret = s->dc_crt_h_sync;
        !           727:        break;
        !           728:     case SM501_DC_CRT_V_TOT:
        !           729:        ret = s->dc_crt_v_total;
        !           730:        break;
        !           731:     case SM501_DC_CRT_V_SYNC:
        !           732:        ret = s->dc_crt_v_sync;
        !           733:        break;
        !           734: 
        !           735:     case SM501_DC_CRT_HWC_ADDR:
        !           736:        ret = s->dc_crt_hwc_addr;
        !           737:        break;
        !           738:     case SM501_DC_CRT_HWC_LOC:
        !           739:        ret = s->dc_crt_hwc_addr;
        !           740:        break;
        !           741:     case SM501_DC_CRT_HWC_COLOR_1_2:
        !           742:        ret = s->dc_crt_hwc_addr;
        !           743:        break;
        !           744:     case SM501_DC_CRT_HWC_COLOR_3:
        !           745:        ret = s->dc_crt_hwc_addr;
        !           746:        break;
        !           747: 
        !           748:     case SM501_DC_PANEL_PALETTE ... SM501_DC_PANEL_PALETTE + 0x400*3 - 4:
        !           749:         ret = sm501_palette_read(opaque, addr - SM501_DC_PANEL_PALETTE);
        !           750:         break;
        !           751: 
        !           752:     default:
        !           753:        printf("sm501 disp ctrl : not implemented register read."
        !           754:               " addr=%x\n", (int)addr);
        !           755:        assert(0);
        !           756:     }
        !           757: 
        !           758:     return ret;
        !           759: }
        !           760: 
        !           761: static void sm501_disp_ctrl_write(void *opaque,
        !           762:                                           target_phys_addr_t addr,
        !           763:                                           uint32_t value)
        !           764: {
        !           765:     SM501State * s = (SM501State *)opaque;
        !           766:     SM501_DPRINTF("sm501 disp ctrl regs : write addr=%x, val=%x\n",
        !           767:                  addr, value);
        !           768: 
        !           769:     switch(addr) {
        !           770:     case SM501_DC_PANEL_CONTROL:
        !           771:        s->dc_panel_control = value & 0x0FFF73FF;
        !           772:        break;
        !           773:     case SM501_DC_PANEL_PANNING_CONTROL:
        !           774:        s->dc_panel_panning_control = value & 0xFF3FFF3F;
        !           775:        break;
        !           776:     case SM501_DC_PANEL_FB_ADDR:
        !           777:        s->dc_panel_fb_addr = value & 0x8FFFFFF0;
        !           778:        break;
        !           779:     case SM501_DC_PANEL_FB_OFFSET:
        !           780:        s->dc_panel_fb_offset = value & 0x3FF03FF0;
        !           781:        break;
        !           782:     case SM501_DC_PANEL_FB_WIDTH:
        !           783:        s->dc_panel_fb_width = value & 0x0FFF0FFF;
        !           784:        break;
        !           785:     case SM501_DC_PANEL_FB_HEIGHT:
        !           786:        s->dc_panel_fb_height = value & 0x0FFF0FFF;
        !           787:        break;
        !           788:     case SM501_DC_PANEL_TL_LOC:
        !           789:        s->dc_panel_tl_location = value & 0x07FF07FF;
        !           790:        break;
        !           791:     case SM501_DC_PANEL_BR_LOC:
        !           792:        s->dc_panel_br_location = value & 0x07FF07FF;
        !           793:        break;
        !           794: 
        !           795:     case SM501_DC_PANEL_H_TOT:
        !           796:        s->dc_panel_h_total = value & 0x0FFF0FFF;
        !           797:        break;
        !           798:     case SM501_DC_PANEL_H_SYNC:
        !           799:        s->dc_panel_h_sync = value & 0x00FF0FFF;
        !           800:        break;
        !           801:     case SM501_DC_PANEL_V_TOT:
        !           802:        s->dc_panel_v_total = value & 0x0FFF0FFF;
        !           803:        break;
        !           804:     case SM501_DC_PANEL_V_SYNC:
        !           805:        s->dc_panel_v_sync = value & 0x003F0FFF;
        !           806:        break;
        !           807: 
        !           808:     case SM501_DC_PANEL_HWC_ADDR:
        !           809:        s->dc_panel_hwc_addr = value & 0x8FFFFFF0;
        !           810:        break;
        !           811:     case SM501_DC_PANEL_HWC_LOC:
        !           812:        s->dc_panel_hwc_addr = value & 0x0FFF0FFF;
        !           813:        break;
        !           814:     case SM501_DC_PANEL_HWC_COLOR_1_2:
        !           815:        s->dc_panel_hwc_addr = value;
        !           816:        break;
        !           817:     case SM501_DC_PANEL_HWC_COLOR_3:
        !           818:        s->dc_panel_hwc_addr = value & 0x0000FFFF;
        !           819:        break;
        !           820: 
        !           821:     case SM501_DC_CRT_CONTROL:
        !           822:        s->dc_crt_control = value & 0x0003FFFF;
        !           823:        break;
        !           824:     case SM501_DC_CRT_FB_ADDR:
        !           825:        s->dc_crt_fb_addr = value & 0x8FFFFFF0;
        !           826:        break;
        !           827:     case SM501_DC_CRT_FB_OFFSET:
        !           828:        s->dc_crt_fb_offset = value & 0x3FF03FF0;
        !           829:        break;
        !           830:     case SM501_DC_CRT_H_TOT:
        !           831:        s->dc_crt_h_total = value & 0x0FFF0FFF;
        !           832:        break;
        !           833:     case SM501_DC_CRT_H_SYNC:
        !           834:        s->dc_crt_h_sync = value & 0x00FF0FFF;
        !           835:        break;
        !           836:     case SM501_DC_CRT_V_TOT:
        !           837:        s->dc_crt_v_total = value & 0x0FFF0FFF;
        !           838:        break;
        !           839:     case SM501_DC_CRT_V_SYNC:
        !           840:        s->dc_crt_v_sync = value & 0x003F0FFF;
        !           841:        break;
        !           842: 
        !           843:     case SM501_DC_CRT_HWC_ADDR:
        !           844:        s->dc_crt_hwc_addr = value & 0x8FFFFFF0;
        !           845:        break;
        !           846:     case SM501_DC_CRT_HWC_LOC:
        !           847:        s->dc_crt_hwc_addr = value & 0x0FFF0FFF;
        !           848:        break;
        !           849:     case SM501_DC_CRT_HWC_COLOR_1_2:
        !           850:        s->dc_crt_hwc_addr = value;
        !           851:        break;
        !           852:     case SM501_DC_CRT_HWC_COLOR_3:
        !           853:        s->dc_crt_hwc_addr = value & 0x0000FFFF;
        !           854:        break;
        !           855: 
        !           856:     case SM501_DC_PANEL_PALETTE ... SM501_DC_PANEL_PALETTE + 0x400*3 - 4:
        !           857:         sm501_palette_write(opaque, addr - SM501_DC_PANEL_PALETTE, value);
        !           858:         break;
        !           859: 
        !           860:     default:
        !           861:        printf("sm501 disp ctrl : not implemented register write."
        !           862:               " addr=%x, val=%x\n", (int)addr, value);
        !           863:        assert(0);
        !           864:     }
        !           865: }
        !           866: 
        !           867: static CPUReadMemoryFunc *sm501_disp_ctrl_readfn[] = {
        !           868:     NULL,
        !           869:     NULL,
        !           870:     &sm501_disp_ctrl_read,
        !           871: };
        !           872: 
        !           873: static CPUWriteMemoryFunc *sm501_disp_ctrl_writefn[] = {
        !           874:     NULL,
        !           875:     NULL,
        !           876:     &sm501_disp_ctrl_write,
        !           877: };
        !           878: 
        !           879: /* draw line functions for all console modes */
        !           880: 
        !           881: #include "pixel_ops.h"
        !           882: 
        !           883: typedef void draw_line_func(uint8_t *d, const uint8_t *s,
        !           884:                            int width, const uint32_t *pal);
        !           885: 
        !           886: #define DEPTH 8
        !           887: #include "sm501_template.h"
        !           888: 
        !           889: #define DEPTH 15
        !           890: #include "sm501_template.h"
        !           891: 
        !           892: #define BGR_FORMAT
        !           893: #define DEPTH 15
        !           894: #include "sm501_template.h"
        !           895: 
        !           896: #define DEPTH 16
        !           897: #include "sm501_template.h"
        !           898: 
        !           899: #define BGR_FORMAT
        !           900: #define DEPTH 16
        !           901: #include "sm501_template.h"
        !           902: 
        !           903: #define DEPTH 32
        !           904: #include "sm501_template.h"
        !           905: 
        !           906: #define BGR_FORMAT
        !           907: #define DEPTH 32
        !           908: #include "sm501_template.h"
        !           909: 
        !           910: static draw_line_func * draw_line8_funcs[] = {
        !           911:     draw_line8_8,
        !           912:     draw_line8_15,
        !           913:     draw_line8_16,
        !           914:     draw_line8_32,
        !           915:     draw_line8_32bgr,
        !           916:     draw_line8_15bgr,
        !           917:     draw_line8_16bgr,
        !           918: };
        !           919: 
        !           920: static draw_line_func * draw_line16_funcs[] = {
        !           921:     draw_line16_8,
        !           922:     draw_line16_15,
        !           923:     draw_line16_16,
        !           924:     draw_line16_32,
        !           925:     draw_line16_32bgr,
        !           926:     draw_line16_15bgr,
        !           927:     draw_line16_16bgr,
        !           928: };
        !           929: 
        !           930: static draw_line_func * draw_line32_funcs[] = {
        !           931:     draw_line32_8,
        !           932:     draw_line32_15,
        !           933:     draw_line32_16,
        !           934:     draw_line32_32,
        !           935:     draw_line32_32bgr,
        !           936:     draw_line32_15bgr,
        !           937:     draw_line32_16bgr,
        !           938: };
        !           939: 
        !           940: static inline int get_depth_index(DisplayState *s)
        !           941: {
        !           942:     switch(ds_get_bits_per_pixel(s)) {
        !           943:     default:
        !           944:     case 8:
        !           945:        return 0;
        !           946:     case 15:
        !           947:         return 1;
        !           948:     case 16:
        !           949:         return 2;
        !           950:     case 32:
        !           951:         return 3;
        !           952:     }
        !           953: }
        !           954: 
        !           955: static void sm501_draw_crt(SM501State * s)
        !           956: {
        !           957:     int y;
        !           958:     int width = (s->dc_crt_h_total & 0x00000FFF) + 1;
        !           959:     int height = (s->dc_crt_v_total & 0x00000FFF) + 1;
        !           960: 
        !           961:     uint8_t  * src = s->local_mem;
        !           962:     int src_bpp = 0;
        !           963:     int dst_bpp = ds_get_bytes_per_pixel(s->ds) + (ds_get_bits_per_pixel(s->ds) % 8 ? 1 : 0);
        !           964:     uint32_t * palette = (uint32_t *)&s->dc_palette[SM501_DC_CRT_PALETTE
        !           965:                                                    - SM501_DC_PANEL_PALETTE];
        !           966:     int ds_depth_index = get_depth_index(s->ds);
        !           967:     draw_line_func * draw_line = NULL;
        !           968:     int full_update = 0;
        !           969:     int y_start = -1;
        !           970:     int page_min = 0x7fffffff;
        !           971:     int page_max = -1;
        !           972: 
        !           973:     /* choose draw_line function */
        !           974:     switch (s->dc_crt_control & 3) {
        !           975:     case SM501_DC_CRT_CONTROL_8BPP:
        !           976:        src_bpp = 1;
        !           977:        draw_line = draw_line8_funcs[ds_depth_index];
        !           978:        break;
        !           979:     case SM501_DC_CRT_CONTROL_16BPP:
        !           980:        src_bpp = 2;
        !           981:        draw_line = draw_line16_funcs[ds_depth_index];
        !           982:        break;
        !           983:     case SM501_DC_CRT_CONTROL_32BPP:
        !           984:        src_bpp = 4;
        !           985:        draw_line = draw_line32_funcs[ds_depth_index];
        !           986:        break;
        !           987:     default:
        !           988:        printf("sm501 draw crt : invalid DC_CRT_CONTROL=%x.\n",
        !           989:               s->dc_crt_control);
        !           990:        assert(0);
        !           991:        break;
        !           992:     }
        !           993: 
        !           994:     /* adjust console size */
        !           995:     if (s->last_width != width || s->last_height != height) {
        !           996:        qemu_console_resize(s->ds, width, height);
        !           997:        s->last_width = width;
        !           998:        s->last_height = height;
        !           999:        full_update = 1;
        !          1000:     }
        !          1001: 
        !          1002:     /* draw each line according to conditions */
        !          1003:     for (y = 0; y < height; y++) {
        !          1004:        int update = full_update;
        !          1005:        uint8_t * line_end = &src[width * src_bpp - 1];
        !          1006:        int page0 = (src - phys_ram_base) & TARGET_PAGE_MASK;
        !          1007:        int page1 = (line_end - phys_ram_base) & TARGET_PAGE_MASK;
        !          1008:        int page;
        !          1009: 
        !          1010:        /* check dirty flags for each line */
        !          1011:        for (page = page0; page <= page1; page += TARGET_PAGE_SIZE)
        !          1012:            if (cpu_physical_memory_get_dirty(page, VGA_DIRTY_FLAG))
        !          1013:                update = 1;
        !          1014: 
        !          1015:        /* draw line and change status */
        !          1016:        if (update) {
        !          1017:            draw_line(&(ds_get_data(s->ds)[y * width * dst_bpp]), src, width, palette);
        !          1018:            if (y_start < 0)
        !          1019:                y_start = y;
        !          1020:            if (page0 < page_min)
        !          1021:                page_min = page0;
        !          1022:            if (page1 > page_max)
        !          1023:                page_max = page1;
        !          1024:        } else {
        !          1025:            if (y_start >= 0) {
        !          1026:                /* flush to display */
        !          1027:                dpy_update(s->ds, 0, y_start, width, y - y_start);
        !          1028:                y_start = -1;
        !          1029:            }
        !          1030:        }
        !          1031: 
        !          1032:        src += width * src_bpp;
        !          1033:     }
        !          1034: 
        !          1035:     /* complete flush to display */
        !          1036:     if (y_start >= 0)
        !          1037:        dpy_update(s->ds, 0, y_start, width, y - y_start);
        !          1038: 
        !          1039:     /* clear dirty flags */
        !          1040:     if (page_max != -1)
        !          1041:        cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE,
        !          1042:                                        VGA_DIRTY_FLAG);
        !          1043: }
        !          1044: 
        !          1045: static void sm501_update_display(void *opaque)
        !          1046: {
        !          1047:     SM501State * s = (SM501State *)opaque;
        !          1048: 
        !          1049:     if (s->dc_crt_control & SM501_DC_CRT_CONTROL_ENABLE)
        !          1050:        sm501_draw_crt(s);
        !          1051: }
        !          1052: 
        !          1053: void sm501_init(uint32_t base, unsigned long local_mem_base,
        !          1054:                uint32_t local_mem_bytes, CharDriverState *chr)
        !          1055: {
        !          1056:     SM501State * s;
        !          1057:     int sm501_system_config_index;
        !          1058:     int sm501_disp_ctrl_index;
        !          1059: 
        !          1060:     /* allocate management data region */
        !          1061:     s = (SM501State *)qemu_mallocz(sizeof(SM501State));
        !          1062:     s->base = base;
        !          1063:     s->local_mem_size_index
        !          1064:        = get_local_mem_size_index(local_mem_bytes);
        !          1065:     SM501_DPRINTF("local mem size=%x. index=%d\n", get_local_mem_size(s),
        !          1066:                  s->local_mem_size_index);
        !          1067:     s->system_control = 0x00100000;
        !          1068:     s->misc_control = 0x00001000; /* assumes SH, active=low */
        !          1069:     s->dc_panel_control = 0x00010000;
        !          1070:     s->dc_crt_control = 0x00010000;
        !          1071: 
        !          1072:     /* allocate local memory */
        !          1073:     s->local_mem = (uint8 *)phys_ram_base + local_mem_base;
        !          1074:     cpu_register_physical_memory(base, local_mem_bytes, local_mem_base);
        !          1075: 
        !          1076:     /* map mmio */
        !          1077:     sm501_system_config_index
        !          1078:        = cpu_register_io_memory(0, sm501_system_config_readfn,
        !          1079:                                 sm501_system_config_writefn, s);
        !          1080:     cpu_register_physical_memory(base + MMIO_BASE_OFFSET,
        !          1081:                                 0x6c, sm501_system_config_index);
        !          1082:     sm501_disp_ctrl_index = cpu_register_io_memory(0, sm501_disp_ctrl_readfn,
        !          1083:                                                   sm501_disp_ctrl_writefn, s);
        !          1084:     cpu_register_physical_memory(base + MMIO_BASE_OFFSET + SM501_DC,
        !          1085:                                  0x1000, sm501_disp_ctrl_index);
        !          1086: 
        !          1087:     /* bridge to serial emulation module */
        !          1088:     if (chr)
        !          1089:        serial_mm_init(base + MMIO_BASE_OFFSET + SM501_UART0, 2,
        !          1090:                       0, /* TODO : chain irq to IRL */
        !          1091:                       115200, chr, 1);
        !          1092: 
        !          1093:     /* create qemu graphic console */
        !          1094:     s->ds = graphic_console_init(sm501_update_display, NULL,
        !          1095:                                 NULL, NULL, s);
        !          1096: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.