Annotation of tme/machine/sun/sun-cgsix.c, revision 1.1

1.1     ! root        1: /* $Id: sun-cgsix.c,v 1.3 2010/06/05 19:16:12 fredette Exp $ */
        !             2: 
        !             3: /* machine/sun/sun-cgsix.c - Sun cgsix emulation: */
        !             4: 
        !             5: /*
        !             6:  * Copyright (c) 2009 Fredette
        !             7:  * All rights reserved.
        !             8:  *
        !             9:  * Redistribution and use in source and binary forms, with or without
        !            10:  * modification, are permitted provided that the following conditions
        !            11:  * are met:
        !            12:  * 1. Redistributions of source code must retain the above copyright
        !            13:  *    notice, this list of conditions and the following disclaimer.
        !            14:  * 2. Redistributions in binary form must reproduce the above copyright
        !            15:  *    notice, this list of conditions and the following disclaimer in the
        !            16:  *    documentation and/or other materials provided with the distribution.
        !            17:  * 3. All advertising materials mentioning features or use of this software
        !            18:  *    must display the following acknowledgement:
        !            19:  *      This product includes software developed by Matt Fredette.
        !            20:  * 4. The name of the author may not be used to endorse or promote products
        !            21:  *    derived from this software without specific prior written permission.
        !            22:  *
        !            23:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            24:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
        !            25:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
        !            26:  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
        !            27:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
        !            28:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
        !            29:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            30:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
        !            31:  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
        !            32:  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        !            33:  * POSSIBILITY OF SUCH DAMAGE.
        !            34:  */
        !            35: 
        !            36: #include <tme/common.h>
        !            37: _TME_RCSID("$Id: sun-cgsix.c,v 1.3 2010/06/05 19:16:12 fredette Exp $");
        !            38: 
        !            39: /* includes: */
        !            40: #include <tme/machine/sun.h>
        !            41: #include <tme/generic/bus-device.h>
        !            42: #include <tme/generic/fb.h>
        !            43: #include "sun-fb.h"
        !            44: 
        !            45: /* macros: */
        !            46: 
        !            47: /* cgsix types: */
        !            48: #define TME_SUNCG6_TYPE_NULL           (0)
        !            49: #define TME_SUNCG6_TYPE_501_2325       (1)
        !            50: 
        !            51: /* register subregions: */
        !            52: #define tme_suncg6_bus_subregion_p4 tme_suncg6_sunfb.tme_sunfb_bus_subregion_regs
        !            53: #define tme_suncg6_bus_handler_p4 tme_suncg6_sunfb.tme_sunfb_bus_handler_regs
        !            54: #define tme_suncg6_bus_subregion_fbc tme_suncg6_sunfb.tme_sunfb_bus_subregions[1]
        !            55: #define tme_suncg6_bus_handler_fbc tme_suncg6_sunfb.tme_sunfb_bus_handlers[1]
        !            56: #define tme_suncg6_bus_subregion_dac tme_suncg6_sunfb.tme_sunfb_bus_subregions[2]
        !            57: #define tme_suncg6_bus_handler_dac tme_suncg6_sunfb.tme_sunfb_bus_handlers[2]
        !            58: #define tme_suncg6_bus_subregion_fhc_thc tme_suncg6_sunfb.tme_sunfb_bus_subregions[4]
        !            59: #define tme_suncg6_bus_handler_fhc_thc tme_suncg6_sunfb.tme_sunfb_bus_handlers[4]
        !            60: #define tme_suncg6_bus_subregion_tec tme_suncg6_sunfb.tme_sunfb_bus_subregions[3]
        !            61: #define tme_suncg6_bus_handler_tec tme_suncg6_sunfb.tme_sunfb_bus_handlers[3]
        !            62: #define tme_suncg6_bus_subregion_alt tme_suncg6_sunfb.tme_sunfb_bus_subregions[6]
        !            63: #define tme_suncg6_bus_handler_alt tme_suncg6_sunfb.tme_sunfb_bus_handlers[6]
        !            64: 
        !            65: /* this converts a group member to a register offset: */
        !            66: #define _TME_SUNCG6_REG_X(module_cap, module, n, x)            \
        !            67:   (_TME_CONCAT4(TME_SUNCG6_REG_,module_cap,_GROUP,n)           \
        !            68:    + ((tme_uint8_t *) &((struct tme_suncg6 *) 0)               \
        !            69:       ->_TME_CONCAT4(tme_suncg6_,module,_group,n)              \
        !            70:       ._TME_CONCAT4(tme_suncg6_,module,_,x))                   \
        !            71:    - ((tme_uint8_t *) &((struct tme_suncg6 *) 0)               \
        !            72:       ->_TME_CONCAT4(tme_suncg6_,module,_group,n)))
        !            73: 
        !            74: /* this expands part of a large ternary expression that converts a
        !            75:    register address into pointer to a register: */
        !            76: #define TME_SUNCG6_REG_POINTER(suncg6, reg, module_cap, module, n)\
        !            77:   (((reg)                                                      \
        !            78:     >= _TME_CONCAT4(TME_SUNCG6_REG_,module_cap,_GROUP,n))      \
        !            79:    && ((reg)                                                   \
        !            80:        < (_TME_CONCAT4(TME_SUNCG6_REG_,module_cap,_GROUP,n)    \
        !            81:          + sizeof((suncg6)                                     \
        !            82:                   ->_TME_CONCAT4(tme_suncg6_,module,_group,n)))))\
        !            83:   ? (((tme_suncg6_reg_t *)                                     \
        !            84:       &((suncg6)                                               \
        !            85:        ->_TME_CONCAT4(tme_suncg6_,module,_group,n)))           \
        !            86:      + (((reg)                                                 \
        !            87:         - _TME_CONCAT4(TME_SUNCG6_REG_,module_cap,_GROUP,n))   \
        !            88:        / sizeof(tme_suncg6_reg_t)))
        !            89:  
        !            90: /* some register offsets and sizes: */
        !            91: #define TME_SUNCG6_REG_DAC                     (0x200000)
        !            92: #define TME_SUNCG6_REG_ALT                     (0x280000)
        !            93: #define TME_SUNCG6_SIZ_ALT                     (0x1000)
        !            94: #define TME_SUNCG6_REG_THC(n,x)                        _TME_SUNCG6_REG_X(THC,thc,n,x)
        !            95: #define TME_SUNCG6_SIZ_THC                     (0x1000)
        !            96: #define TME_SUNCG6_REG_FBC(n,x)                        _TME_SUNCG6_REG_X(FBC,fbc,n,x)
        !            97: #define TME_SUNCG6_REG_TEC(n,x)                        _TME_SUNCG6_REG_X(TEC,tec,n,x)
        !            98: #define TME_SUNCG6_TEC_SIZE                    (0x1000)
        !            99: 
        !           100: /* the FHC register: */
        !           101: #define        TME_SUNCG6_FHC_ID_MASK                  (0xff000000)
        !           102: #define        TME_SUNCG6_FHC_REVISION_MASK            (0x00f00000)
        !           103: #define        TME_SUNCG6_FHC_DISABLE_FROP             (0x00080000)
        !           104: #define        TME_SUNCG6_FHC_DISABLE_ROW              (0x00040000)
        !           105: #define        TME_SUNCG6_FHC_DISABLE_SRC              (0x00020000)
        !           106: #define        TME_SUNCG6_FHC_DISABLE_DST              (0x00010000)
        !           107: #define        TME_SUNCG6_FHC_RESET                    (0x00008000)
        !           108: #define        TME_SUNCG6_FHC_ENDIAN_LITTLE            (0x00002000)
        !           109: #define        TME_SUNCG6_FHC_SIZE_MASK                (0x00001800)
        !           110: #define         TME_SUNCG6_FHC_SIZE_1024_768            (0x00000000)
        !           111: #define         TME_SUNCG6_FHC_SIZE_1152_900            (0x00000800)
        !           112: #define         TME_SUNCG6_FHC_SIZE_1280_1024           (0x00001000)
        !           113: #define         TME_SUNCG6_FHC_SIZE_1600_1280           (0x00001800)
        !           114: #define        TME_SUNCG6_FHC_CPU_MASK                 (0x00000600)
        !           115: #define         TME_SUNCG6_FHC_CPU_SPARC                (0x00000000)
        !           116: #define         TME_SUNCG6_FHC_CPU_68K                  (0x00000200)
        !           117: #define         TME_SUNCG6_FHC_CPU_IA32                 (0x00000400)
        !           118: #define        TME_SUNCG6_FHC_TEST                     (0x00000100)
        !           119: #define        TME_SUNCG6_FHC_TESTX_MASK               (0x000000f0)
        !           120: #define        TME_SUNCG6_FHC_TESTY_MASK               (0x0000000f)
        !           121: 
        !           122: /* the THC miscellaneous register: */
        !           123: #define        TME_SUNCG6_THC_MISC_UNKNOWN_20          (0xfff00000)
        !           124: #define        TME_SUNCG6_THC_MISC_REVISION_MASK       (0x000f0000)
        !           125: #define        TME_SUNCG6_THC_MISC_UNKNOWN_13          (0x0000e000)
        !           126: #define        TME_SUNCG6_THC_MISC_RESET               (0x00001000)
        !           127: #define        TME_SUNCG6_THC_MISC_UNKNOWN_11          (0x00000800)
        !           128: #define        TME_SUNCG6_THC_MISC_ENABLE_VIDEO        (0x00000400)
        !           129: #define        TME_SUNCG6_THC_MISC_SYNC                (0x00000200)
        !           130: #define        TME_SUNCG6_THC_MISC_VSYNC               (0x00000100)
        !           131: #define        TME_SUNCG6_THC_MISC_ENABLE_SYNC         (0x00000080)
        !           132: #define        TME_SUNCG6_THC_MISC_CURSOR_RESOLUTION   (0x00000040)
        !           133: #define        TME_SUNCG6_THC_MISC_INT_ENABLE          (0x00000020)
        !           134: #define        TME_SUNCG6_THC_MISC_INT_ACTIVE          (0x00000010)
        !           135: #define        TME_SUNCG6_THC_MISC_UNKNOWN_0           (0x0000000f)
        !           136: 
        !           137: /* the FBC rasterop register: */
        !           138: #define TME_SUNCG6_FBC_RASTEROP_PLANE_ONES     (0x80000000)
        !           139: #define TME_SUNCG6_FBC_RASTEROP_PLANE_ZEROES   (0x40000000)
        !           140: #define TME_SUNCG6_FBC_RASTEROP_PIXEL_ONES     (0x20000000)
        !           141: #define TME_SUNCG6_FBC_RASTEROP_PIXEL_ZEROES   (0x10000000)
        !           142: #define TME_SUNCG6_FBC_RASTEROP_PATTERN_ONES   (0x08000000)
        !           143: #define TME_SUNCG6_FBC_RASTEROP_PATTERN_ZEROES (0x04000000)
        !           144: #define TME_SUNCG6_FBC_RASTEROP_POLYG_NONOVERLAP (0x02000000)
        !           145: #define TME_SUNCG6_FBC_RASTEROP_POLYG_OVERLAP  (0x01000000)
        !           146: #define TME_SUNCG6_FBC_RASTEROP_ATTR_SUPP      (0x00800000)
        !           147: #define TME_SUNCG6_FBC_RASTEROP_ATTR_UNSUPP    (0x00400000)
        !           148: #define TME_SUNCG6_FBC_RASTEROP_RAST_BOOL      (0x00000000)
        !           149: #define TME_SUNCG6_FBC_RASTEROP_RAST_LINEAR    (0x00020000)
        !           150: #define TME_SUNCG6_FBC_RASTEROP_PLOT_PLOT      (0x00000000)
        !           151: #define TME_SUNCG6_FBC_RASTEROP_PLOT_UNPLOT    (0x00010000)
        !           152: #define TME_SUNCG6_FBC_RASTEROP_ROP_11_1(x)    ((x) << 14)
        !           153: #define TME_SUNCG6_FBC_RASTEROP_ROP_11_0(x)    ((x) << 12)
        !           154: #define TME_SUNCG6_FBC_RASTEROP_ROP_10_1(x)    ((x) << 10)
        !           155: #define TME_SUNCG6_FBC_RASTEROP_ROP_10_0(x)    ((x) <<  8)
        !           156: #define TME_SUNCG6_FBC_RASTEROP_ROP_01_1(x)    ((x) <<  6)
        !           157: #define TME_SUNCG6_FBC_RASTEROP_ROP_01_0(x)    ((x) <<  4)
        !           158: #define TME_SUNCG6_FBC_RASTEROP_ROP_00_1(x)    ((x) <<  2)
        !           159: #define TME_SUNCG6_FBC_RASTEROP_ROP_00_0(x)    ((x) <<  0)
        !           160: #define  TME_SUNCG6_FBC_RASTEROP_ROP_CLEAR      (0x0)
        !           161: #define  TME_SUNCG6_FBC_RASTEROP_ROP_INVERT     (0x1)
        !           162: #define  TME_SUNCG6_FBC_RASTEROP_ROP_NOP        (0x2)
        !           163: #define  TME_SUNCG6_FBC_RASTEROP_ROP_SET        (0x3)
        !           164: 
        !           165: /* common FBC rasterop functions: */
        !           166: 
        !           167: /* copy: */
        !           168: #define TME_SUNCG6_FBC_RASTEROP_FUNC_COPY                                      \
        !           169:   (TME_SUNCG6_FBC_RASTEROP_PLANE_ONES                                          \
        !           170:    | TME_SUNCG6_FBC_RASTEROP_PIXEL_ONES                                                \
        !           171:    | TME_SUNCG6_FBC_RASTEROP_PATTERN_ONES                                      \
        !           172:    | TME_SUNCG6_FBC_RASTEROP_POLYG_OVERLAP                                     \
        !           173:    | TME_SUNCG6_FBC_RASTEROP_ATTR_SUPP                                         \
        !           174:    | TME_SUNCG6_FBC_RASTEROP_ROP_11_1(TME_SUNCG6_FBC_RASTEROP_ROP_SET)         \
        !           175:    | TME_SUNCG6_FBC_RASTEROP_ROP_11_0(TME_SUNCG6_FBC_RASTEROP_ROP_CLEAR)       \
        !           176:    | TME_SUNCG6_FBC_RASTEROP_ROP_10_1(TME_SUNCG6_FBC_RASTEROP_ROP_SET)         \
        !           177:    | TME_SUNCG6_FBC_RASTEROP_ROP_10_0(TME_SUNCG6_FBC_RASTEROP_ROP_CLEAR)       \
        !           178:    | TME_SUNCG6_FBC_RASTEROP_ROP_01_1(TME_SUNCG6_FBC_RASTEROP_ROP_SET)         \
        !           179:    | TME_SUNCG6_FBC_RASTEROP_ROP_01_0(TME_SUNCG6_FBC_RASTEROP_ROP_CLEAR)       \
        !           180:    | TME_SUNCG6_FBC_RASTEROP_ROP_00_1(TME_SUNCG6_FBC_RASTEROP_ROP_SET)         \
        !           181:    | TME_SUNCG6_FBC_RASTEROP_ROP_00_0(TME_SUNCG6_FBC_RASTEROP_ROP_CLEAR))
        !           182: 
        !           183: /* fill: */
        !           184: #define TME_SUNCG6_FBC_RASTEROP_FUNC_FILL                                      \
        !           185:   (TME_SUNCG6_FBC_RASTEROP_PLANE_ONES                                          \
        !           186:    | TME_SUNCG6_FBC_RASTEROP_PIXEL_ONES                                                \
        !           187:    | TME_SUNCG6_FBC_RASTEROP_PATTERN_ONES                                      \
        !           188:    | TME_SUNCG6_FBC_RASTEROP_POLYG_OVERLAP                                     \
        !           189:    | TME_SUNCG6_FBC_RASTEROP_ATTR_SUPP                                         \
        !           190:    | TME_SUNCG6_FBC_RASTEROP_ROP_11_1(TME_SUNCG6_FBC_RASTEROP_ROP_SET)         \
        !           191:    | TME_SUNCG6_FBC_RASTEROP_ROP_11_0(TME_SUNCG6_FBC_RASTEROP_ROP_SET)         \
        !           192:    | TME_SUNCG6_FBC_RASTEROP_ROP_10_1(TME_SUNCG6_FBC_RASTEROP_ROP_SET)         \
        !           193:    | TME_SUNCG6_FBC_RASTEROP_ROP_10_0(TME_SUNCG6_FBC_RASTEROP_ROP_SET)         \
        !           194:    | TME_SUNCG6_FBC_RASTEROP_ROP_01_1(TME_SUNCG6_FBC_RASTEROP_ROP_CLEAR)       \
        !           195:    | TME_SUNCG6_FBC_RASTEROP_ROP_01_0(TME_SUNCG6_FBC_RASTEROP_ROP_CLEAR)       \
        !           196:    | TME_SUNCG6_FBC_RASTEROP_ROP_00_1(TME_SUNCG6_FBC_RASTEROP_ROP_CLEAR)       \
        !           197:    | TME_SUNCG6_FBC_RASTEROP_ROP_00_0(TME_SUNCG6_FBC_RASTEROP_ROP_CLEAR))
        !           198: 
        !           199: /* flip: */
        !           200: #define TME_SUNCG6_FBC_RASTEROP_FUNC_FLIP                                      \
        !           201:   (TME_SUNCG6_FBC_RASTEROP_PLANE_ONES                                          \
        !           202:    | TME_SUNCG6_FBC_RASTEROP_PIXEL_ONES                                                \
        !           203:    | TME_SUNCG6_FBC_RASTEROP_PATTERN_ONES                                      \
        !           204:    | TME_SUNCG6_FBC_RASTEROP_POLYG_OVERLAP                                     \
        !           205:    | TME_SUNCG6_FBC_RASTEROP_ATTR_SUPP                                         \
        !           206:    | TME_SUNCG6_FBC_RASTEROP_ROP_11_1(TME_SUNCG6_FBC_RASTEROP_ROP_INVERT)      \
        !           207:    | TME_SUNCG6_FBC_RASTEROP_ROP_11_0(TME_SUNCG6_FBC_RASTEROP_ROP_INVERT)      \
        !           208:    | TME_SUNCG6_FBC_RASTEROP_ROP_10_1(TME_SUNCG6_FBC_RASTEROP_ROP_INVERT)      \
        !           209:    | TME_SUNCG6_FBC_RASTEROP_ROP_10_0(TME_SUNCG6_FBC_RASTEROP_ROP_INVERT)      \
        !           210:    | TME_SUNCG6_FBC_RASTEROP_ROP_01_1(TME_SUNCG6_FBC_RASTEROP_ROP_INVERT)      \
        !           211:    | TME_SUNCG6_FBC_RASTEROP_ROP_01_0(TME_SUNCG6_FBC_RASTEROP_ROP_INVERT)      \
        !           212:    | TME_SUNCG6_FBC_RASTEROP_ROP_00_1(TME_SUNCG6_FBC_RASTEROP_ROP_INVERT)      \
        !           213:    | TME_SUNCG6_FBC_RASTEROP_ROP_00_0(TME_SUNCG6_FBC_RASTEROP_ROP_INVERT))
        !           214: 
        !           215: /* NB: I couldn't reason out how the rop?? values work.  the values
        !           216:    used by X11 and the NetBSD cgsix driver make some sense, but the
        !           217:    0x6c60 used by the SUNW,501-2325 PROM for all of its blits and
        !           218:    draws is confusing: */
        !           219: #define TME_SUNCG6_FBC_RASTEROP_FUNC_PROM                                      \
        !           220:   (TME_SUNCG6_FBC_RASTEROP_PLANE_ONES                                          \
        !           221:    | TME_SUNCG6_FBC_RASTEROP_PIXEL_ONES                                                \
        !           222:    | TME_SUNCG6_FBC_RASTEROP_PATTERN_ONES                                      \
        !           223:    | TME_SUNCG6_FBC_RASTEROP_POLYG_OVERLAP                                     \
        !           224:    | TME_SUNCG6_FBC_RASTEROP_ATTR_SUPP                                         \
        !           225:    | TME_SUNCG6_FBC_RASTEROP_ROP_11_1(TME_SUNCG6_FBC_RASTEROP_ROP_INVERT)      \
        !           226:    | TME_SUNCG6_FBC_RASTEROP_ROP_11_0(TME_SUNCG6_FBC_RASTEROP_ROP_NOP)         \
        !           227:    | TME_SUNCG6_FBC_RASTEROP_ROP_10_1(TME_SUNCG6_FBC_RASTEROP_ROP_SET)         \
        !           228:    | TME_SUNCG6_FBC_RASTEROP_ROP_10_0(TME_SUNCG6_FBC_RASTEROP_ROP_CLEAR)       \
        !           229:    | TME_SUNCG6_FBC_RASTEROP_ROP_01_1(TME_SUNCG6_FBC_RASTEROP_ROP_INVERT)      \
        !           230:    | TME_SUNCG6_FBC_RASTEROP_ROP_01_0(TME_SUNCG6_FBC_RASTEROP_ROP_NOP)         \
        !           231:    | TME_SUNCG6_FBC_RASTEROP_ROP_00_1(TME_SUNCG6_FBC_RASTEROP_ROP_CLEAR)       \
        !           232:    | TME_SUNCG6_FBC_RASTEROP_ROP_00_0(TME_SUNCG6_FBC_RASTEROP_ROP_CLEAR))
        !           233: 
        !           234: /* types: */
        !           235: 
        !           236: /* the cgsix pixel is eight bits: */
        !           237: typedef tme_uint8_t tme_suncg6_pixel_t;
        !           238: 
        !           239: /* all cgsix registers are at least 32-bit aligned: */
        !           240: typedef tme_uint32_t tme_suncg6_reg_t;
        !           241: 
        !           242: /* the card: */
        !           243: struct tme_suncg6 {
        !           244: 
        !           245:   /* our generic Sun framebuffer: */
        !           246:   struct tme_sunfb tme_suncg6_sunfb;
        !           247: #define tme_suncg6_mutex tme_suncg6_sunfb.tme_sunfb_mutex
        !           248: #define tme_suncg6_bus_subregion_memory tme_suncg6_sunfb.tme_sunfb_bus_subregion_memory
        !           249: #define tme_suncg6_bus_subregion_regs tme_suncg6_sunfb.tme_sunfb_bus_subregion_regs
        !           250: 
        !           251:   /* the type of the cgsix: */
        !           252:   tme_uint32_t tme_suncg6_type;
        !           253: 
        !           254:   /* the current framebuffer width and height: */
        !           255:   tme_uint32_t tme_suncg6_width;
        !           256:   tme_uint32_t tme_suncg6_height;
        !           257: 
        !           258:   /* the FHC: */
        !           259: #define TME_SUNCG6_REG_FHC                     (0x300000)
        !           260:   tme_suncg6_reg_t tme_suncg6_fhc;
        !           261: 
        !           262:   /* the THC: */
        !           263: #define TME_SUNCG6_REG_THC_UNKNOWN_0x0         (0x301000)
        !           264:   struct {
        !           265: #define TME_SUNCG6_REG_THC_GROUP0              (0x301090)
        !           266:     tme_suncg6_reg_t tme_suncg6_thc_unknown_0x90;
        !           267:     tme_suncg6_reg_t tme_suncg6_thc_unknown_0x94;
        !           268:   } tme_suncg6_thc_group0;
        !           269:   struct {
        !           270: #define TME_SUNCG6_REG_THC_GROUP1              (0x301800)
        !           271:     tme_suncg6_reg_t tme_suncg6_thc_hsync1;
        !           272:     tme_suncg6_reg_t tme_suncg6_thc_hsync2;
        !           273:     tme_suncg6_reg_t tme_suncg6_thc_hsync3;
        !           274:     tme_suncg6_reg_t tme_suncg6_thc_vsync1;
        !           275:     tme_suncg6_reg_t tme_suncg6_thc_vsync2;
        !           276:     tme_suncg6_reg_t tme_suncg6_thc_refresh;
        !           277:     tme_suncg6_reg_t tme_suncg6_thc_misc;
        !           278:     tme_suncg6_reg_t tme_suncg6_thc_unknown_0x81c[56];
        !           279:     tme_suncg6_reg_t tme_suncg6_thc_cursor_xy;
        !           280:     tme_suncg6_reg_t tme_suncg6_thc_cursor_mask[32];
        !           281:     tme_suncg6_reg_t tme_suncg6_thc_cursor_bits[32];
        !           282:   } tme_suncg6_thc_group1;
        !           283: 
        !           284:   /* the FBC: */
        !           285:   struct {
        !           286: #define TME_SUNCG6_REG_FBC_GROUP0              (0x700000)
        !           287:     tme_suncg6_reg_t tme_suncg6_fbc_unknown_0x0;
        !           288:     tme_suncg6_reg_t tme_suncg6_fbc_misc;
        !           289:     tme_suncg6_reg_t tme_suncg6_fbc_clip_check;
        !           290:     tme_suncg6_reg_t tme_suncg6_fbc_unknown_0xc;
        !           291:     tme_suncg6_reg_t tme_suncg6_fbc_status;
        !           292:     tme_suncg6_reg_t tme_suncg6_fbc_status_draw;
        !           293:     tme_suncg6_reg_t tme_suncg6_fbc_status_blit;
        !           294:     tme_suncg6_reg_t tme_suncg6_fbc_font;
        !           295:     tme_suncg6_reg_t tme_suncg6_fbc_unknown_0x20[24];
        !           296:     tme_suncg6_reg_t tme_suncg6_fbc_x0;
        !           297:     tme_suncg6_reg_t tme_suncg6_fbc_y0;
        !           298:     tme_suncg6_reg_t tme_suncg6_fbc_z0;
        !           299:     tme_suncg6_reg_t tme_suncg6_fbc_color0;
        !           300:     tme_suncg6_reg_t tme_suncg6_fbc_x1;
        !           301:     tme_suncg6_reg_t tme_suncg6_fbc_y1;
        !           302:     tme_suncg6_reg_t tme_suncg6_fbc_z1;
        !           303:     tme_suncg6_reg_t tme_suncg6_fbc_color1;
        !           304:     tme_suncg6_reg_t tme_suncg6_fbc_x2;
        !           305:     tme_suncg6_reg_t tme_suncg6_fbc_y2;
        !           306:     tme_suncg6_reg_t tme_suncg6_fbc_z2;
        !           307:     tme_suncg6_reg_t tme_suncg6_fbc_color2;
        !           308:     tme_suncg6_reg_t tme_suncg6_fbc_x3;
        !           309:     tme_suncg6_reg_t tme_suncg6_fbc_y3;
        !           310:     tme_suncg6_reg_t tme_suncg6_fbc_z3;
        !           311:     tme_suncg6_reg_t tme_suncg6_fbc_color3;
        !           312:     tme_suncg6_reg_t tme_suncg6_fbc_offx;
        !           313:     tme_suncg6_reg_t tme_suncg6_fbc_offy;
        !           314:     tme_suncg6_reg_t tme_suncg6_fbc_unknown_0xc8[2];
        !           315:     tme_suncg6_reg_t tme_suncg6_fbc_inc_x;
        !           316:     tme_suncg6_reg_t tme_suncg6_fbc_inc_y;
        !           317:     tme_suncg6_reg_t tme_suncg6_fbc_unknown_0xd8[2];
        !           318:     tme_suncg6_reg_t tme_suncg6_fbc_clip_min_x;
        !           319:     tme_suncg6_reg_t tme_suncg6_fbc_clip_min_y;
        !           320:     tme_suncg6_reg_t tme_suncg6_fbc_unknown_0xe8[2];
        !           321:     tme_suncg6_reg_t tme_suncg6_fbc_clip_max_x;
        !           322:     tme_suncg6_reg_t tme_suncg6_fbc_clip_max_y;
        !           323:     tme_suncg6_reg_t tme_suncg6_fbc_unknown_0xf8[2];
        !           324:     tme_suncg6_reg_t tme_suncg6_fbc_fg;
        !           325:     tme_suncg6_reg_t tme_suncg6_fbc_bg;
        !           326:     tme_suncg6_reg_t tme_suncg6_fbc_rasterop;
        !           327:     tme_suncg6_reg_t tme_suncg6_fbc_pm;
        !           328:     tme_suncg6_reg_t tme_suncg6_fbc_pixelm;
        !           329:     tme_suncg6_reg_t tme_suncg6_fbc_unknown_0x114[2];
        !           330:     tme_suncg6_reg_t tme_suncg6_fbc_patalign;
        !           331:     tme_suncg6_reg_t tme_suncg6_fbc_pattern[8];
        !           332:   } tme_suncg6_fbc_group0;
        !           333:   struct {
        !           334: #define TME_SUNCG6_REG_FBC_GROUP1              (0x700900)
        !           335:     tme_suncg6_reg_t tme_suncg6_fbc_rect_abs_x;
        !           336:     tme_suncg6_reg_t tme_suncg6_fbc_rect_abs_y;
        !           337:   } tme_suncg6_fbc_group1;
        !           338: 
        !           339:   /* in the FBC, the rectangle absolute coordinate registers seem to
        !           340:      be indexed: */
        !           341: #define TME_SUNCG6_RECT_ABS_COUNT              (2)
        !           342:   unsigned int tme_suncg6_fbc_rect_abs_x_i;
        !           343:   unsigned int tme_suncg6_fbc_rect_abs_y_i;
        !           344:   tme_suncg6_reg_t tme_suncg6_fbc_rect_abs_x[TME_SUNCG6_RECT_ABS_COUNT];
        !           345:   tme_suncg6_reg_t tme_suncg6_fbc_rect_abs_y[TME_SUNCG6_RECT_ABS_COUNT];
        !           346: 
        !           347:   /* the TEC: */
        !           348:   struct {
        !           349: #define TME_SUNCG6_REG_TEC_GROUP0              (0x701000)
        !           350:     tme_suncg6_reg_t tme_suncg6_tec_mv;
        !           351:     tme_suncg6_reg_t tme_suncg6_tec_clip;
        !           352:     tme_suncg6_reg_t tme_suncg6_tec_vdc;
        !           353:   } tme_suncg6_tec_group0;
        !           354: };
        !           355: 
        !           356: /* this does a blit: */
        !           357: static void
        !           358: _tme_suncg6_blit(struct tme_suncg6 *suncg6)
        !           359: {
        !           360:   tme_uint32_t fb_width;
        !           361:   tme_uint32_t fb_height;
        !           362:   tme_int32_t src_x;
        !           363:   tme_int32_t src_y;
        !           364:   tme_int32_t dst_x;
        !           365:   tme_int32_t dst_y;
        !           366:   tme_int32_t blit_width;
        !           367:   tme_int32_t blit_height;
        !           368:   int unsupported;
        !           369:   tme_uint32_t offset_updated_first;
        !           370:   tme_uint32_t offset_updated_last;
        !           371:   const tme_suncg6_pixel_t *src;
        !           372:   tme_suncg6_pixel_t *dst;
        !           373: 
        !           374:   /* get the framebuffer width and height: */
        !           375:   fb_width = suncg6->tme_suncg6_width;
        !           376:   fb_height = suncg6->tme_suncg6_height;
        !           377: 
        !           378:   /* get the blit source: */
        !           379:   src_x = suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_x0;
        !           380:   src_y = suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_y0;
        !           381: 
        !           382:   /* get the blit destination: */
        !           383:   dst_x = suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_x2;
        !           384:   dst_y = suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_y2;
        !           385: 
        !           386:   /* get the blit width and height: */
        !           387:   blit_width = suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_x1;
        !           388:   blit_width
        !           389:     = (blit_width < src_x
        !           390:        ? 0
        !           391:        : (blit_width + 1 - src_x));
        !           392:   blit_height = suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_y1;
        !           393:   blit_height
        !           394:     = (blit_height < src_y
        !           395:        ? 0
        !           396:        : (blit_height + 1 - src_y));
        !           397: 
        !           398:   /* check that this blit is supported: */
        !           399:   unsupported = FALSE;
        !           400:   unsupported |= (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_clip_check != 0);
        !           401:   unsupported |= (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_status != 0);
        !           402:   unsupported |= (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_offx != 0);
        !           403:   unsupported |= (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_offy != 0);
        !           404:   unsupported |= (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_clip_min_x != 0);
        !           405:   unsupported |= (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_clip_min_y != 0);
        !           406:   unsupported |= (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_clip_max_x != (fb_width - 1));
        !           407:   unsupported |= (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_clip_max_y != (fb_height - 1));
        !           408:   unsupported
        !           409:     |= (blit_width
        !           410:        != (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_x3 < dst_x
        !           411:            ? 0
        !           412:            : (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_x3 + 1 - dst_x)));
        !           413:   unsupported
        !           414:     |= (blit_height
        !           415:        != (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_y3 < dst_y
        !           416:            ? 0
        !           417:            : (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_y3 + 1 - dst_y)));
        !           418:   if (__tme_predict_false(unsupported)) {
        !           419:     tme_log(TME_SUNFB_LOG_HANDLE(&suncg6->tme_suncg6_sunfb), 0, EINVAL,
        !           420:            (TME_SUNFB_LOG_HANDLE(&suncg6->tme_suncg6_sunfb),
        !           421:             _("unsupported blit parameters")));
        !           422:     return;
        !           423:   }
        !           424: 
        !           425:   /* if any of the least coordinates aren't in the framebuffer: */
        !           426:   if (src_x >= fb_width
        !           427:       || dst_x >= fb_width
        !           428:       || src_y >= fb_height
        !           429:       || dst_y >= fb_height) {
        !           430:     return;
        !           431:   }
        !           432: 
        !           433:   /* make sure the blit height and width stay in the framebuffer: */
        !           434:   blit_width = TME_MIN(blit_width,
        !           435:                       TME_MIN(fb_width - src_x,
        !           436:                               fb_width - dst_x));
        !           437:   blit_height = TME_MIN(blit_height,
        !           438:                        TME_MIN(fb_height - src_y,
        !           439:                                fb_height - dst_y));
        !           440: 
        !           441:   /* if the blit height or width are zero: */
        !           442:   if (blit_width == 0
        !           443:       || blit_height == 0) {
        !           444:     return;
        !           445:   }
        !           446: 
        !           447:   /* get the offsets of the first and last bytes of the
        !           448:      destination: */
        !           449:   offset_updated_first = ((fb_width * dst_y) + dst_x);
        !           450:   offset_updated_last
        !           451:     = (offset_updated_first
        !           452:        + (blit_width - 1)
        !           453:        + (fb_width * (blit_height - 1)));
        !           454: 
        !           455:   /* get the first source and destination rows: */
        !           456:   dst = (tme_suncg6_pixel_t *) suncg6->tme_suncg6_sunfb.tme_sunfb_memory;
        !           457:   src = dst + ((fb_width * src_y) + src_x);
        !           458:   dst += offset_updated_first;
        !           459: 
        !           460:   /* if this is a copy: */
        !           461:   if (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_rasterop
        !           462:       == TME_SUNCG6_FBC_RASTEROP_FUNC_COPY
        !           463:       /* XXX FIXME - the rasterop function that the SUNW,501-2325 PROM
        !           464:         uses for all of its blits and draws doesn't do a copy blit,
        !           465:         but for now we treat it like it does: */
        !           466:       || (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_rasterop
        !           467:          == TME_SUNCG6_FBC_RASTEROP_FUNC_PROM)
        !           468:       ) {
        !           469: 
        !           470:     /* if the copy is full-width: */
        !           471:     if (blit_width == fb_width) {
        !           472: 
        !           473:       /* copy the source to the destination: */
        !           474:       memmove(dst,
        !           475:              src,
        !           476:              sizeof(tme_suncg6_pixel_t) * blit_width * blit_height);
        !           477:     }
        !           478: 
        !           479:     /* otherwise, the copy is not full-width: */
        !           480:     else {
        !           481: 
        !           482:       /* copy the source to the destination: */
        !           483:       do {
        !           484:        memmove(dst,
        !           485:                src,
        !           486:                sizeof(tme_suncg6_pixel_t) * blit_width);
        !           487:        dst += sizeof(tme_suncg6_pixel_t) * fb_width;
        !           488:        src += sizeof(tme_suncg6_pixel_t) * fb_width;
        !           489:       } while (--blit_height);
        !           490:     }
        !           491:   }
        !           492: 
        !           493:   /* otherwise, this is an unsupported blit: */
        !           494:   else {
        !           495:     tme_log(TME_SUNFB_LOG_HANDLE(&suncg6->tme_suncg6_sunfb), 0, EINVAL,
        !           496:            (TME_SUNFB_LOG_HANDLE(&suncg6->tme_suncg6_sunfb),
        !           497:             _("unsupported blit function")));
        !           498:   }
        !           499: 
        !           500:   /* update the offsets of the first and last bytes updated in the
        !           501:      real framebuffer memory: */
        !           502:   offset_updated_first
        !           503:     = TME_MIN(offset_updated_first,
        !           504:              suncg6->tme_suncg6_sunfb.tme_sunfb_offset_updated_first);
        !           505:   offset_updated_last
        !           506:     = TME_MAX(offset_updated_last,
        !           507:              suncg6->tme_suncg6_sunfb.tme_sunfb_offset_updated_last);
        !           508:   suncg6->tme_suncg6_sunfb.tme_sunfb_offset_updated_first = offset_updated_first;
        !           509:   suncg6->tme_suncg6_sunfb.tme_sunfb_offset_updated_last = offset_updated_last;
        !           510: }
        !           511: 
        !           512: /* this does a draw: */
        !           513: static void
        !           514: _tme_suncg6_draw(struct tme_suncg6 *suncg6)
        !           515: {
        !           516:   tme_uint32_t fb_width;
        !           517:   tme_uint32_t fb_height;
        !           518:   unsigned int rect_abs_i;
        !           519:   tme_int32_t draw_width;
        !           520:   tme_int32_t dst_x;
        !           521:   tme_int32_t draw_height;
        !           522:   tme_int32_t dst_y;
        !           523:   int unsupported;
        !           524:   tme_uint32_t offset_updated_first;
        !           525:   tme_uint32_t offset_updated_last;
        !           526:   tme_suncg6_pixel_t *dst;
        !           527:   tme_int32_t resid_width;
        !           528: 
        !           529:   /* get the framebuffer width and height: */
        !           530:   fb_width = suncg6->tme_suncg6_width;
        !           531:   fb_height = suncg6->tme_suncg6_height;
        !           532: 
        !           533:   /* get the draw width and destination x: */
        !           534:   rect_abs_i = suncg6->tme_suncg6_fbc_rect_abs_x_i;
        !           535:   draw_width = suncg6->tme_suncg6_fbc_rect_abs_x[rect_abs_i % TME_SUNCG6_RECT_ABS_COUNT];
        !           536:   rect_abs_i = rect_abs_i - 1;
        !           537:   dst_x = suncg6->tme_suncg6_fbc_rect_abs_x[rect_abs_i % TME_SUNCG6_RECT_ABS_COUNT];
        !           538:   draw_width
        !           539:     = (draw_width < dst_x
        !           540:        ? 0
        !           541:        : (draw_width + 1 - dst_x));
        !           542: 
        !           543:   /* get the draw height and destination y: */
        !           544:   rect_abs_i = suncg6->tme_suncg6_fbc_rect_abs_y_i;
        !           545:   draw_height = suncg6->tme_suncg6_fbc_rect_abs_y[rect_abs_i % TME_SUNCG6_RECT_ABS_COUNT];
        !           546:   rect_abs_i = rect_abs_i - 1;
        !           547:   dst_y = suncg6->tme_suncg6_fbc_rect_abs_y[rect_abs_i % TME_SUNCG6_RECT_ABS_COUNT];
        !           548:   draw_height
        !           549:     = (draw_height < dst_y
        !           550:        ? 0
        !           551:        : (draw_height + 1 - dst_y));
        !           552: 
        !           553:   /* check that this draw is supported: */
        !           554:   unsupported = FALSE;
        !           555:   unsupported |= (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_clip_check != 0);
        !           556:   unsupported |= (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_status != 0);
        !           557:   unsupported |= (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_offx != 0);
        !           558:   unsupported |= (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_offy != 0);
        !           559:   unsupported |= (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_clip_min_x != 0);
        !           560:   unsupported |= (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_clip_min_y != 0);
        !           561:   unsupported |= (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_clip_max_x != (fb_width - 1));
        !           562:   unsupported |= (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_clip_max_y != (fb_height - 1));
        !           563:   if (__tme_predict_false(unsupported)) {
        !           564:     tme_log(TME_SUNFB_LOG_HANDLE(&suncg6->tme_suncg6_sunfb), 0, EINVAL,
        !           565:            (TME_SUNFB_LOG_HANDLE(&suncg6->tme_suncg6_sunfb),
        !           566:             _("unsupported draw parameters")));
        !           567:     return;
        !           568:   }
        !           569: 
        !           570:   /* if the draw coordinate isn't in the framebuffer: */
        !           571:   if (dst_x >= fb_width
        !           572:       || dst_y >= fb_height) {
        !           573:     return;
        !           574:   }
        !           575: 
        !           576:   /* make sure the draw height and width stay in the framebuffer: */
        !           577:   draw_width = TME_MIN(draw_width,
        !           578:                       fb_width - dst_x);
        !           579:   draw_height = TME_MIN(draw_height,
        !           580:                        fb_height - dst_y);
        !           581: 
        !           582:   /* if the draw height or width are zero: */
        !           583:   if (draw_width == 0
        !           584:       || draw_height == 0) {
        !           585:     return;
        !           586:   }
        !           587: 
        !           588:   /* get the offsets of the first and last bytes of the
        !           589:      destination: */
        !           590:   offset_updated_first = ((fb_width * dst_y) + dst_x);
        !           591:   offset_updated_last
        !           592:     = (offset_updated_first
        !           593:        + (draw_width - 1)
        !           594:        + (fb_width * (draw_height - 1)));
        !           595: 
        !           596:   /* get the first destination row: */
        !           597:   dst = (tme_suncg6_pixel_t *) suncg6->tme_suncg6_sunfb.tme_sunfb_memory;
        !           598:   dst += offset_updated_first;
        !           599: 
        !           600:   /* if this is a fill: */
        !           601:   if (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_rasterop
        !           602:       == TME_SUNCG6_FBC_RASTEROP_FUNC_FILL
        !           603:       /* XXX FIXME - the rasterop function that the SUNW,501-2325 PROM
        !           604:         uses for all of its blits and draws doesn't do a fill draw,
        !           605:         but for now we treat it like it does: */
        !           606:       || (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_rasterop
        !           607:          == TME_SUNCG6_FBC_RASTEROP_FUNC_PROM)
        !           608:       ) {
        !           609: 
        !           610:     /* if the fill is full-width: */
        !           611:     if (draw_width == fb_width) {
        !           612: 
        !           613:       /* fill the destination: */
        !           614:       memset(dst,
        !           615:             (tme_uint8_t) suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_fg,
        !           616:             sizeof(tme_suncg6_pixel_t) * draw_width * draw_height);
        !           617:     }
        !           618: 
        !           619:     /* otherwise, the fill is not full-width: */
        !           620:     else {
        !           621: 
        !           622:       /* fill the destination: */
        !           623:       do {
        !           624:        memset(dst,
        !           625:               (tme_uint8_t) suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_fg,
        !           626:               sizeof(tme_suncg6_pixel_t) * draw_width);
        !           627:        dst += sizeof(tme_suncg6_pixel_t) * fb_width;
        !           628:       } while (--draw_height);
        !           629:     }
        !           630:   }
        !           631: 
        !           632:   /* otherwise, if this is an invert: */
        !           633:   else if (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_rasterop
        !           634:           == TME_SUNCG6_FBC_RASTEROP_FUNC_FLIP) {
        !           635: 
        !           636:     /* do the inversion: */
        !           637:     /* XXX FIXME - the inversion almost certainly isn't this
        !           638:        simple: */
        !           639:     do {
        !           640:       resid_width = draw_width;
        !           641:       do {
        !           642:        *(dst++) ^= 0xff;
        !           643:       } while (--resid_width);
        !           644:       dst = (dst - draw_width) + fb_width;
        !           645:     } while (--draw_height);
        !           646:   }
        !           647: 
        !           648:   /* otherwise, this is an unsupported draw: */
        !           649:   else {
        !           650:     tme_log(TME_SUNFB_LOG_HANDLE(&suncg6->tme_suncg6_sunfb), 0, EINVAL,
        !           651:            (TME_SUNFB_LOG_HANDLE(&suncg6->tme_suncg6_sunfb),
        !           652:             _("unsupported draw function")));
        !           653:   }
        !           654: 
        !           655:   /* update the offsets of the first and last bytes updated in the
        !           656:      real framebuffer memory: */
        !           657:   offset_updated_first
        !           658:     = TME_MIN(offset_updated_first,
        !           659:              suncg6->tme_suncg6_sunfb.tme_sunfb_offset_updated_first);
        !           660:   offset_updated_last
        !           661:     = TME_MAX(offset_updated_last,
        !           662:              suncg6->tme_suncg6_sunfb.tme_sunfb_offset_updated_last);
        !           663:   suncg6->tme_suncg6_sunfb.tme_sunfb_offset_updated_first = offset_updated_first;
        !           664:   suncg6->tme_suncg6_sunfb.tme_sunfb_offset_updated_last = offset_updated_last;
        !           665: }
        !           666: 
        !           667: /* this does a font draw: */
        !           668: static void
        !           669: _tme_suncg6_font(struct tme_suncg6 *suncg6,
        !           670:                 tme_suncg6_reg_t font)
        !           671: {
        !           672:   tme_uint32_t fb_width;
        !           673:   tme_uint32_t fb_height;
        !           674:   tme_int32_t dst_x;
        !           675:   tme_int32_t dst_y;
        !           676:   tme_int32_t draw_width;
        !           677:   int unsupported;
        !           678:   tme_uint32_t offset_updated_first;
        !           679:   tme_uint32_t offset_updated_last;
        !           680:   tme_suncg6_pixel_t *dst;
        !           681:   tme_uint16_t pixels;
        !           682: 
        !           683:   /* get the framebuffer width and height: */
        !           684:   fb_width = suncg6->tme_suncg6_width;
        !           685:   fb_height = suncg6->tme_suncg6_height;
        !           686: 
        !           687:   /* get the font draw destination: */
        !           688:   dst_x = suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_x0;
        !           689:   dst_y = suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_y0;
        !           690: 
        !           691:   /* get the font draw width: */
        !           692:   draw_width = suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_x1;
        !           693:   draw_width
        !           694:     = (draw_width < dst_x
        !           695:        ? 0
        !           696:        : (draw_width + 1 - dst_x));
        !           697:   
        !           698:   /* check that this font draw is supported: */
        !           699:   unsupported = FALSE;
        !           700:   unsupported |= (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_clip_check != 0);
        !           701:   unsupported |= (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_status != 0);
        !           702:   unsupported |= (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_offx != 0);
        !           703:   unsupported |= (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_offy != 0);
        !           704:   unsupported |= (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_clip_min_x != 0);
        !           705:   unsupported |= (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_clip_min_y != 0);
        !           706:   unsupported |= (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_clip_max_x != (fb_width - 1));
        !           707:   unsupported |= (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_clip_max_y != (fb_height - 1));
        !           708:   if (__tme_predict_false(unsupported)) {
        !           709:     tme_log(TME_SUNFB_LOG_HANDLE(&suncg6->tme_suncg6_sunfb), 0, EINVAL,
        !           710:            (TME_SUNFB_LOG_HANDLE(&suncg6->tme_suncg6_sunfb),
        !           711:             _("unsupported font draw parameters")));
        !           712:     return;
        !           713:   }
        !           714: 
        !           715:   /* if the font draw coordinate isn't in the framebuffer: */
        !           716:   if (dst_x >= fb_width
        !           717:       || dst_y >= fb_height) {
        !           718:     return;
        !           719:   }
        !           720: 
        !           721:   /* make sure the font draw width stays in the framebuffer: */
        !           722:   draw_width = TME_MIN(draw_width,
        !           723:                       fb_width - dst_x);
        !           724: 
        !           725:   /* if the draw width is zero: */
        !           726:   if (draw_width == 0) {
        !           727:     return;
        !           728:   }
        !           729: 
        !           730:   /* get the offsets of the first and last bytes of the
        !           731:      destination: */
        !           732:   offset_updated_first = ((fb_width * dst_y) + dst_x);
        !           733:   offset_updated_last
        !           734:     = (offset_updated_first
        !           735:        + (draw_width - 1));
        !           736: 
        !           737:   /* get the first destination row: */
        !           738:   dst = (tme_suncg6_pixel_t *) suncg6->tme_suncg6_sunfb.tme_sunfb_memory;
        !           739:   dst += offset_updated_first;
        !           740: 
        !           741:   /* get the foreground and background pixels: */
        !           742:   pixels = (tme_suncg6_pixel_t) suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_fg;
        !           743:   pixels <<= (8 * sizeof(tme_suncg6_pixel_t));
        !           744:   pixels += (tme_suncg6_pixel_t) suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_bg;
        !           745: 
        !           746:   /* do the font draw: */
        !           747:   do {
        !           748:     *(dst++)
        !           749:       = ((tme_suncg6_pixel_t)
        !           750:         (pixels
        !           751:          >> ((0 - (((tme_int32_t) font) < 0))
        !           752:              & (8 * sizeof(tme_suncg6_pixel_t)))));
        !           753:     font <<= 1;
        !           754:   } while (--draw_width);
        !           755: 
        !           756:   /* advance after the font draw: */
        !           757:   suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_x0 += suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_inc_x;
        !           758:   suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_x1 += suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_inc_x;
        !           759:   suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_y0 += suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_inc_y;
        !           760: 
        !           761:   /* update the offsets of the first and last bytes updated in the
        !           762:      real framebuffer memory: */
        !           763:   offset_updated_first
        !           764:     = TME_MIN(offset_updated_first,
        !           765:              suncg6->tme_suncg6_sunfb.tme_sunfb_offset_updated_first);
        !           766:   offset_updated_last
        !           767:     = TME_MAX(offset_updated_last,
        !           768:              suncg6->tme_suncg6_sunfb.tme_sunfb_offset_updated_last);
        !           769:   suncg6->tme_suncg6_sunfb.tme_sunfb_offset_updated_first = offset_updated_first;
        !           770:   suncg6->tme_suncg6_sunfb.tme_sunfb_offset_updated_last = offset_updated_last;
        !           771: }
        !           772: 
        !           773: /* the ALT bus cycle handler: */
        !           774: static void
        !           775: _tme_suncg6_bus_cycle_alt(struct tme_sunfb *sunfb,
        !           776:                          struct tme_bus_cycle *master_cycle,
        !           777:                          tme_uint32_t *_master_fast_cycle_types,
        !           778:                          struct tme_completion *master_completion)
        !           779: {
        !           780:   struct tme_suncg6 *suncg6;
        !           781:   tme_bus_addr32_t reg;
        !           782:   tme_suncg6_reg_t *_reg;
        !           783:   tme_suncg6_reg_t value32_buffer;
        !           784:   tme_suncg6_reg_t value32;
        !           785: 
        !           786:   /* recover our data structure: */
        !           787:   suncg6 = (struct tme_suncg6 *) sunfb;
        !           788: 
        !           789:   /* get the register: */
        !           790:   reg = master_cycle->tme_bus_cycle_address;
        !           791: 
        !           792:   /* convert the register into a pointer: */
        !           793:   _reg = NULL;
        !           794: 
        !           795:   /* if this is a write: */
        !           796:   if (master_cycle->tme_bus_cycle_type == TME_BUS_CYCLE_WRITE) {
        !           797: 
        !           798:     /* run the bus cycle: */
        !           799:     tme_bus_cycle_xfer_reg(master_cycle, 
        !           800:                           &value32_buffer,
        !           801:                           TME_BUS32_LOG2);
        !           802:     value32 = value32_buffer;
        !           803:   }
        !           804: 
        !           805:   /* otherwise, this must be a read: */
        !           806:   else {
        !           807:     assert (master_cycle->tme_bus_cycle_type == TME_BUS_CYCLE_READ);
        !           808: 
        !           809:     /* this must be a maintained register: */
        !           810:     if (_reg == NULL) {
        !           811:       abort();
        !           812:     }
        !           813:     value32 = *_reg;
        !           814: 
        !           815:     /* run the bus cycle: */
        !           816:     value32_buffer = value32;
        !           817:     tme_bus_cycle_xfer_reg(master_cycle, 
        !           818:                           &value32_buffer,
        !           819:                           TME_BUS32_LOG2);
        !           820:   }
        !           821: 
        !           822:   /* complete the cycle: */
        !           823:   master_completion->tme_completion_error = TME_OK;
        !           824:   tme_memory_barrier(master_completion, sizeof(*master_completion), TME_MEMORY_BARRIER_WRITE_BEFORE_WRITE);
        !           825:   tme_completion_validate(master_completion);
        !           826:   *_master_fast_cycle_types = 0;
        !           827: 
        !           828:   tme_log(TME_SUNFB_LOG_HANDLE(sunfb), 2000, TME_OK,
        !           829:          (TME_SUNFB_LOG_HANDLE(sunfb),
        !           830:           _("ALT 0x%06" TME_PRIx32 " %s%s 0x%08" TME_PRIx32),
        !           831:           reg,
        !           832:           (_reg == NULL
        !           833:            ? "UNKNOWN "
        !           834:            : ""),
        !           835:           (master_cycle->tme_bus_cycle_type == TME_BUS_CYCLE_WRITE
        !           836:            ? "<-"
        !           837:            : "->"),
        !           838:           value32));
        !           839: }
        !           840: 
        !           841: /* the FHC and THC bus cycle handler: */
        !           842: static void
        !           843: _tme_suncg6_bus_cycle_fhc_thc(struct tme_sunfb *sunfb,
        !           844:                              struct tme_bus_cycle *master_cycle,
        !           845:                              tme_uint32_t *_master_fast_cycle_types,
        !           846:                              struct tme_completion *master_completion)
        !           847: {
        !           848:   struct tme_suncg6 *suncg6;
        !           849:   tme_bus_addr32_t reg;
        !           850:   tme_suncg6_reg_t *_reg;
        !           851:   tme_suncg6_reg_t value32_buffer;
        !           852:   tme_suncg6_reg_t value32;
        !           853:   tme_suncg6_reg_t reg_mask_ro;
        !           854: 
        !           855:   /* recover our data structure: */
        !           856:   suncg6 = (struct tme_suncg6 *) sunfb;
        !           857: 
        !           858:   /* get the register: */
        !           859:   reg = master_cycle->tme_bus_cycle_address;
        !           860: 
        !           861:   /* convert the register into a pointer: */
        !           862:   if (reg >= TME_SUNCG6_REG_THC_UNKNOWN_0x0) {
        !           863:     _reg = (TME_SUNCG6_REG_POINTER(suncg6, reg,THC,thc,0)
        !           864:            : TME_SUNCG6_REG_POINTER(suncg6, reg,THC,thc,1)
        !           865:            : NULL);
        !           866:   }
        !           867:   else {
        !           868:     reg = TME_SUNCG6_REG_FHC;
        !           869:     _reg = &suncg6->tme_suncg6_fhc;
        !           870:   }
        !           871: 
        !           872:   /* if this is a write: */
        !           873:   if (master_cycle->tme_bus_cycle_type == TME_BUS_CYCLE_WRITE) {
        !           874: 
        !           875:     /* run the bus cycle: */
        !           876:     tme_bus_cycle_xfer_reg(master_cycle, 
        !           877:                           &value32_buffer,
        !           878:                           TME_BUS32_LOG2);
        !           879:     value32 = value32_buffer;
        !           880: 
        !           881:     /* assume that none of the register is read-only: */
        !           882:     reg_mask_ro = 0;
        !           883: 
        !           884:     /* dispatch on the register: */
        !           885:     switch (reg) {
        !           886: 
        !           887:       /* the FHC: */
        !           888:     case TME_SUNCG6_REG_FHC:
        !           889:       reg_mask_ro
        !           890:        = (TME_SUNCG6_FHC_ID_MASK
        !           891:           + TME_SUNCG6_FHC_REVISION_MASK
        !           892:           + TME_SUNCG6_FHC_SIZE_MASK);
        !           893:       break;
        !           894: 
        !           895:       /* the THC miscellaneous register: */
        !           896:     case TME_SUNCG6_REG_THC(1,misc):
        !           897:       reg_mask_ro
        !           898:        = (TME_SUNCG6_THC_MISC_REVISION_MASK
        !           899:           );
        !           900:       break;
        !           901: 
        !           902:     default:
        !           903:       break;
        !           904:     }
        !           905: 
        !           906:     /* if this is a maintained register: */
        !           907:     if (_reg != NULL) {
        !           908:       *_reg
        !           909:        = ((*_reg
        !           910:            & reg_mask_ro)
        !           911:           + (value32
        !           912:              & ~reg_mask_ro));
        !           913:     }
        !           914:   }
        !           915: 
        !           916:   /* otherwise, this is a read: */
        !           917:   else {
        !           918:     assert (master_cycle->tme_bus_cycle_type == TME_BUS_CYCLE_READ);
        !           919: 
        !           920:     /* dispatch on the register: */
        !           921:     switch (reg) {
        !           922: 
        !           923:     default:
        !           924:       break;
        !           925:     }
        !           926: 
        !           927:     /* this must be a maintained register: */
        !           928:     if (_reg == NULL) {
        !           929:       abort();
        !           930:     }
        !           931:     value32 = *_reg;
        !           932: 
        !           933:     /* run the bus cycle: */
        !           934:     value32_buffer = value32;
        !           935:     tme_bus_cycle_xfer_reg(master_cycle, 
        !           936:                           &value32_buffer,
        !           937:                           TME_BUS32_LOG2);
        !           938:   }
        !           939: 
        !           940:   /* complete the cycle: */
        !           941:   master_completion->tme_completion_error = TME_OK;
        !           942:   tme_memory_barrier(master_completion, sizeof(*master_completion), TME_MEMORY_BARRIER_WRITE_BEFORE_WRITE);
        !           943:   tme_completion_validate(master_completion);
        !           944:   *_master_fast_cycle_types = 0;
        !           945: 
        !           946:   tme_log(TME_SUNFB_LOG_HANDLE(sunfb), 2000, TME_OK,
        !           947:          (TME_SUNFB_LOG_HANDLE(sunfb),
        !           948:           _("%s 0x%06" TME_PRIx32 " %s%s 0x%08" TME_PRIx32),
        !           949:           (reg >= TME_SUNCG6_REG_THC_UNKNOWN_0x0
        !           950:            ? "THC"
        !           951:            : "FHC"),
        !           952:           reg,
        !           953:           (_reg == NULL
        !           954:            ? "UNKNOWN "
        !           955:            : ""),
        !           956:           (master_cycle->tme_bus_cycle_type == TME_BUS_CYCLE_WRITE
        !           957:            ? "<-"
        !           958:            : "->"),
        !           959:           value32));
        !           960: }
        !           961: 
        !           962: /* the FBC bus cycle handler: */
        !           963: static void
        !           964: _tme_suncg6_bus_cycle_fbc(struct tme_sunfb *sunfb,
        !           965:                          struct tme_bus_cycle *master_cycle,
        !           966:                          tme_uint32_t *_master_fast_cycle_types,
        !           967:                          struct tme_completion *master_completion)
        !           968: {
        !           969:   struct tme_suncg6 *suncg6;
        !           970:   tme_bus_addr32_t reg;
        !           971:   tme_suncg6_reg_t *_reg;
        !           972:   tme_suncg6_reg_t value32_buffer;
        !           973:   tme_suncg6_reg_t value32;
        !           974:   tme_suncg6_reg_t reg_mask_ro;
        !           975: 
        !           976:   /* recover our data structure: */
        !           977:   suncg6 = (struct tme_suncg6 *) sunfb;
        !           978: 
        !           979:   /* get the register: */
        !           980:   reg = master_cycle->tme_bus_cycle_address;
        !           981: 
        !           982:   /* convert the register into a pointer: */
        !           983:   _reg
        !           984:     = (TME_SUNCG6_REG_POINTER(suncg6, reg,FBC,fbc,0)
        !           985:        : TME_SUNCG6_REG_POINTER(suncg6, reg,FBC,fbc,1)
        !           986:        : NULL);
        !           987: 
        !           988:   /* if this is a write: */
        !           989:   if (master_cycle->tme_bus_cycle_type == TME_BUS_CYCLE_WRITE) {
        !           990: 
        !           991:     /* run the bus cycle: */
        !           992:     tme_bus_cycle_xfer_reg(master_cycle, 
        !           993:                           &value32_buffer,
        !           994:                           TME_BUS32_LOG2);
        !           995:     value32 = value32_buffer;
        !           996: 
        !           997:     /* assume that none of the register is read-only: */
        !           998:     reg_mask_ro = 0;
        !           999: 
        !          1000:     /* dispatch on the register: */
        !          1001:     switch (reg) {
        !          1002: 
        !          1003:       /* a write of the font register: */
        !          1004:     case TME_SUNCG6_REG_FBC(0,font):
        !          1005:       _tme_suncg6_font(suncg6, value32);
        !          1006:       break;
        !          1007: 
        !          1008:       /* a write of the rectangle absolute coordinate registers: */
        !          1009:     case TME_SUNCG6_REG_FBC(1,rect_abs_x):
        !          1010:       suncg6->tme_suncg6_fbc_rect_abs_x_i
        !          1011:        = ((suncg6->tme_suncg6_fbc_rect_abs_x_i + 1)
        !          1012:           % TME_SUNCG6_RECT_ABS_COUNT);
        !          1013:       _reg = &suncg6->tme_suncg6_fbc_rect_abs_x[suncg6->tme_suncg6_fbc_rect_abs_x_i];
        !          1014:       break;
        !          1015:     case TME_SUNCG6_REG_FBC(1,rect_abs_y):
        !          1016:       suncg6->tme_suncg6_fbc_rect_abs_y_i
        !          1017:        = ((suncg6->tme_suncg6_fbc_rect_abs_y_i + 1)
        !          1018:           % TME_SUNCG6_RECT_ABS_COUNT);
        !          1019:       _reg = &suncg6->tme_suncg6_fbc_rect_abs_y[suncg6->tme_suncg6_fbc_rect_abs_y_i];
        !          1020:       break;
        !          1021: 
        !          1022:     default:
        !          1023:       break;
        !          1024:     }
        !          1025: 
        !          1026:     /* if this is a maintained register: */
        !          1027:     if (_reg != NULL) {
        !          1028:       *_reg
        !          1029:        = ((*_reg
        !          1030:            & reg_mask_ro)
        !          1031:           + (value32
        !          1032:              & ~reg_mask_ro));
        !          1033:     }
        !          1034:   }
        !          1035: 
        !          1036:   /* otherwise, this is a read: */
        !          1037:   else {
        !          1038:     assert (master_cycle->tme_bus_cycle_type == TME_BUS_CYCLE_READ);
        !          1039: 
        !          1040:     /* dispatch on the register: */
        !          1041:     switch (reg) {
        !          1042: 
        !          1043:       /* a read of the status register: */
        !          1044:     case TME_SUNCG6_REG_FBC(0,status):
        !          1045:       *_reg = 0;
        !          1046:       break;
        !          1047: 
        !          1048:       /* a read of the blit status register: */
        !          1049:     case TME_SUNCG6_REG_FBC(0,status_blit):
        !          1050: 
        !          1051:       /* trigger a blit: */
        !          1052:       _tme_suncg6_blit(suncg6);
        !          1053: 
        !          1054:       *_reg = 0;
        !          1055:       break;
        !          1056: 
        !          1057:       /* a read of the drawing status register: */
        !          1058:     case TME_SUNCG6_REG_FBC(0,status_draw):
        !          1059: 
        !          1060:       /* trigger a draw: */
        !          1061:       _tme_suncg6_draw(suncg6);
        !          1062: 
        !          1063:       *_reg = 0;
        !          1064:       break;
        !          1065: 
        !          1066:     default:
        !          1067:       break;
        !          1068:     }
        !          1069: 
        !          1070:     /* this must be a maintained register: */
        !          1071:     if (_reg == NULL) {
        !          1072:       abort();
        !          1073:     }
        !          1074:     value32 = *_reg;
        !          1075: 
        !          1076:     /* run the bus cycle: */
        !          1077:     value32_buffer = value32;
        !          1078:     tme_bus_cycle_xfer_reg(master_cycle, 
        !          1079:                           &value32_buffer,
        !          1080:                           TME_BUS32_LOG2);
        !          1081:   }
        !          1082: 
        !          1083:   /* complete the cycle: */
        !          1084:   master_completion->tme_completion_error = TME_OK;
        !          1085:   tme_memory_barrier(master_completion, sizeof(*master_completion), TME_MEMORY_BARRIER_WRITE_BEFORE_WRITE);
        !          1086:   tme_completion_validate(master_completion);
        !          1087:   *_master_fast_cycle_types = 0;
        !          1088: 
        !          1089:   tme_log(TME_SUNFB_LOG_HANDLE(sunfb), 2000, TME_OK,
        !          1090:          (TME_SUNFB_LOG_HANDLE(sunfb),
        !          1091:           _("FBC 0x%06" TME_PRIx32 " %s%s 0x%08" TME_PRIx32),
        !          1092:           reg,
        !          1093:           (_reg == NULL
        !          1094:            ? "UNKNOWN "
        !          1095:            : ""),
        !          1096:           (master_cycle->tme_bus_cycle_type == TME_BUS_CYCLE_WRITE
        !          1097:            ? "<-"
        !          1098:            : "->"),
        !          1099:           value32));
        !          1100: }
        !          1101: 
        !          1102: /* the TEC bus cycle handler: */
        !          1103: static void
        !          1104: _tme_suncg6_bus_cycle_tec(struct tme_sunfb *sunfb,
        !          1105:                          struct tme_bus_cycle *master_cycle,
        !          1106:                          tme_uint32_t *_master_fast_cycle_types,
        !          1107:                          struct tme_completion *master_completion)
        !          1108: {
        !          1109:   struct tme_suncg6 *suncg6;
        !          1110:   tme_bus_addr32_t reg;
        !          1111:   tme_suncg6_reg_t *_reg;
        !          1112:   tme_suncg6_reg_t value32_buffer;
        !          1113:   tme_suncg6_reg_t value32;
        !          1114:   tme_suncg6_reg_t reg_mask_ro;
        !          1115: 
        !          1116:   /* recover our data structure: */
        !          1117:   suncg6 = (struct tme_suncg6 *) sunfb;
        !          1118: 
        !          1119:   /* get the register: */
        !          1120:   reg = master_cycle->tme_bus_cycle_address;
        !          1121: 
        !          1122:   /* convert the register into a pointer: */
        !          1123:   _reg
        !          1124:     = (TME_SUNCG6_REG_POINTER(suncg6, reg,TEC,tec,0)
        !          1125:        : NULL);
        !          1126: 
        !          1127:   /* if this is a write: */
        !          1128:   if (master_cycle->tme_bus_cycle_type == TME_BUS_CYCLE_WRITE) {
        !          1129: 
        !          1130:     /* run the bus cycle: */
        !          1131:     tme_bus_cycle_xfer_reg(master_cycle, 
        !          1132:                           &value32_buffer,
        !          1133:                           TME_BUS32_LOG2);
        !          1134:     value32 = value32_buffer;
        !          1135: 
        !          1136:     /* assume that none of the register is read-only: */
        !          1137:     reg_mask_ro = 0;
        !          1138: 
        !          1139:     /* dispatch on the register: */
        !          1140:     switch (reg) {
        !          1141: 
        !          1142:     default:
        !          1143:       break;
        !          1144:     }
        !          1145: 
        !          1146:     /* if this is a maintained register: */
        !          1147:     if (_reg != NULL) {
        !          1148:       *_reg
        !          1149:        = ((*_reg
        !          1150:            & reg_mask_ro)
        !          1151:           + (value32
        !          1152:              & ~reg_mask_ro));
        !          1153:     }
        !          1154:   }
        !          1155: 
        !          1156:   /* otherwise, this is a read: */
        !          1157:   else {
        !          1158:     assert (master_cycle->tme_bus_cycle_type == TME_BUS_CYCLE_READ);
        !          1159: 
        !          1160:     /* dispatch on the register: */
        !          1161:     switch (reg) {
        !          1162: 
        !          1163:     default:
        !          1164:       break;
        !          1165:     }
        !          1166: 
        !          1167:     /* this must be a maintained register: */
        !          1168:     if (_reg == NULL) {
        !          1169:       abort();
        !          1170:     }
        !          1171:     value32 = *_reg;
        !          1172: 
        !          1173:     /* run the bus cycle: */
        !          1174:     value32_buffer = value32;
        !          1175:     tme_bus_cycle_xfer_reg(master_cycle, 
        !          1176:                           &value32_buffer,
        !          1177:                           TME_BUS32_LOG2);
        !          1178:   }
        !          1179: 
        !          1180:   /* complete the cycle: */
        !          1181:   master_completion->tme_completion_error = TME_OK;
        !          1182:   tme_memory_barrier(master_completion, sizeof(*master_completion), TME_MEMORY_BARRIER_WRITE_BEFORE_WRITE);
        !          1183:   tme_completion_validate(master_completion);
        !          1184:   *_master_fast_cycle_types = 0;
        !          1185: 
        !          1186:   tme_log(TME_SUNFB_LOG_HANDLE(sunfb), 2000, TME_OK,
        !          1187:          (TME_SUNFB_LOG_HANDLE(sunfb),
        !          1188:           _("TEC 0x%06" TME_PRIx32 " %s%s 0x%08" TME_PRIx32),
        !          1189:           reg,
        !          1190:           (_reg == NULL
        !          1191:            ? "UNKNOWN "
        !          1192:            : ""),
        !          1193:           (master_cycle->tme_bus_cycle_type == TME_BUS_CYCLE_WRITE
        !          1194:            ? "<-"
        !          1195:            : "->"),
        !          1196:           value32));
        !          1197: }
        !          1198: 
        !          1199: #if TME_SUNFB_BUS_TRANSITION
        !          1200: 
        !          1201: /* this is the bus cycle transition glue: */
        !          1202: #define _tme_suncg6_bus_cycle_transition(regs)                                         \
        !          1203: static int                                                                             \
        !          1204: _TME_CONCAT(_tme_suncg6_bus_cycle_transition_,regs)(void *_sunfb,                      \
        !          1205:                                                    struct tme_bus_cycle *master_cycle) \
        !          1206: {                                                                                      \
        !          1207:   return (tme_sunfb_bus_cycle_transition(_sunfb,                                       \
        !          1208:                                         master_cycle,                                  \
        !          1209:                                         _TME_CONCAT(_tme_suncg6_bus_cycle_,regs)));    \
        !          1210: }                                                                                      \
        !          1211: struct _tme_suncg6_bus_cycle_transition
        !          1212: _tme_suncg6_bus_cycle_transition(alt);
        !          1213: _tme_suncg6_bus_cycle_transition(fhc_thc);
        !          1214: _tme_suncg6_bus_cycle_transition(fbc);
        !          1215: _tme_suncg6_bus_cycle_transition(tec);
        !          1216: #define _tme_suncg6_bus_cycle_alt _tme_suncg6_bus_cycle_transition_alt
        !          1217: #define _tme_suncg6_bus_cycle_fhc_thc _tme_suncg6_bus_cycle_transition_fhc_thc
        !          1218: #define _tme_suncg6_bus_cycle_fbc _tme_suncg6_bus_cycle_transition_fbc
        !          1219: #define _tme_suncg6_bus_cycle_tec _tme_suncg6_bus_cycle_transition_tec
        !          1220: #undef _tme_suncg6_bus_cycle_transition
        !          1221: 
        !          1222: #endif /* TME_SUNFB_BUS_TRANSITION */
        !          1223: 
        !          1224: /* this sets the cgsix type: */
        !          1225: static const char *
        !          1226: _tme_suncg6_type_set(struct tme_sunfb *sunfb, const char *cg6_type_string)
        !          1227: {
        !          1228:   struct tme_suncg6 *suncg6;
        !          1229:   tme_uint32_t cg6_type;
        !          1230:   tme_suncg6_reg_t fhc;
        !          1231:   tme_suncg6_reg_t thc_misc;
        !          1232: 
        !          1233:   /* recover our data structure: */
        !          1234:   suncg6 = (struct tme_suncg6 *) sunfb;
        !          1235: 
        !          1236:   /* see if this is a good type: */
        !          1237:   cg6_type = TME_SUNCG6_TYPE_NULL;
        !          1238:   if (TME_ARG_IS(cg6_type_string, "501-2325")) {
        !          1239:     cg6_type = TME_SUNCG6_TYPE_501_2325;
        !          1240:   }
        !          1241: 
        !          1242:   /* set the new type: */
        !          1243:   suncg6->tme_suncg6_type = cg6_type;
        !          1244: 
        !          1245:   /* zero various registers: */
        !          1246:   fhc = 0;
        !          1247:   thc_misc = 0;
        !          1248: 
        !          1249:   /* dispatch on the new type: */
        !          1250:   switch (cg6_type) {
        !          1251: 
        !          1252:     /* if this was a bad type, return a string of types: */
        !          1253:   default: assert(FALSE);
        !          1254:   case TME_SUNCG6_TYPE_NULL:
        !          1255:     return ("501-2325");
        !          1256: 
        !          1257:   case TME_SUNCG6_TYPE_501_2325:
        !          1258:     TME_FIELD_MASK_DEPOSITU(fhc, TME_SUNCG6_FHC_ID_MASK, 0x63);
        !          1259:     TME_FIELD_MASK_DEPOSITU(fhc, TME_SUNCG6_FHC_REVISION_MASK, 0xb);
        !          1260:     TME_FIELD_MASK_DEPOSITU(thc_misc, TME_SUNCG6_THC_MISC_REVISION_MASK, 0x4);
        !          1261:     sunfb->tme_sunfb_bus_signal_int = TME_BUS_SIGNAL_INT(5);
        !          1262:     break;
        !          1263:   }
        !          1264: 
        !          1265:   /* set various initial registers: */
        !          1266:   suncg6->tme_suncg6_fhc = fhc;
        !          1267:   suncg6->tme_suncg6_thc_group1.tme_suncg6_thc_misc = thc_misc;
        !          1268: 
        !          1269:   /* success: */
        !          1270:   return (NULL);
        !          1271: }
        !          1272: 
        !          1273: /* the new sun cgsix function: */
        !          1274: int
        !          1275: tme_sun_cgsix(struct tme_element *element, const char * const *args, char **_output)
        !          1276: {
        !          1277:   struct tme_suncg6 *suncg6;
        !          1278:   struct tme_sunfb *sunfb;
        !          1279:   tme_uint8_t *cmap;
        !          1280:   int rc;
        !          1281:   tme_suncg6_reg_t fhc;
        !          1282: 
        !          1283:   /* start the suncg6 structure: */
        !          1284:   suncg6 = tme_new0(struct tme_suncg6, 1);
        !          1285:   suncg6->tme_suncg6_sunfb.tme_sunfb_element = element;
        !          1286: 
        !          1287:   /* initialize the sunfb structure: */
        !          1288:   sunfb = &suncg6->tme_suncg6_sunfb;
        !          1289:   sunfb->tme_sunfb_class = TME_FB_XLAT_CLASS_COLOR;
        !          1290:   sunfb->tme_sunfb_depth = 8;
        !          1291:   sunfb->tme_sunfb_type_set = _tme_suncg6_type_set;
        !          1292:   sunfb->tme_sunfb_flags
        !          1293:     |= ((!TME_SUNFB_FLAG_BT458_CMAP_PACKED)
        !          1294:        | TME_SUNFB_FLAG_BT458_BYTE_D24_D31);
        !          1295: 
        !          1296:   /* possible cgsix framebuffer sizes: */
        !          1297:   suncg6->tme_suncg6_sunfb.tme_sunfb_size
        !          1298:     = (TME_SUNFB_SIZE_1024_768
        !          1299:        | TME_SUNFB_SIZE_1152_900
        !          1300:        | TME_SUNFB_SIZE_1280_1024
        !          1301:        | TME_SUNFB_SIZE_1600_1280);
        !          1302: 
        !          1303:   /* assume that this is not a P4 cgsix: */
        !          1304:   suncg6->tme_suncg6_bus_subregion_p4.tme_bus_subregion_address_first = 1;
        !          1305:   suncg6->tme_suncg6_bus_subregion_p4.tme_bus_subregion_address_last = 0;
        !          1306:   suncg6->tme_suncg6_bus_handler_p4 = NULL;
        !          1307: 
        !          1308:   /* the DAC registers: */
        !          1309:   suncg6->tme_suncg6_bus_subregion_dac.tme_bus_subregion_address_first = TME_SUNCG6_REG_DAC;
        !          1310:   suncg6->tme_suncg6_bus_subregion_dac.tme_bus_subregion_address_last = TME_SUNCG6_REG_ALT - 1;
        !          1311:   suncg6->tme_suncg6_bus_handler_dac = tme_sunfb_bus_cycle_bt458;
        !          1312: 
        !          1313:   /* the ALT registers: */
        !          1314:   suncg6->tme_suncg6_bus_subregion_alt.tme_bus_subregion_address_first = TME_SUNCG6_REG_ALT;
        !          1315:   suncg6->tme_suncg6_bus_subregion_alt.tme_bus_subregion_address_last = TME_SUNCG6_REG_ALT + TME_SUNCG6_SIZ_ALT - 1;
        !          1316:   suncg6->tme_suncg6_bus_handler_alt = _tme_suncg6_bus_cycle_alt;
        !          1317: 
        !          1318:   /* the FHC and THC registers: */
        !          1319:   suncg6->tme_suncg6_bus_subregion_fhc_thc.tme_bus_subregion_address_first = TME_SUNCG6_REG_FHC;
        !          1320:   suncg6->tme_suncg6_bus_subregion_fhc_thc.tme_bus_subregion_address_last
        !          1321:     = (TME_SUNCG6_REG_THC_UNKNOWN_0x0
        !          1322:        + TME_SUNCG6_SIZ_THC
        !          1323:        - 1);
        !          1324:   suncg6->tme_suncg6_bus_handler_fhc_thc = _tme_suncg6_bus_cycle_fhc_thc;
        !          1325: 
        !          1326:   /* the FBC registers: */
        !          1327:   suncg6->tme_suncg6_bus_subregion_fbc.tme_bus_subregion_address_first
        !          1328:     = TME_SUNCG6_REG_FBC_GROUP0;
        !          1329:   suncg6->tme_suncg6_bus_subregion_fbc.tme_bus_subregion_address_last
        !          1330:     = TME_SUNCG6_REG_TEC_GROUP0 - 1;
        !          1331:   suncg6->tme_suncg6_bus_handler_fbc = _tme_suncg6_bus_cycle_fbc;
        !          1332: 
        !          1333:   /* the TEC registers: */
        !          1334:   suncg6->tme_suncg6_bus_subregion_tec.tme_bus_subregion_address_first
        !          1335:     = TME_SUNCG6_REG_TEC_GROUP0;
        !          1336:   suncg6->tme_suncg6_bus_subregion_tec.tme_bus_subregion_address_last
        !          1337:     = (TME_SUNCG6_REG_TEC_GROUP0
        !          1338:        + TME_SUNCG6_TEC_SIZE
        !          1339:        - 1);
        !          1340:   suncg6->tme_suncg6_bus_handler_tec = _tme_suncg6_bus_cycle_tec;
        !          1341: 
        !          1342:   /* the memory address: */
        !          1343:   sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_first = TME_SUNFB_S4_OFFSET_MEMORY;
        !          1344: 
        !          1345:   /* if the generic initialization fails: */
        !          1346:   rc = tme_sunfb_new(sunfb, args, _output);
        !          1347:   if (rc) {
        !          1348: 
        !          1349:     /* free the sunfb structure and return the error: */
        !          1350:     tme_free(sunfb);
        !          1351:     return (rc);
        !          1352:   }
        !          1353: 
        !          1354:   /* set the size in the initial FHC: */
        !          1355:   fhc = suncg6->tme_suncg6_fhc;
        !          1356:   fhc &= (TME_SUNCG6_FHC_ID_MASK
        !          1357:          + TME_SUNCG6_FHC_REVISION_MASK);
        !          1358:   switch (sunfb->tme_sunfb_size) {
        !          1359:   default: assert(FALSE);
        !          1360:   case TME_SUNFB_SIZE_1152_900: fhc += TME_SUNCG6_FHC_SIZE_1152_900; break;
        !          1361:   case TME_SUNFB_SIZE_1024_768: fhc += TME_SUNCG6_FHC_SIZE_1024_768; break;
        !          1362:   case TME_SUNFB_SIZE_1280_1024: fhc += TME_SUNCG6_FHC_SIZE_1280_1024; break;
        !          1363:   case TME_SUNFB_SIZE_1600_1280: fhc += TME_SUNCG6_FHC_SIZE_1600_1280; break;
        !          1364:   }
        !          1365:   suncg6->tme_suncg6_fhc = fhc;
        !          1366: 
        !          1367:   /* save the size: */
        !          1368:   suncg6->tme_suncg6_width = tme_sunfb_size_width(suncg6->tme_suncg6_sunfb.tme_sunfb_size);
        !          1369:   suncg6->tme_suncg6_height = tme_sunfb_size_height(suncg6->tme_suncg6_sunfb.tme_sunfb_size);
        !          1370: 
        !          1371:   /* allocate the colormap arrays: */
        !          1372:   cmap = tme_new0(tme_uint8_t, 256 * 3);
        !          1373:   sunfb->tme_sunfb_cmap_g = &cmap[256 * 0];
        !          1374:   sunfb->tme_sunfb_cmap_r = &cmap[256 * 1];
        !          1375:   sunfb->tme_sunfb_cmap_b = &cmap[256 * 2];
        !          1376:   sunfb->tme_sunfb_bt458.tme_bt458_cmap_g = sunfb->tme_sunfb_cmap_g;
        !          1377:   sunfb->tme_sunfb_bt458.tme_bt458_cmap_r = sunfb->tme_sunfb_cmap_r;
        !          1378:   sunfb->tme_sunfb_bt458.tme_bt458_cmap_b = sunfb->tme_sunfb_cmap_b;
        !          1379: 
        !          1380:   return (TME_OK);
        !          1381: }

unix.superglobalmegacorp.com

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