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

1.1     ! root        1: /* $Id: sun-cgtwo.c,v 1.2 2005/05/09 02:01:02 fredette Exp $ */
        !             2: 
        !             3: /* machine/sun/sun-cgtwo.c - Sun cgtwo emulation: */
        !             4: 
        !             5: /*
        !             6:  * Copyright (c) 2003, 2004, 2005 Matt 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-cgtwo.c,v 1.2 2005/05/09 02:01:02 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: /* cgtwo types: */
        !            48: #define TME_SUNCG2_TYPE_NULL                   (0)
        !            49: #define TME_SUNCG2_TYPE_SUN3                   (1)
        !            50: 
        !            51: /* a cgtwo has eight planes: */
        !            52: #define TME_SUNCG2_PLANE_MAX                   (8)
        !            53: 
        !            54: /* every rasterop unit has its alternate, prime registers: */
        !            55: #define TME_SUNCG2_ROPC_PRIME                  (9)
        !            56: 
        !            57: /* every so many CSR reads, we fake a retrace: */
        !            58: #define TME_SUNCG2_CYCLE_RETRACE               (10)
        !            59: 
        !            60: /* this gives the index into the entire colormap of a pixel's
        !            61:    intensity for a given primary: */
        !            62: #define TME_SUNCG2_CMAP_INDEX(pixel, primary)  ((((primary) - TME_SUNCG2_REG_CMAP_R) / sizeof(tme_uint16_t)) + (pixel))
        !            63: 
        !            64: /* this gives a pixel's intensity for a given primary: */
        !            65: #define TME_SUNCG2_CMAP_VALUE(suncg2, pixel, primary)                  \
        !            66:   (tme_betoh_u16((suncg2)->tme_suncg2_cmap_raw[TME_SUNCG2_CMAP_INDEX(pixel, primary)]) & 0xff)
        !            67: 
        !            68: /* a plane bitmap has one bit per pixel: */
        !            69: #define TME_SUNCG2_REG_BITMAP(x)               (0x000000 + (TME_SUNCG2_SIZ_BITMAP * (x)))
        !            70: #define TME_SUNCG2_SIZ_BITMAP                  ((1024 * 1024) / 8)
        !            71: 
        !            72: /* the pixmap has one byte per pixel: */
        !            73: #define TME_SUNCG2_REG_PIXMAP                  (0x100000)
        !            74: #define TME_SUNCG2_SIZ_PIXMAP                  (1024 * 1024)
        !            75: 
        !            76: /* the raster op data: */
        !            77: #define TME_SUNCG2_REG_ROP_DATA                        (0x200000)
        !            78: 
        !            79: /* register offsets and sizes.  many registers are decoded at all
        !            80:    size-aligned addresses within a 4KB page: */
        !            81: #define TME_SUNCG2_SIZ_REG_PAGE                        (0x001000)
        !            82: #define TME_SUNCG2_REG_ROPC_UNIT(x)            (0x300000 + ((x) * TME_SUNCG2_SIZ_REG_PAGE))
        !            83: #define TME_SUNCG2_REG_ROPC_UNIT_PRIME(x)      (TME_SUNCG2_REG_ROPC_UNIT(x) + 0x000800)
        !            84: #define TME_SUNCG2_REG_CSR                     (0x309000)
        !            85: #define TME_SUNCG2_REG_PLANE_MASK              (0x30a000)
        !            86: #define TME_SUNCG2_REG_SUN2_PAN_HI             (0x30b000)
        !            87: #define TME_SUNCG2_REG_SUN3_DOUBLE_BUF         (0x30b000)
        !            88: #define TME_SUNCG2_REG_SUN2_ZOOM               (0x30c000)
        !            89: #define TME_SUNCG2_REG_SUN3_DMA_BASE           (0x30c000)
        !            90: #define TME_SUNCG2_REG_SUN2_PAN_LO             (0x30d000)
        !            91: #define TME_SUNCG2_REG_SUN3_DMA_WIDTH          (0x30d000)
        !            92: #define TME_SUNCG2_REG_SUN2_ZOOM_VAR           (0x30e000)
        !            93: #define TME_SUNCG2_REG_SUN3_FRAME_COUNT                (0x30e000)
        !            94: #define TME_SUNCG2_REG_INTVEC                  (0x30f000)
        !            95: #define TME_SUNCG2_REG_CMAP_R                  (0x310000)
        !            96: #define TME_SUNCG2_REG_CMAP_G                  (0x310200)
        !            97: #define TME_SUNCG2_REG_CMAP_B                  (0x310400)
        !            98: #define TME_SUNCG2_SIZ_REGS                    (0x310600)
        !            99: 
        !           100: /* the bits in the Control/Status register: */
        !           101: #define TME_SUNCG2_CSR_ENABLE_VIDEO            (0x0001)
        !           102: #define TME_SUNCG2_CSR_CMAP_UPDATE             (0x0002)
        !           103: #define TME_SUNCG2_CSR_INT_ENABLE              (0x0004)
        !           104: #define TME_SUNCG2_CSR_ROP_MODE_MASK           (0x0038)
        !           105: #define  TME_SUNCG2_CSR_ROP_MODE_PRWWRD                 (0x0000)
        !           106: #define  TME_SUNCG2_CSR_ROP_MODE_SRWPIX                 (0x0008)
        !           107: #define  TME_SUNCG2_CSR_ROP_MODE_PWWWRD                 (0x0010)
        !           108: #define  TME_SUNCG2_CSR_ROP_MODE_SWWPIX                 (0x0018)
        !           109: #define  TME_SUNCG2_CSR_ROP_MODE_PRRWRD                 (0x0020)
        !           110: #define  TME_SUNCG2_CSR_ROP_MODE_PRWPIX                 (0x0028)
        !           111: #define  TME_SUNCG2_CSR_ROP_MODE_PWRWRD                 (0x0030)
        !           112: #define  TME_SUNCG2_CSR_ROP_MODE_PWWPIX                 (0x0038)
        !           113: #define TME_SUNCG2_CSR_INT_ACTIVE              (0x0040)
        !           114: #define TME_SUNCG2_CSR_RETRACE                 (0x0080)
        !           115: #define TME_SUNCG2_CSR_SIZE_MASK_SUN2          (0x0f00)
        !           116: #define TME_SUNCG2_CSR_SIZE_MASK_SUN3          (0x0100)
        !           117: #define  TME_SUNCG2_CSR_SIZE_1152_900           (0x0000)
        !           118: #define  TME_SUNCG2_CSR_SIZE_1024_1024          (0x0100)
        !           119: 
        !           120: /* the raster ops: */
        !           121: #define TME_SUNCG2_ROP_SRC                     (0xcc)
        !           122: #define TME_SUNCG2_ROP_DST                     (0xaa)
        !           123: #define TME_SUNCG2_ROP_NOT(x)                  ((x) ^ 0xff)
        !           124: 
        !           125: /* the callout flags: */
        !           126: #define TME_SUNCG2_CALLOUT_CHECK               (0)
        !           127: #define TME_SUNCG2_CALLOUT_RUNNING             TME_BIT(0)
        !           128: #define TME_SUNCG2_CALLOUTS_MASK               (-2)
        !           129: #define  TME_SUNCG2_CALLOUT_MODE_CHANGE                TME_BIT(1)
        !           130: #define         TME_SUNCG2_CALLOUT_INT                 TME_BIT(2)
        !           131: 
        !           132: /* state flags: */
        !           133: #define TME_SUNCG2_FLAG_INVALID_DISPLAYED      TME_BIT(0)
        !           134: #define TME_SUNCG2_FLAG_INVALID_PIXMAP         TME_BIT(1)
        !           135: #define TME_SUNCG2_FLAG_INVALID_BITMAPS                TME_BIT(2)
        !           136: #define TME_SUNCG2_FLAG_CALLOUT_THREAD_RUNNING TME_BIT(3)
        !           137: 
        !           138: /* structures: */
        !           139: 
        !           140: /* the card: */
        !           141: struct tme_suncg2 {
        !           142: 
        !           143:   /* our simple bus device header: */
        !           144:   struct tme_bus_device tme_suncg2_device;
        !           145: #define tme_suncg2_element tme_suncg2_device.tme_bus_device_element
        !           146: 
        !           147:   /* the mutex protecting the card: */
        !           148:   tme_mutex_t tme_suncg2_mutex;
        !           149: 
        !           150:   /* the rwlock protecting the card: */
        !           151:   tme_rwlock_t tme_suncg2_rwlock;
        !           152: 
        !           153:   /* the framebuffer connection: */
        !           154:   struct tme_fb_connection *tme_suncg2_fb_connection;
        !           155: 
        !           156:   /* the callout flags: */
        !           157:   int tme_suncg2_callout_flags;
        !           158: 
        !           159:   /* the type of the cgtwo: */
        !           160:   tme_uint32_t tme_suncg2_type;
        !           161: 
        !           162:   /* the size of the bwtwo: */
        !           163:   tme_uint32_t tme_suncg2_size;
        !           164: 
        !           165:   /* the number of displayed pixels: */
        !           166:   tme_uint32_t tme_suncg2_pixel_count;
        !           167: 
        !           168:   /* the raw memory: */
        !           169:   tme_uint8_t *tme_suncg2_raw_memory;
        !           170: 
        !           171:   /* the displayed memory: */
        !           172:   tme_uint8_t *tme_suncg2_displayed_memory;
        !           173: 
        !           174:   /* the rasterop registers: */
        !           175:   struct {
        !           176:     tme_uint16_t tme_suncg2_ropc_dest;
        !           177:     tme_uint16_t tme_suncg2_ropc_source1;
        !           178:     tme_uint16_t tme_suncg2_ropc_source2;
        !           179:     tme_uint16_t tme_suncg2_ropc_pattern;
        !           180:     tme_uint16_t tme_suncg2_ropc_mask1;
        !           181:     tme_uint16_t tme_suncg2_ropc_mask2;
        !           182:     tme_uint16_t tme_suncg2_ropc_ena_shift;
        !           183:     tme_uint16_t tme_suncg2_ropc_op;
        !           184:     tme_uint16_t tme_suncg2_ropc_width;
        !           185:     tme_uint16_t tme_suncg2_ropc_opcount;
        !           186:     tme_uint16_t tme_suncg2_ropc_decoderout;
        !           187:     tme_uint16_t tme_suncg2_ropc_x11;
        !           188:     tme_uint16_t tme_suncg2_ropc_x12;
        !           189:     tme_uint16_t tme_suncg2_ropc_x13;
        !           190:     tme_uint16_t tme_suncg2_ropc_x14;
        !           191:     tme_uint16_t tme_suncg2_ropc_x15;
        !           192:   } tme_suncg2_ropc[TME_SUNCG2_ROPC_PRIME * 2];
        !           193: 
        !           194:   /* our csr: */
        !           195:   tme_uint16_t tme_suncg2_csr;
        !           196: 
        !           197:   /* our interrupt vector: */
        !           198:   tme_uint16_t tme_suncg2_intvec;
        !           199: 
        !           200:   /* our plane mask: */
        !           201:   tme_uint16_t tme_suncg2_plane_mask;
        !           202: 
        !           203:   /* the raw colormap: */
        !           204:   tme_uint16_t tme_suncg2_cmap_raw[(1 << TME_SUNCG2_PLANE_MAX) * 3];
        !           205:   
        !           206:   /* the cooked colormap: */
        !           207:   tme_uint8_t tme_suncg2_cmap[(1 << TME_SUNCG2_PLANE_MAX) * 3];
        !           208: 
        !           209:   /* if this is zero, the next CSR read will have the retrace bit set: */
        !           210:   unsigned int tme_suncg2_cycle_retrace;
        !           211: 
        !           212:   /* if this is TME_SUNCG2_PLANE_MAX, we are displaying the pixmap,
        !           213:      else we are displaying this plane's bitmap: */
        !           214:   unsigned int tme_suncg2_bitmap_mode_plane;
        !           215: 
        !           216:   /* state flags: */
        !           217:   unsigned int tme_suncg2_flags;
        !           218: 
        !           219:   /* any outstanding TLBs: */
        !           220:   struct tme_bus_tlb *tme_suncg2_tlbs[4];
        !           221:   unsigned int tme_suncg2_tlb_head;
        !           222: 
        !           223:   /* a rasterop buffered SRC value: */
        !           224:   tme_uint16_t tme_suncg2_rop_src_buffer;
        !           225: };
        !           226: 
        !           227: /* globals: */
        !           228: 
        !           229: #ifndef TME_NO_LOG
        !           230: static const char *_tme_suncg2_ropc_regs[] = 
        !           231:   { "dest",
        !           232:     "source1",
        !           233:     "source2",
        !           234:     "pattern",
        !           235:     "mask1",
        !           236:     "mask2",
        !           237:     "ena_shift",
        !           238:     "op",
        !           239:     "width",
        !           240:     "opcount",
        !           241:     "decoderout",
        !           242:     "x11",
        !           243:     "x12",
        !           244:     "x13",
        !           245:     "x14",
        !           246:     "x15",
        !           247:   };
        !           248: #endif /* !TME_NO_LOG */    
        !           249: 
        !           250: /* this invalidates any outstanding TLBs: */
        !           251: static void
        !           252: _tme_suncg2_tlb_invalidate(struct tme_suncg2 *suncg2, struct tme_bus_tlb *tlb_valid)
        !           253: {
        !           254:   unsigned int tlb_i;
        !           255:   struct tme_bus_tlb *tlb;
        !           256: 
        !           257:   if (tlb_valid != NULL) {
        !           258:     tlb_valid = TME_ATOMIC_READ(struct tme_bus_tlb *, 
        !           259:                                tlb_valid->tme_bus_tlb_backing_reservation);
        !           260:   }
        !           261: 
        !           262:   for (tlb_i = 0; tlb_i < TME_ARRAY_ELS(suncg2->tme_suncg2_tlbs); tlb_i++) {
        !           263:     tlb = suncg2->tme_suncg2_tlbs[tlb_i];
        !           264:     suncg2->tme_suncg2_tlbs[tlb_i] = NULL;
        !           265:     if (tlb != NULL
        !           266:        && tlb != tlb_valid) {
        !           267:       tme_bus_tlb_invalidate(tlb);
        !           268:     }
        !           269:   }
        !           270: }
        !           271: 
        !           272: /* this adds an outstanding TLB: */
        !           273: static void
        !           274: _tme_suncg2_tlb_add(struct tme_suncg2 *suncg2, struct tme_bus_tlb *tlb_valid)
        !           275: {
        !           276:   struct tme_bus_tlb *tlb;
        !           277: 
        !           278:   tlb_valid = TME_ATOMIC_READ(struct tme_bus_tlb *, 
        !           279:                              tlb_valid->tme_bus_tlb_backing_reservation);
        !           280: 
        !           281:   tlb = suncg2->tme_suncg2_tlbs[suncg2->tme_suncg2_tlb_head % TME_ARRAY_ELS(suncg2->tme_suncg2_tlbs)];
        !           282:   if (tlb != NULL
        !           283:       && tlb != tlb_valid) {
        !           284:     tme_bus_tlb_invalidate(tlb);
        !           285:   }
        !           286:   suncg2->tme_suncg2_tlbs[suncg2->tme_suncg2_tlb_head % TME_ARRAY_ELS(suncg2->tme_suncg2_tlbs)] = tlb_valid;
        !           287:   suncg2->tme_suncg2_tlb_head++;
        !           288: }
        !           289: 
        !           290: /* this validates the bitmaps: */
        !           291: static void
        !           292: _tme_suncg2_validate_bitmaps(struct tme_suncg2 *suncg2, struct tme_bus_tlb *tlb)
        !           293: {
        !           294: #if SIZEOF_LONG > 4
        !           295:   const unsigned long *pixmap_pointer;
        !           296:   unsigned long pixmap;
        !           297: #else  /* SIZEOF_LONG <= 4 */
        !           298:   const tme_uint32_t *pixmap_pointer;
        !           299:   tme_uint32_t pixmap;
        !           300: #endif /* SIZEOF_LONG <= 4 */
        !           301:   tme_uint32_t pixmap_resid;
        !           302:   tme_uint32_t bitmaps_lo;
        !           303:   tme_uint32_t bitmaps_hi;
        !           304:   tme_uint8_t *bitmap_pointer;
        !           305: 
        !           306:   /* if the bitmaps are invalid: */
        !           307:   if (suncg2->tme_suncg2_flags & TME_SUNCG2_FLAG_INVALID_BITMAPS) {
        !           308: 
        !           309:     /* the pixmap must not be invalid: */
        !           310:     assert (!(suncg2->tme_suncg2_flags & TME_SUNCG2_FLAG_INVALID_PIXMAP));
        !           311: 
        !           312:     /* invalidate any outstanding TLBs: */
        !           313:     _tme_suncg2_tlb_invalidate(suncg2, tlb);
        !           314: 
        !           315:     /* if we are displaying the pixmap: */
        !           316:     if (suncg2->tme_suncg2_bitmap_mode_plane == TME_SUNCG2_PLANE_MAX) {
        !           317: 
        !           318:       /* if the displayed memory is not invalid: */
        !           319:       if (!(suncg2->tme_suncg2_flags & TME_SUNCG2_FLAG_INVALID_DISPLAYED)) {
        !           320: 
        !           321:        /* copy the displayed memory back into the pixmap: */
        !           322:        memcpy((suncg2->tme_suncg2_raw_memory
        !           323:                + TME_SUNCG2_REG_PIXMAP),
        !           324:               suncg2->tme_suncg2_displayed_memory,
        !           325:               TME_SUNCG2_SIZ_PIXMAP);
        !           326:       }
        !           327:     }
        !           328: 
        !           329:     /* otherwise, we're displaying a bitmap: */
        !           330:     else {
        !           331: 
        !           332:       /* the displayed memory must be invalid: */
        !           333:       assert (suncg2->tme_suncg2_flags & TME_SUNCG2_FLAG_INVALID_DISPLAYED);
        !           334:     }
        !           335: 
        !           336:     /* start in the pixmap: */
        !           337:     pixmap_pointer = (tme_uint32_t *) (suncg2->tme_suncg2_raw_memory + TME_SUNCG2_REG_PIXMAP);
        !           338:     pixmap_resid = TME_SUNCG2_SIZ_PIXMAP;
        !           339:     pixmap = 0;
        !           340:   
        !           341:     /* start in the bitmaps: */
        !           342:     bitmap_pointer = suncg2->tme_suncg2_raw_memory + TME_SUNCG2_REG_BITMAP(0);
        !           343:     bitmaps_lo = 0;
        !           344:     bitmaps_hi = 0;
        !           345: 
        !           346:     /* do the translation: */
        !           347:     do {
        !           348: 
        !           349:       /* if the pixmap data is empty, reload it: */
        !           350:       if (__tme_predict_false((pixmap_resid % sizeof(pixmap)) == 0)) {
        !           351:        pixmap = *(pixmap_pointer++);
        !           352:        pixmap = tme_betoh_u32(pixmap);
        !           353:       }
        !           354: 
        !           355:       /* translate another pixel's bits into the bitmaps: */
        !           356:       bitmaps_lo >>= 1;
        !           357:       if (pixmap & TME_BIT(0)) bitmaps_lo |= 0x00000080;
        !           358:       if (pixmap & TME_BIT(1)) bitmaps_lo |= 0x00008000;
        !           359:       if (pixmap & TME_BIT(2)) bitmaps_lo |= 0x00800000;
        !           360:       if (pixmap & TME_BIT(3)) bitmaps_lo |= 0x80000000;
        !           361:       bitmaps_hi >>= 1;
        !           362:       if (pixmap & TME_BIT(4)) bitmaps_hi |= 0x00000080;
        !           363:       if (pixmap & TME_BIT(5)) bitmaps_hi |= 0x00008000;
        !           364:       if (pixmap & TME_BIT(6)) bitmaps_hi |= 0x00800000;
        !           365:       if (pixmap & TME_BIT(7)) bitmaps_hi |= 0x80000000;
        !           366: 
        !           367:       /* we have translated another pixel: */
        !           368:       pixmap >>= 8;
        !           369:       pixmap_resid--;
        !           370: 
        !           371:       /* after every eight pixels, we have another eight bytes of bitmap
        !           372:         data to write out: */
        !           373:       if (__tme_predict_false((pixmap_resid % 8) == 0)) {
        !           374:        bitmap_pointer[TME_SUNCG2_SIZ_BITMAP * 0] = TME_FIELD_MASK_EXTRACTU(bitmaps_lo, 0x000000ff);
        !           375:        bitmap_pointer[TME_SUNCG2_SIZ_BITMAP * 1] = TME_FIELD_MASK_EXTRACTU(bitmaps_lo, 0x0000ff00);
        !           376:        bitmap_pointer[TME_SUNCG2_SIZ_BITMAP * 2] = TME_FIELD_MASK_EXTRACTU(bitmaps_lo, 0x00ff0000);
        !           377:        bitmap_pointer[TME_SUNCG2_SIZ_BITMAP * 3] = TME_FIELD_MASK_EXTRACTU(bitmaps_lo, 0xff000000);
        !           378:        bitmaps_lo = 0;
        !           379:        bitmap_pointer[TME_SUNCG2_SIZ_BITMAP * 4] = TME_FIELD_MASK_EXTRACTU(bitmaps_hi, 0x000000ff);
        !           380:        bitmap_pointer[TME_SUNCG2_SIZ_BITMAP * 5] = TME_FIELD_MASK_EXTRACTU(bitmaps_hi, 0x0000ff00);
        !           381:        bitmap_pointer[TME_SUNCG2_SIZ_BITMAP * 6] = TME_FIELD_MASK_EXTRACTU(bitmaps_hi, 0x00ff0000);
        !           382:        bitmap_pointer[TME_SUNCG2_SIZ_BITMAP * 7] = TME_FIELD_MASK_EXTRACTU(bitmaps_hi, 0xff000000);
        !           383:        bitmaps_hi = 0;
        !           384:        bitmap_pointer++;
        !           385:       }
        !           386: 
        !           387:       /* loop while we have pixmap bytes remaining: */
        !           388:     } while (pixmap_resid > 0);
        !           389: 
        !           390:     /* the bitmaps are no longer invalid: */
        !           391:     suncg2->tme_suncg2_flags &= ~TME_SUNCG2_FLAG_INVALID_BITMAPS;
        !           392:   }
        !           393: 
        !           394:   /* otherwise, the bitmaps are valid: */
        !           395:   else {
        !           396: 
        !           397:     /* if our caller needs the actual raw bitmap memory valid
        !           398:        (indicated by tlb == NULL): */
        !           399:     if (tlb == NULL) {
        !           400: 
        !           401:       /* invalidate any outstanding TLBs: */
        !           402:       _tme_suncg2_tlb_invalidate(suncg2, NULL);
        !           403: 
        !           404:       /* if we're displaying a bitmap: */
        !           405:       if (suncg2->tme_suncg2_bitmap_mode_plane != TME_SUNCG2_PLANE_MAX) {
        !           406: 
        !           407:        /* if the displayed memory is not invalid: */
        !           408:        if (!(suncg2->tme_suncg2_flags & TME_SUNCG2_FLAG_INVALID_DISPLAYED)) {
        !           409: 
        !           410:          /* copy the displayed memory back into the bitmap: */
        !           411:          memcpy((suncg2->tme_suncg2_raw_memory
        !           412:                  + TME_SUNCG2_REG_BITMAP(suncg2->tme_suncg2_bitmap_mode_plane)),
        !           413:                 suncg2->tme_suncg2_displayed_memory,
        !           414:                 TME_SUNCG2_SIZ_BITMAP);
        !           415:        }
        !           416:       }
        !           417:     }
        !           418:   }
        !           419: }
        !           420: 
        !           421: /* this validates the pixmap: */
        !           422: static void
        !           423: _tme_suncg2_validate_pixmap(struct tme_suncg2 *suncg2, struct tme_bus_tlb *tlb)
        !           424: {
        !           425: #if SIZEOF_LONG > 4
        !           426:   unsigned long *pixmap_pointer;
        !           427:   unsigned long pixmap;
        !           428: #else  /* SIZEOF_LONG <= 4 */
        !           429:   tme_uint32_t *pixmap_pointer;
        !           430:   tme_uint32_t pixmap;
        !           431: #endif /* SIZEOF_LONG <= 4 */
        !           432:   tme_uint32_t pixmap_resid;
        !           433:   tme_uint32_t bitmaps_lo;
        !           434:   tme_uint32_t bitmaps_hi;
        !           435:   const tme_uint8_t *bitmap_pointer;
        !           436: 
        !           437:   /* if the pixmap is invalid: */
        !           438:   if (suncg2->tme_suncg2_flags & TME_SUNCG2_FLAG_INVALID_PIXMAP) {
        !           439: 
        !           440:     /* the bitmaps must not be invalid: */
        !           441:     assert (!(suncg2->tme_suncg2_flags & TME_SUNCG2_FLAG_INVALID_BITMAPS));
        !           442: 
        !           443:     /* invalidate any outstanding TLBs: */
        !           444:     _tme_suncg2_tlb_invalidate(suncg2, tlb);
        !           445: 
        !           446:     /* if we are displaying a bitmap: */
        !           447:     if (suncg2->tme_suncg2_bitmap_mode_plane != TME_SUNCG2_PLANE_MAX) {
        !           448: 
        !           449:       /* if the displayed memory is not invalid: */
        !           450:       if (!(suncg2->tme_suncg2_flags & TME_SUNCG2_FLAG_INVALID_DISPLAYED)) {
        !           451: 
        !           452:        /* copy the displayed memory back into the bitmap: */
        !           453:        memcpy((suncg2->tme_suncg2_raw_memory
        !           454:                + TME_SUNCG2_REG_BITMAP(suncg2->tme_suncg2_bitmap_mode_plane)),
        !           455:               suncg2->tme_suncg2_displayed_memory,
        !           456:               TME_SUNCG2_SIZ_BITMAP);
        !           457:       }
        !           458:     }
        !           459: 
        !           460:     /* otherwise, we're displaying the pixmap: */
        !           461:     else {
        !           462: 
        !           463:       /* the displayed memory must be invalid: */
        !           464:       assert (suncg2->tme_suncg2_flags & TME_SUNCG2_FLAG_INVALID_DISPLAYED);
        !           465:     }
        !           466: 
        !           467:     /* start in the pixmap: */
        !           468:     pixmap_pointer = (tme_uint32_t *) (suncg2->tme_suncg2_raw_memory + TME_SUNCG2_REG_PIXMAP);
        !           469:     pixmap_resid = TME_SUNCG2_SIZ_PIXMAP;
        !           470:     pixmap = 0;
        !           471:   
        !           472:     /* start in the bitmaps: */
        !           473:     bitmap_pointer = suncg2->tme_suncg2_raw_memory + TME_SUNCG2_REG_BITMAP(0);
        !           474:     bitmaps_lo = 0;
        !           475:     bitmaps_hi = 0;
        !           476: 
        !           477:     /* do the translation: */
        !           478:     do {
        !           479: 
        !           480:       /* if the bitmap data is empty, reload it: */
        !           481:       if (__tme_predict_false((pixmap_resid % 8) == 0)) {
        !           482:        bitmaps_lo
        !           483:          = ((((tme_uint32_t) bitmap_pointer[TME_SUNCG2_SIZ_BITMAP * 0]) << 0)
        !           484:             | (((tme_uint32_t) bitmap_pointer[TME_SUNCG2_SIZ_BITMAP * 1]) << 8)
        !           485:             | (((tme_uint32_t) bitmap_pointer[TME_SUNCG2_SIZ_BITMAP * 2]) << 16)
        !           486:             | (((tme_uint32_t) bitmap_pointer[TME_SUNCG2_SIZ_BITMAP * 3]) << 24));
        !           487:        bitmaps_hi
        !           488:          = ((((tme_uint32_t) bitmap_pointer[TME_SUNCG2_SIZ_BITMAP * 4]) << 0)
        !           489:             | (((tme_uint32_t) bitmap_pointer[TME_SUNCG2_SIZ_BITMAP * 5]) << 8)
        !           490:             | (((tme_uint32_t) bitmap_pointer[TME_SUNCG2_SIZ_BITMAP * 6]) << 16)
        !           491:             | (((tme_uint32_t) bitmap_pointer[TME_SUNCG2_SIZ_BITMAP * 7]) << 24));
        !           492:        bitmap_pointer++;
        !           493:       }
        !           494: 
        !           495:       /* we are about to translate another pixel: */
        !           496:       pixmap <<= 8;
        !           497:       pixmap_resid--;
        !           498: 
        !           499:       /* translate another pixel's bits from the bitmaps: */
        !           500:       if (bitmaps_lo & 0x00000080) pixmap |= TME_BIT(0);
        !           501:       if (bitmaps_lo & 0x00008000) pixmap |= TME_BIT(1);
        !           502:       if (bitmaps_lo & 0x00800000) pixmap |= TME_BIT(2);
        !           503:       if (bitmaps_lo & 0x80000000) pixmap |= TME_BIT(3);
        !           504:       bitmaps_lo <<= 1;
        !           505:       if (bitmaps_hi & 0x00000080) pixmap |= TME_BIT(4);
        !           506:       if (bitmaps_hi & 0x00008000) pixmap |= TME_BIT(5);
        !           507:       if (bitmaps_hi & 0x00800000) pixmap |= TME_BIT(6);
        !           508:       if (bitmaps_hi & 0x80000000) pixmap |= TME_BIT(7);
        !           509:       bitmaps_hi <<= 1;
        !           510:     
        !           511:       /* if the pixmap data is full, write it: */
        !           512:       if (__tme_predict_false((pixmap_resid % sizeof(pixmap)) == 0)) {
        !           513:        *(pixmap_pointer++) = tme_htobe_u32(pixmap);
        !           514:        pixmap = 0;
        !           515:       }
        !           516: 
        !           517:       /* loop while we have pixmap bytes remaining: */
        !           518:     } while (pixmap_resid > 0);
        !           519: 
        !           520:     /* the pixmap is no longer invalid, but the bitmaps are: */
        !           521:     suncg2->tme_suncg2_flags &= ~TME_SUNCG2_FLAG_INVALID_PIXMAP;
        !           522:   }
        !           523: 
        !           524:   /* otherwise, the pixmap is valid: */
        !           525:   else {
        !           526: 
        !           527:     /* if our caller needs the actual raw pixmap memory valid
        !           528:        (indicated by tlb == NULL): */
        !           529:     if (tlb == NULL) {
        !           530: 
        !           531:       /* invalidate any outstanding TLBs: */
        !           532:       _tme_suncg2_tlb_invalidate(suncg2, NULL);
        !           533: 
        !           534:       /* if we're displaying the pixmap: */
        !           535:       if (suncg2->tme_suncg2_bitmap_mode_plane == TME_SUNCG2_PLANE_MAX) {
        !           536: 
        !           537:        /* if the displayed memory is not invalid: */
        !           538:        if (!(suncg2->tme_suncg2_flags & TME_SUNCG2_FLAG_INVALID_DISPLAYED)) {
        !           539: 
        !           540:          /* copy the displayed memory back into the pixmap: */
        !           541:          memcpy((suncg2->tme_suncg2_raw_memory
        !           542:                  + TME_SUNCG2_REG_PIXMAP),
        !           543:                 suncg2->tme_suncg2_displayed_memory,
        !           544:                 TME_SUNCG2_SIZ_PIXMAP);
        !           545:        }
        !           546:       }
        !           547:     }
        !           548:   }
        !           549: }
        !           550: 
        !           551: /* this validates the displayed memory: */
        !           552: static void
        !           553: _tme_suncg2_validate_displayed(struct tme_suncg2 *suncg2, struct tme_bus_tlb *tlb)
        !           554: {
        !           555: 
        !           556:   /* if the displayed memory is invalid: */
        !           557:   if (suncg2->tme_suncg2_flags & TME_SUNCG2_FLAG_INVALID_DISPLAYED) {
        !           558: 
        !           559:     /* if we're displaying the pixmap: */
        !           560:     if (suncg2->tme_suncg2_bitmap_mode_plane == TME_SUNCG2_PLANE_MAX) {
        !           561: 
        !           562:       /* validate the pixmap: */
        !           563:       _tme_suncg2_validate_pixmap(suncg2, tlb);
        !           564: 
        !           565:       /* copy the pixmap into the displayed memory: */
        !           566:       memcpy(suncg2->tme_suncg2_displayed_memory,
        !           567:             (suncg2->tme_suncg2_raw_memory
        !           568:              + TME_SUNCG2_REG_PIXMAP),
        !           569:             TME_SUNCG2_SIZ_PIXMAP);
        !           570:     }
        !           571: 
        !           572:     /* otherwise, we're displaying a bitmap: */
        !           573:     else {
        !           574: 
        !           575:       /* validate the bitmaps: */
        !           576:       _tme_suncg2_validate_bitmaps(suncg2, tlb);
        !           577: 
        !           578:       /* copy the bitmap into the displayed memory: */
        !           579:       memcpy(suncg2->tme_suncg2_displayed_memory,
        !           580:             (suncg2->tme_suncg2_raw_memory
        !           581:              + TME_SUNCG2_REG_BITMAP(suncg2->tme_suncg2_bitmap_mode_plane)),
        !           582:             TME_SUNCG2_SIZ_BITMAP);
        !           583:     }
        !           584: 
        !           585:     /* the displayed memory is no longer invalid: */
        !           586:     suncg2->tme_suncg2_flags &= ~TME_SUNCG2_FLAG_INVALID_DISPLAYED;
        !           587:   }
        !           588: }
        !           589: 
        !           590: /* this handles a mode change callout: */
        !           591: static int
        !           592: _tme_suncg2_mode_change(struct tme_suncg2 *suncg2)
        !           593: {
        !           594:   struct tme_fb_connection *conn_fb_other;
        !           595:   struct tme_fb_connection *conn_fb;
        !           596:   unsigned int pixel_i;
        !           597:   unsigned int mono_mask;
        !           598:   tme_uint32_t color0;
        !           599:   tme_uint32_t color1;
        !           600:   tme_uint32_t color;
        !           601:   unsigned int bitmap_mode_plane;
        !           602:   unsigned int color_i;
        !           603:   int rc;
        !           604: 
        !           605:   /* this makes a color for a pixel: */
        !           606: #define _TME_SUNCG2_PIXEL_COLOR(pixel)                                 \
        !           607:   ((TME_SUNCG2_CMAP_VALUE(suncg2, pixel, TME_SUNCG2_REG_CMAP_G) << 0)  \
        !           608:    | (TME_SUNCG2_CMAP_VALUE(suncg2, pixel, TME_SUNCG2_REG_CMAP_R) << 8)        \
        !           609:    | (TME_SUNCG2_CMAP_VALUE(suncg2, pixel, TME_SUNCG2_REG_CMAP_B) << 16))
        !           610: 
        !           611:   /* if we are to display a bitmap, the color for pixmap pixel zero
        !           612:      must be the color for bitmap pixel zero, and the color for pixmap
        !           613:      pixel 255 must be the color for bitmap pixel one: */
        !           614:   color0 = _TME_SUNCG2_PIXEL_COLOR(0);
        !           615:   color1 = _TME_SUNCG2_PIXEL_COLOR(255);
        !           616: 
        !           617:   /* we don't know what the monochrome mask is yet: */
        !           618:   mono_mask = 0xff;
        !           619: 
        !           620:   /* loop over the other pixels: */
        !           621:   for (pixel_i = 1; pixel_i < 255; pixel_i++) {
        !           622: 
        !           623:     /* get the color for this pixel: */
        !           624:     color = _TME_SUNCG2_PIXEL_COLOR(pixel_i);
        !           625: 
        !           626:     /* if this matches color0: */
        !           627:     if (color == color0) {
        !           628: 
        !           629:       /* any set bits in this pixel number can't be in the monochrome
        !           630:         mask: */
        !           631:       mono_mask &= ~pixel_i;
        !           632:     }
        !           633: 
        !           634:     /* else, if this matches color1: */
        !           635:     else if (color == color1) {
        !           636: 
        !           637:       /* any clear bits in this pixel number can't be in the
        !           638:         monochrome mask: */
        !           639:       mono_mask &= pixel_i;
        !           640:     }
        !           641: 
        !           642:     /* otherwise, this is some other color: */
        !           643:     else {
        !           644: 
        !           645:       /* we can't be in bitmap mode: */
        !           646:       mono_mask = 0;
        !           647:       break;
        !           648:     }
        !           649:   }
        !           650: 
        !           651:   /* if we completed the above loop, but our monochrome mask is zero,
        !           652:      the colors for all pixel values must be the same.  while strange,
        !           653:      we tolerate this, and take the least significant bit as the
        !           654:      monochrome mask: */
        !           655:   if (pixel_i == 255
        !           656:       && mono_mask == 0) {
        !           657:     assert (color0 == color1);
        !           658:     mono_mask = 1;
        !           659:   }
        !           660: 
        !           661:   /* if the monochrome mask is zero, we must display the pixmap, else
        !           662:      we display the bitmap corresponding to the least significant set
        !           663:      bit in the monochrome mask: */
        !           664:   if (mono_mask == 0) {
        !           665:     bitmap_mode_plane = TME_SUNCG2_PLANE_MAX;
        !           666:   }
        !           667:   else {
        !           668:     for (bitmap_mode_plane = 0;
        !           669:         (mono_mask & 1) == 0;
        !           670:         bitmap_mode_plane++, mono_mask >>= 1);
        !           671:   }
        !           672: 
        !           673: #undef _TME_SUNCG2_PIXEL_COLOR
        !           674: 
        !           675:   /* get both sides of the framebuffer connection: */
        !           676:   conn_fb_other = suncg2->tme_suncg2_fb_connection;
        !           677:   conn_fb = (struct tme_fb_connection *) conn_fb_other->tme_fb_connection.tme_connection_other;
        !           678: 
        !           679:   /* if we are displaying the pixmap: */
        !           680:   if (bitmap_mode_plane == TME_SUNCG2_PLANE_MAX) {
        !           681: 
        !           682:     /* the pixmap is eight bits deep: */
        !           683:     conn_fb->tme_fb_connection_depth = TME_SUNCG2_PLANE_MAX;
        !           684:     conn_fb->tme_fb_connection_bits_per_pixel = TME_SUNCG2_PLANE_MAX;
        !           685:     
        !           686:     /* recook the colormap: */
        !           687:     for (color_i = 0;
        !           688:         color_i < TME_ARRAY_ELS(suncg2->tme_suncg2_cmap_raw);
        !           689:         color_i++) {
        !           690:       suncg2->tme_suncg2_cmap[color_i] = tme_betoh_u16(suncg2->tme_suncg2_cmap_raw[color_i]);
        !           691:     }
        !           692:   }
        !           693: 
        !           694:   /* otherwise, we can display a bitmap: */
        !           695:   else {
        !           696: 
        !           697:     /* a bitmap is one bit deep: */
        !           698:     conn_fb->tme_fb_connection_depth = 1;
        !           699:     conn_fb->tme_fb_connection_bits_per_pixel = 1;
        !           700: 
        !           701:     /* cook the monochrome colormap: */
        !           702:     suncg2->tme_suncg2_cmap[TME_SUNCG2_CMAP_INDEX(0, TME_SUNCG2_REG_CMAP_G)] = TME_SUNCG2_CMAP_VALUE(suncg2, 0, TME_SUNCG2_REG_CMAP_G);
        !           703:     suncg2->tme_suncg2_cmap[TME_SUNCG2_CMAP_INDEX(0, TME_SUNCG2_REG_CMAP_R)] = TME_SUNCG2_CMAP_VALUE(suncg2, 0, TME_SUNCG2_REG_CMAP_R);
        !           704:     suncg2->tme_suncg2_cmap[TME_SUNCG2_CMAP_INDEX(0, TME_SUNCG2_REG_CMAP_B)] = TME_SUNCG2_CMAP_VALUE(suncg2, 0, TME_SUNCG2_REG_CMAP_B);
        !           705:     suncg2->tme_suncg2_cmap[TME_SUNCG2_CMAP_INDEX(1, TME_SUNCG2_REG_CMAP_G)] = TME_SUNCG2_CMAP_VALUE(suncg2, 255, TME_SUNCG2_REG_CMAP_G);
        !           706:     suncg2->tme_suncg2_cmap[TME_SUNCG2_CMAP_INDEX(1, TME_SUNCG2_REG_CMAP_R)] = TME_SUNCG2_CMAP_VALUE(suncg2, 255, TME_SUNCG2_REG_CMAP_R);
        !           707:     suncg2->tme_suncg2_cmap[TME_SUNCG2_CMAP_INDEX(1, TME_SUNCG2_REG_CMAP_B)] = TME_SUNCG2_CMAP_VALUE(suncg2, 255, TME_SUNCG2_REG_CMAP_B);
        !           708:   }
        !           709: 
        !           710:   /* if the display is changing: */
        !           711:   if (bitmap_mode_plane != suncg2->tme_suncg2_bitmap_mode_plane) {
        !           712: 
        !           713:     /* log the change: */
        !           714:     tme_log(&suncg2->tme_suncg2_element->tme_element_log_handle,
        !           715:            100, TME_OK,
        !           716:            (&suncg2->tme_suncg2_element->tme_element_log_handle,
        !           717:             "display changing from plane %u to plane %u",
        !           718:             suncg2->tme_suncg2_bitmap_mode_plane,
        !           719:             bitmap_mode_plane));
        !           720: 
        !           721:     /* if we were displaying the pixmap, validate the pixmap, else
        !           722:        validate the bitmaps, to copy the current displayed memory back
        !           723:        into the raw memory: */
        !           724:     if (suncg2->tme_suncg2_bitmap_mode_plane == TME_SUNCG2_PLANE_MAX) {
        !           725:       _tme_suncg2_validate_pixmap(suncg2, NULL);
        !           726:     }
        !           727:     else {
        !           728:       _tme_suncg2_validate_bitmaps(suncg2, NULL);
        !           729:     }
        !           730: 
        !           731:     /* invalidate any outstanding TLBs: */
        !           732:     _tme_suncg2_tlb_invalidate(suncg2, NULL);
        !           733: 
        !           734:     /* set the display: */
        !           735:     suncg2->tme_suncg2_bitmap_mode_plane = bitmap_mode_plane;
        !           736: 
        !           737:     /* free any previously allocated memory: */
        !           738:     if (suncg2->tme_suncg2_displayed_memory != NULL) {
        !           739:       tme_free(suncg2->tme_suncg2_displayed_memory);
        !           740:     }
        !           741: 
        !           742:     /* allocate memory for our framebuffer connection: */
        !           743:     rc = tme_fb_xlat_alloc_src(conn_fb);
        !           744:     assert (rc == TME_OK);
        !           745:     suncg2->tme_suncg2_displayed_memory = conn_fb->tme_fb_connection_buffer;
        !           746: 
        !           747:     /* the displayed memory is now invalid: */
        !           748:     suncg2->tme_suncg2_flags |= TME_SUNCG2_FLAG_INVALID_DISPLAYED;
        !           749:   }
        !           750: 
        !           751:   /* unlock the mutex: */
        !           752:   tme_mutex_unlock(&suncg2->tme_suncg2_mutex);
        !           753:       
        !           754:   /* do the callout: */
        !           755:   rc = (conn_fb_other != NULL
        !           756:        ? ((*conn_fb_other->tme_fb_connection_mode_change)
        !           757:           (conn_fb_other))
        !           758:        : TME_OK);
        !           759:       
        !           760:   /* lock the mutex: */
        !           761:   tme_mutex_lock(&suncg2->tme_suncg2_mutex);
        !           762: 
        !           763:   return (rc);
        !           764: }
        !           765: 
        !           766: /* the suncg2 callout function.  it must be called with the mutex locked: */
        !           767: static void
        !           768: _tme_suncg2_callout(struct tme_suncg2 *suncg2, int new_callouts)
        !           769: {
        !           770:   int callouts, later_callouts;
        !           771:   int rc;
        !           772: 
        !           773:   /* add in any new callouts: */
        !           774:   suncg2->tme_suncg2_callout_flags |= new_callouts;
        !           775: 
        !           776:   /* if this function is already running in another thread, simply
        !           777:      return now.  the other thread will do our work: */
        !           778:   if (suncg2->tme_suncg2_callout_flags
        !           779:       & TME_SUNCG2_CALLOUT_RUNNING) {
        !           780:     return;
        !           781:   }
        !           782: 
        !           783:   /* callouts are now running: */
        !           784:   suncg2->tme_suncg2_callout_flags
        !           785:     |= TME_SUNCG2_CALLOUT_RUNNING;
        !           786: 
        !           787:   /* assume that we won't need any later callouts: */
        !           788:   later_callouts = 0;
        !           789: 
        !           790:   /* loop while callouts are needed: */
        !           791:   for (; ((callouts
        !           792:           = suncg2->tme_suncg2_callout_flags)
        !           793:          & TME_SUNCG2_CALLOUTS_MASK); ) {
        !           794: 
        !           795:     /* clear the needed callouts: */
        !           796:     suncg2->tme_suncg2_callout_flags
        !           797:       = (callouts
        !           798:         & ~TME_SUNCG2_CALLOUTS_MASK);
        !           799:     callouts
        !           800:       &= TME_SUNCG2_CALLOUTS_MASK;
        !           801: 
        !           802:     /* if we need a mode change: */
        !           803:     if (new_callouts & TME_SUNCG2_CALLOUT_MODE_CHANGE) {
        !           804: 
        !           805:       /* call out the mode change: */
        !           806:       rc = _tme_suncg2_mode_change(suncg2);
        !           807: 
        !           808:       /* if the callout failed: */
        !           809:       if (rc != TME_OK) {
        !           810: 
        !           811:        /* remember that this callout should be attempted again at
        !           812:            some later time: */
        !           813:        later_callouts |= TME_SUNCG2_CALLOUT_MODE_CHANGE;
        !           814:       }
        !           815:     }
        !           816:   }
        !           817:   
        !           818:   /* put in any later callouts, and clear that callouts are running: */
        !           819:   suncg2->tme_suncg2_callout_flags = later_callouts;
        !           820: }
        !           821: 
        !           822: /* the callout thread: */
        !           823: static void
        !           824: _tme_suncg2_callout_thread(void *_suncg2)
        !           825: {
        !           826:   struct tme_suncg2 *suncg2;
        !           827: 
        !           828:   /* recover our data structure: */
        !           829:   suncg2 = _suncg2;
        !           830: 
        !           831:   /* lock the mutex: */
        !           832:   tme_mutex_lock(&suncg2->tme_suncg2_mutex);
        !           833: 
        !           834:   /* the callout thread is no longer running: */
        !           835:   suncg2->tme_suncg2_flags &= ~TME_SUNCG2_FLAG_CALLOUT_THREAD_RUNNING;
        !           836: 
        !           837:   /* make any callouts: */
        !           838:   _tme_suncg2_callout(suncg2, 0);
        !           839: 
        !           840:   /* unlock the mutex: */
        !           841:   tme_mutex_unlock(&suncg2->tme_suncg2_mutex);
        !           842: }
        !           843: 
        !           844: /* this is called before the framebuffer's display is updated: */
        !           845: static int
        !           846: _tme_suncg2_update(struct tme_fb_connection *conn_fb)
        !           847: {
        !           848:   struct tme_suncg2 *suncg2;
        !           849: 
        !           850:   /* recover our data structure: */
        !           851:   suncg2 = conn_fb->tme_fb_connection.tme_connection_element->tme_element_private;
        !           852: 
        !           853:   /* lock the mutex: */
        !           854:   tme_mutex_lock(&suncg2->tme_suncg2_mutex);
        !           855: 
        !           856:   /* validate the displayed memory: */
        !           857:   _tme_suncg2_validate_displayed(suncg2, NULL);
        !           858: 
        !           859:   /* if we still need callouts, and the callout thread isn't running,
        !           860:      start it: */
        !           861:   if ((suncg2->tme_suncg2_callout_flags & TME_SUNCG2_CALLOUTS_MASK) != 0
        !           862:       && !(suncg2->tme_suncg2_flags & TME_SUNCG2_FLAG_CALLOUT_THREAD_RUNNING)) {
        !           863:     tme_thread_create(_tme_suncg2_callout_thread, suncg2);
        !           864:     suncg2->tme_suncg2_flags |= TME_SUNCG2_FLAG_CALLOUT_THREAD_RUNNING;
        !           865:   }
        !           866:       
        !           867:   /* unlock the mutex: */
        !           868:   tme_mutex_unlock(&suncg2->tme_suncg2_mutex);
        !           869: 
        !           870:   return (TME_OK);
        !           871: }
        !           872: 
        !           873: /* the suncg2 displayed memory bus cycle handler: */
        !           874: static int
        !           875: _tme_suncg2_bus_cycle_displayed(void *_suncg2, struct tme_bus_cycle *cycle_init)
        !           876: {
        !           877:   struct tme_suncg2 *suncg2;
        !           878:   unsigned int plane_i;
        !           879:   tme_bus_addr_t address_first;
        !           880:   tme_bus_addr_t address_last;
        !           881: 
        !           882:   /* recover our data structure: */
        !           883:   suncg2 = (struct tme_suncg2 *) _suncg2;
        !           884: 
        !           885:   /* lock the mutex: */
        !           886:   tme_mutex_lock(&suncg2->tme_suncg2_mutex);
        !           887: 
        !           888:   /* if we're displaying the pixmap: */
        !           889:   plane_i = suncg2->tme_suncg2_bitmap_mode_plane;
        !           890:   if (plane_i == TME_SUNCG2_PLANE_MAX) {
        !           891: 
        !           892:     /* the displayed memory is the pixmap memory: */
        !           893:     address_first = TME_SUNCG2_REG_PIXMAP;
        !           894:     address_last = TME_SUNCG2_REG_PIXMAP + suncg2->tme_suncg2_pixel_count - 1;
        !           895:   }
        !           896: 
        !           897:   /* otherwise, we're in bitmap mode: */
        !           898:   else {
        !           899: 
        !           900:     /* the displayed memory is the displayed bitmap memory: */
        !           901:     address_first = TME_SUNCG2_REG_BITMAP(plane_i);
        !           902:     address_last = address_first + (suncg2->tme_suncg2_pixel_count / 8) - 1;
        !           903:   }
        !           904: 
        !           905:   /* run the cycle: */
        !           906:   tme_bus_cycle_xfer_memory(cycle_init, 
        !           907:                            (suncg2->tme_suncg2_displayed_memory
        !           908:                             - address_first),
        !           909:                            address_last);
        !           910: 
        !           911:   /* unlock the mutex: */
        !           912:   tme_mutex_unlock(&suncg2->tme_suncg2_mutex);
        !           913: 
        !           914:   /* no faults: */
        !           915:   return (TME_OK);
        !           916: }
        !           917: 
        !           918: /* the suncg2 raw memory bus cycle handler: */
        !           919: static int
        !           920: _tme_suncg2_bus_cycle_raw(void *_suncg2, struct tme_bus_cycle *cycle_init)
        !           921: {
        !           922:   struct tme_suncg2 *suncg2;
        !           923: 
        !           924:   /* recover our data structure: */
        !           925:   suncg2 = (struct tme_suncg2 *) _suncg2;
        !           926: 
        !           927:   /* lock the mutex: */
        !           928:   tme_mutex_lock(&suncg2->tme_suncg2_mutex);
        !           929: 
        !           930:   /* run the cycle: */
        !           931:   tme_bus_cycle_xfer_memory(cycle_init, 
        !           932:                            (suncg2->tme_suncg2_raw_memory
        !           933:                             - TME_SUNCG2_REG_BITMAP(0)),
        !           934:                            (TME_SUNCG2_REG_PIXMAP
        !           935:                             + TME_SUNCG2_SIZ_PIXMAP
        !           936:                             - 1));
        !           937: 
        !           938:   /* unlock the mutex: */
        !           939:   tme_mutex_unlock(&suncg2->tme_suncg2_mutex);
        !           940: 
        !           941:   /* no faults: */
        !           942:   return (TME_OK);
        !           943: }
        !           944: 
        !           945: /* this catches unsupported rasterop configurations: */
        !           946: static void
        !           947: _tme_suncg2_rop_unsupported(struct tme_suncg2 *suncg2)
        !           948: {
        !           949:   /* nothing */
        !           950: }
        !           951: 
        !           952: /* this does a raster op: */
        !           953: static tme_uint16_t 
        !           954: _tme_suncg2_rop_op(struct tme_suncg2 *suncg2,
        !           955:                   unsigned int ropc_unit,
        !           956:                   tme_uint16_t src,
        !           957:                   tme_uint16_t dst)
        !           958: {
        !           959:   switch ((tme_uint8_t) suncg2->tme_suncg2_ropc[ropc_unit].tme_suncg2_ropc_op) {
        !           960:   default:
        !           961:     _tme_suncg2_rop_unsupported(suncg2); 
        !           962:     /* FALLTHROUGH */
        !           963:   case (TME_SUNCG2_ROP_SRC): return (src);
        !           964:   case (TME_SUNCG2_ROP_NOT(TME_SUNCG2_ROP_DST)): return (~dst);
        !           965:   }
        !           966: }
        !           967: 
        !           968: /* the bus cycle handler for the rasterop data: */
        !           969: static int
        !           970: _tme_suncg2_bus_cycle_rop_data(void *_suncg2, struct tme_bus_cycle *cycle_init)
        !           971: {
        !           972:   struct tme_suncg2 *suncg2;
        !           973:   tme_uint32_t address;
        !           974:   tme_uint32_t address_aligned;
        !           975:   tme_uint16_t data;
        !           976:   tme_uint8_t src;
        !           977:   tme_uint8_t dst;
        !           978:   tme_uint8_t pixel;
        !           979:   int supported;
        !           980: 
        !           981:   /* recover our data structure: */
        !           982:   suncg2 = (struct tme_suncg2 *) _suncg2;
        !           983: 
        !           984:   /* decode the address: */
        !           985:   address
        !           986:     = (cycle_init->tme_bus_cycle_address
        !           987:        - TME_SUNCG2_REG_ROP_DATA);
        !           988:   address_aligned
        !           989:     = (address & (((tme_uint32_t) 0) - sizeof(tme_uint16_t)));
        !           990: 
        !           991:   /* assume that this access is unsupported: */
        !           992:   supported = FALSE;
        !           993: 
        !           994:   /* lock the mutex: */
        !           995:   tme_mutex_lock(&suncg2->tme_suncg2_mutex);
        !           996: 
        !           997:   /* if this is a read: */
        !           998:   if (cycle_init->tme_bus_cycle_type == TME_BUS_CYCLE_READ) {
        !           999: 
        !          1000:     /* dispatch on the rop mode: */
        !          1001:     switch (suncg2->tme_suncg2_csr & TME_SUNCG2_CSR_ROP_MODE_MASK) {
        !          1002: 
        !          1003:     default:
        !          1004:       _tme_suncg2_rop_unsupported(suncg2);
        !          1005:       data = 0;
        !          1006:       break;
        !          1007: 
        !          1008:       /* the single pixel, LD_SRC write, LD_DST write, mode: */
        !          1009:     case TME_SUNCG2_CSR_ROP_MODE_SWWPIX:
        !          1010:       
        !          1011:       /* this mode has partial support: */
        !          1012:       supported = TRUE;
        !          1013: 
        !          1014:       /* XXX FIXME does a load reset the state? */
        !          1015:       
        !          1016:       /* just load two pixels from the pixmap: */
        !          1017:       _tme_suncg2_validate_pixmap(suncg2, NULL);
        !          1018:       data = (suncg2->tme_suncg2_raw_memory[TME_SUNCG2_REG_PIXMAP + address_aligned]
        !          1019:              & ((tme_uint8_t) suncg2->tme_suncg2_plane_mask));
        !          1020:       data = ((data << 8)
        !          1021:              | (suncg2->tme_suncg2_raw_memory[TME_SUNCG2_REG_PIXMAP + address_aligned + 1]
        !          1022:                 & ((tme_uint8_t) suncg2->tme_suncg2_plane_mask)));
        !          1023:       break;
        !          1024:     }
        !          1025:   }
        !          1026: 
        !          1027:   /* do the bus cycle: */
        !          1028:   tme_bus_cycle_xfer_reg(cycle_init,
        !          1029:                         &data,
        !          1030:                         TME_BUS16_LOG2);
        !          1031: 
        !          1032:   /* get the data: */
        !          1033:   data = (((cycle_init->tme_bus_cycle_size == sizeof(tme_uint16_t)
        !          1034:            || (address % sizeof(tme_uint16_t)) == 1)
        !          1035:           ? data
        !          1036:           : (data >> 8))
        !          1037:          & (0xffff >> (sizeof(tme_uint16_t) - cycle_init->tme_bus_cycle_size)));
        !          1038: 
        !          1039:   /* log the cycle: */
        !          1040:   tme_log(&suncg2->tme_suncg2_element->tme_element_log_handle,
        !          1041:          100, TME_OK,
        !          1042:          (&suncg2->tme_suncg2_element->tme_element_log_handle,
        !          1043:           ((cycle_init->tme_bus_cycle_size == sizeof(tme_uint16_t))
        !          1044:            ? "rop data offset 0x%05x size 16bits %s 0x%04x"
        !          1045:            : "rop data offset 0x%05x size  8bits %s 0x%02x"),
        !          1046:           address,
        !          1047:           ((cycle_init->tme_bus_cycle_type == TME_BUS_CYCLE_WRITE)
        !          1048:            ? "<-"
        !          1049:            : "->"),
        !          1050:           data));
        !          1051: 
        !          1052:   /* if this is a write: */
        !          1053:   if (cycle_init->tme_bus_cycle_type == TME_BUS_CYCLE_WRITE) {
        !          1054: 
        !          1055:     /* dispatch on the rop mode: */
        !          1056:     switch (suncg2->tme_suncg2_csr & TME_SUNCG2_CSR_ROP_MODE_MASK) {
        !          1057: 
        !          1058:     default:
        !          1059:       _tme_suncg2_rop_unsupported(suncg2);
        !          1060:       break;
        !          1061: 
        !          1062:       /* the single pixel, LD_SRC write, LD_DST write, mode: */
        !          1063:     case TME_SUNCG2_CSR_ROP_MODE_SWWPIX:
        !          1064:       
        !          1065:       /* this mode has partial support: */
        !          1066:       supported = TRUE;
        !          1067: 
        !          1068:       /* validate the pixmap: */
        !          1069:       _tme_suncg2_validate_pixmap(suncg2, NULL);
        !          1070: 
        !          1071:       /* the current pixel value is DST: */
        !          1072:       dst = suncg2->tme_suncg2_raw_memory[TME_SUNCG2_REG_PIXMAP + address];
        !          1073:       
        !          1074:       /* the current source buffer is SRC: */
        !          1075:       src = suncg2->tme_suncg2_rop_src_buffer;
        !          1076: 
        !          1077:       /* make the new pixel value: */
        !          1078:       pixel = _tme_suncg2_rop_op(suncg2,
        !          1079:                                 8,
        !          1080:                                 src,
        !          1081:                                 dst);
        !          1082: 
        !          1083:       /* store the pixel: */
        !          1084:       suncg2->tme_suncg2_raw_memory[TME_SUNCG2_REG_PIXMAP + address]
        !          1085:        = ((dst & ((tme_uint8_t) (~suncg2->tme_suncg2_plane_mask)))
        !          1086:           | (pixel & ((tme_uint8_t) suncg2->tme_suncg2_plane_mask)));
        !          1087: 
        !          1088:       /* the displayed memory is now invalid: */
        !          1089:       suncg2->tme_suncg2_flags |= TME_SUNCG2_FLAG_INVALID_DISPLAYED;
        !          1090: 
        !          1091:       /* load the source buffer: */
        !          1092:       suncg2->tme_suncg2_rop_src_buffer = data;
        !          1093:       break;
        !          1094:     }
        !          1095:   }
        !          1096: 
        !          1097:   /* if this cycle was unsupported, abort: */
        !          1098:   if (__tme_predict_false(!supported)) {
        !          1099:     _tme_suncg2_rop_unsupported(suncg2);
        !          1100:   }
        !          1101:   
        !          1102:   /* unlock the mutex: */
        !          1103:   tme_mutex_unlock(&suncg2->tme_suncg2_mutex);
        !          1104: 
        !          1105:   /* no faults: */
        !          1106:   return (TME_OK);
        !          1107: }
        !          1108: 
        !          1109: /* the bus cycle handler for the registers: */
        !          1110: static int
        !          1111: _tme_suncg2_bus_cycle_regs(void *_suncg2, struct tme_bus_cycle *cycle_init)
        !          1112: {
        !          1113:   struct tme_suncg2 *suncg2;
        !          1114:   tme_bus_addr_t address;
        !          1115:   tme_uint16_t *reg;
        !          1116:   tme_uint16_t reg_old, reg_new;
        !          1117:   tme_uint16_t junk;
        !          1118:   unsigned int ropc_unit;
        !          1119:   unsigned int ropc_unit_prime;
        !          1120:   unsigned int ropc_reg;
        !          1121:   int new_callouts;
        !          1122: 
        !          1123:   /* assume we won't need any new callouts: */
        !          1124:   new_callouts = 0;
        !          1125: 
        !          1126:   /* recover our data structure: */
        !          1127:   suncg2 = (struct tme_suncg2 *) _suncg2;
        !          1128: 
        !          1129:   /* coarsely decode the address: */
        !          1130:   address
        !          1131:     = (cycle_init->tme_bus_cycle_address
        !          1132:        & (((tme_bus_addr_t) 0)
        !          1133:          - TME_SUNCG2_SIZ_REG_PAGE));
        !          1134: 
        !          1135:   /* lock the mutex: */
        !          1136:   tme_mutex_lock(&suncg2->tme_suncg2_mutex);
        !          1137: 
        !          1138:   /* the rasterop registers go from [TME_SUNCG2_REG_ROPC_UNIT(0)..TME_SUNCG2_REG_CSR): */
        !          1139:   assert (address >= TME_SUNCG2_REG_ROPC_UNIT(0));
        !          1140:   if (address < TME_SUNCG2_REG_CSR) {
        !          1141: 
        !          1142:     /* get the rasterop unit number: */
        !          1143:     ropc_unit = (address - TME_SUNCG2_REG_ROPC_UNIT(0)) / TME_SUNCG2_SIZ_REG_PAGE;
        !          1144: 
        !          1145:     /* see if this is the prime registers: */
        !          1146:     ropc_unit_prime
        !          1147:       = ((cycle_init->tme_bus_cycle_address & (TME_SUNCG2_SIZ_REG_PAGE / 2))
        !          1148:         ? TME_SUNCG2_ROPC_PRIME
        !          1149:         : 0);
        !          1150: 
        !          1151:     /* get the register number: */
        !          1152:     ropc_reg
        !          1153:       = ((cycle_init->tme_bus_cycle_address
        !          1154:          % sizeof(suncg2->tme_suncg2_ropc[ropc_unit_prime + ropc_unit]))
        !          1155:         / sizeof(tme_uint16_t));
        !          1156: 
        !          1157:     /* get a pointer to the single register: */
        !          1158:     reg = (((tme_uint16_t *) &suncg2->tme_suncg2_ropc[ropc_unit_prime + ropc_unit]) + ropc_reg);
        !          1159: 
        !          1160:     /* do the bus cycle: */
        !          1161:     tme_bus_cycle_xfer_reg(cycle_init,
        !          1162:                           reg,
        !          1163:                           TME_BUS16_LOG2);
        !          1164: 
        !          1165: #ifndef TME_NO_LOG
        !          1166:     /* log the transfer: */
        !          1167:     tme_log(&suncg2->tme_suncg2_element->tme_element_log_handle,
        !          1168:            100, TME_OK,
        !          1169:            (&suncg2->tme_suncg2_element->tme_element_log_handle,
        !          1170:             "ropc unit %u%s reg %s %s 0x%04x",
        !          1171:             ropc_unit,
        !          1172:             (ropc_unit_prime
        !          1173:              ? " PRIME"
        !          1174:              : ""),
        !          1175:             _tme_suncg2_ropc_regs[ropc_reg],
        !          1176:             ((cycle_init->tme_bus_cycle_type == TME_BUS_CYCLE_WRITE)
        !          1177:              ? "<-"
        !          1178:              : "->"),
        !          1179:             *reg));
        !          1180: #endif /* !TME_NO_LOG */
        !          1181:   }
        !          1182: 
        !          1183:   /* the CSR is the entire page at TME_SUNCG2_REG_CSR: */
        !          1184:   else if (address == TME_SUNCG2_REG_CSR) {
        !          1185: 
        !          1186:     /* if this is a read: */
        !          1187:     if ((cycle_init->tme_bus_cycle_type & TME_BUS_CYCLE_READ) != 0) {
        !          1188: 
        !          1189:       /* if it's time to set the retrace bit, set it: */
        !          1190:       if (suncg2->tme_suncg2_cycle_retrace-- == 0) {
        !          1191:        suncg2->tme_suncg2_csr |= TME_SUNCG2_CSR_RETRACE;
        !          1192:        suncg2->tme_suncg2_cycle_retrace = TME_SUNCG2_CYCLE_RETRACE;
        !          1193:       }
        !          1194: 
        !          1195:       /* otherwise, clear it: */
        !          1196:       else {
        !          1197:        suncg2->tme_suncg2_csr &= ~TME_SUNCG2_CSR_RETRACE;
        !          1198:       }
        !          1199:     }
        !          1200: 
        !          1201:     /* do the bus cycle: */
        !          1202:     reg_old = suncg2->tme_suncg2_csr;
        !          1203:     tme_bus_cycle_xfer_reg(cycle_init, 
        !          1204:                           &suncg2->tme_suncg2_csr,
        !          1205:                           TME_BUS16_LOG2);
        !          1206:     reg_new = suncg2->tme_suncg2_csr;
        !          1207: 
        !          1208:     /* put back the unchanging bits: */
        !          1209:     reg_new
        !          1210:       = ((reg_new
        !          1211:          & ~(TME_SUNCG2_CSR_INT_ACTIVE
        !          1212:              | TME_SUNCG2_CSR_RETRACE
        !          1213:              | 0xff00))
        !          1214:         | (reg_old
        !          1215:            & (TME_SUNCG2_CSR_INT_ACTIVE
        !          1216:               | TME_SUNCG2_CSR_RETRACE
        !          1217:               | 0xff00)));
        !          1218:     suncg2->tme_suncg2_csr = reg_new;
        !          1219: 
        !          1220:     /* log the transfer: */
        !          1221:     tme_log(&suncg2->tme_suncg2_element->tme_element_log_handle,
        !          1222:            100, TME_OK,
        !          1223:            (&suncg2->tme_suncg2_element->tme_element_log_handle,
        !          1224:             "csr %s 0x%04x",
        !          1225:             ((cycle_init->tme_bus_cycle_type == TME_BUS_CYCLE_WRITE)
        !          1226:              ? "<-"
        !          1227:              : "->"),
        !          1228:             reg_new));
        !          1229: 
        !          1230:     /* we do not support these bits: */
        !          1231:     if ((reg_new
        !          1232:         ^ reg_old)
        !          1233:        & TME_SUNCG2_CSR_INT_ENABLE) {
        !          1234:       abort();
        !          1235:     }
        !          1236: 
        !          1237:     /* if the cmap update bit is transitioning from a zero to a one,
        !          1238:        we need a mode change: */
        !          1239:     if ((reg_old & TME_SUNCG2_CSR_CMAP_UPDATE) == 0
        !          1240:        && (reg_new & TME_SUNCG2_CSR_CMAP_UPDATE) != 0) {
        !          1241:       new_callouts |= TME_SUNCG2_CALLOUT_MODE_CHANGE;
        !          1242:     }
        !          1243:   }
        !          1244:   
        !          1245:   /* if this is the interrupt vector: */
        !          1246:   else if (address == TME_SUNCG2_REG_INTVEC) {
        !          1247:     tme_bus_cycle_xfer_reg(cycle_init,
        !          1248:                           &suncg2->tme_suncg2_intvec,
        !          1249:                           TME_BUS16_LOG2);
        !          1250:   }
        !          1251:   
        !          1252:   /* if this is the plane mask: */
        !          1253:   else if (address == TME_SUNCG2_REG_PLANE_MASK) {
        !          1254: 
        !          1255:     /* do the bus cycle: */
        !          1256:     tme_bus_cycle_xfer_reg(cycle_init,
        !          1257:                           &suncg2->tme_suncg2_plane_mask,
        !          1258:                           TME_BUS16_LOG2);
        !          1259: 
        !          1260:     /* log the transfer: */
        !          1261:     tme_log(&suncg2->tme_suncg2_element->tme_element_log_handle,
        !          1262:            100, TME_OK,
        !          1263:            (&suncg2->tme_suncg2_element->tme_element_log_handle,
        !          1264:             "plane mask %s 0x%04x",
        !          1265:             ((cycle_init->tme_bus_cycle_type == TME_BUS_CYCLE_WRITE)
        !          1266:              ? "<-"
        !          1267:              : "->"),
        !          1268:             suncg2->tme_suncg2_plane_mask));
        !          1269:   }
        !          1270: 
        !          1271:   /* XXX FIXME - the sun3 PROM zeroes the cg3 DMA base register,
        !          1272:      the cg3 double buffer register, the cg3 DMA width register,
        !          1273:      and the cg3 frame count registers: */
        !          1274:   else if (address == TME_SUNCG2_REG_SUN3_DMA_BASE
        !          1275:           || address == TME_SUNCG2_REG_SUN3_DOUBLE_BUF
        !          1276:           || address == TME_SUNCG2_REG_SUN3_DMA_WIDTH
        !          1277:           || address == TME_SUNCG2_REG_SUN3_FRAME_COUNT) {
        !          1278:     tme_bus_cycle_xfer_reg(cycle_init,
        !          1279:                           &junk,
        !          1280:                           TME_BUS16_LOG2);
        !          1281:   }
        !          1282: 
        !          1283:   /* XXX FIXME - this is a partial implementation: */
        !          1284:   else {
        !          1285:     abort();
        !          1286:   }
        !          1287: 
        !          1288:   /* make any new callouts: */
        !          1289:   _tme_suncg2_callout(suncg2, new_callouts);
        !          1290: 
        !          1291:   /* unlock the mutex: */
        !          1292:   tme_mutex_unlock(&suncg2->tme_suncg2_mutex);
        !          1293: 
        !          1294:   /* no faults: */
        !          1295:   return (TME_OK);
        !          1296: }
        !          1297: 
        !          1298: /* the bus cycle handler for the suncg2 colormap registers: */
        !          1299: static int
        !          1300: _tme_suncg2_bus_cycle_cmap(void *_suncg2, struct tme_bus_cycle *cycle_init)
        !          1301: {
        !          1302:   struct tme_suncg2 *suncg2;
        !          1303: 
        !          1304:   /* recover our data structure: */
        !          1305:   suncg2 = (struct tme_suncg2 *) _suncg2;
        !          1306: 
        !          1307:   /* lock the mutex: */
        !          1308:   tme_mutex_lock(&suncg2->tme_suncg2_mutex);
        !          1309: 
        !          1310:   /* run the cycle: */
        !          1311:   tme_bus_cycle_xfer_memory(cycle_init, 
        !          1312:                            (((tme_uint8_t *) suncg2->tme_suncg2_cmap_raw)
        !          1313:                             - TME_SUNCG2_REG_CMAP_R),
        !          1314:                            TME_SUNCG2_SIZ_REGS - 1);
        !          1315: 
        !          1316:   /* if this is a write and colormap updates are enabled, we need to
        !          1317:      call out a mode change.  we don't make the callout now, assuming
        !          1318:      that more writes to the colormap are coming soon.  we will
        !          1319:      eventually make the callout when the framebuffer updates: */
        !          1320:   if ((cycle_init->tme_bus_cycle_type & TME_BUS_CYCLE_WRITE)
        !          1321:       && (suncg2->tme_suncg2_csr
        !          1322:          & TME_SUNCG2_CSR_CMAP_UPDATE)) {
        !          1323:     suncg2->tme_suncg2_callout_flags |= TME_SUNCG2_CALLOUT_MODE_CHANGE;
        !          1324:   }
        !          1325: 
        !          1326:   /* unlock the mutex: */
        !          1327:   tme_mutex_unlock(&suncg2->tme_suncg2_mutex);
        !          1328: 
        !          1329:   /* no faults: */
        !          1330:   return (TME_OK);
        !          1331: }
        !          1332: 
        !          1333: /* the suncg2 TLB filler: */
        !          1334: static int
        !          1335: _tme_suncg2_tlb_fill(void *_suncg2, struct tme_bus_tlb *tlb, 
        !          1336:                     tme_bus_addr_t address, unsigned int cycles)
        !          1337: {
        !          1338:   struct tme_suncg2 *suncg2;
        !          1339:   tme_uint8_t *memory;
        !          1340:   tme_bus_addr_t address_first;
        !          1341:   tme_bus_addr_t address_last;
        !          1342: 
        !          1343:   /* recover our data structure: */
        !          1344:   suncg2 = (struct tme_suncg2 *) _suncg2;
        !          1345: 
        !          1346:   /* initialize the TLB entry: */
        !          1347:   tme_bus_tlb_initialize(tlb);
        !          1348: 
        !          1349:   /* the fast reading and writing rwlock: */
        !          1350:   tlb->tme_bus_tlb_rwlock = &suncg2->tme_suncg2_rwlock;
        !          1351: 
        !          1352:   /* allow reading and writing: */
        !          1353:   tlb->tme_bus_tlb_cycles_ok = TME_BUS_CYCLE_READ | TME_BUS_CYCLE_WRITE;
        !          1354: 
        !          1355:   /* our bus cycle handler private data: */
        !          1356:   tlb->tme_bus_tlb_cycle_private = _suncg2;
        !          1357: 
        !          1358:   /* lock the mutex: */
        !          1359:   tme_mutex_lock(&suncg2->tme_suncg2_mutex);
        !          1360: 
        !          1361:   /* we require a connection: */
        !          1362:   assert (suncg2->tme_suncg2_fb_connection != NULL);
        !          1363:   assert (suncg2->tme_suncg2_displayed_memory != NULL);
        !          1364: 
        !          1365:   /* if this address falls in a bitmap: */
        !          1366:   if ((TME_SUNCG2_REG_BITMAP(0)
        !          1367:        <= address)
        !          1368:       && (address
        !          1369:          < TME_SUNCG2_REG_BITMAP(TME_SUNCG2_PLANE_MAX))) {
        !          1370: 
        !          1371:     /* the cycle handler: */
        !          1372:     tlb->tme_bus_tlb_cycle = _tme_suncg2_bus_cycle_raw;
        !          1373: 
        !          1374:     /* if we're displaying the pixmap: */
        !          1375:     if (suncg2->tme_suncg2_bitmap_mode_plane == TME_SUNCG2_PLANE_MAX) {
        !          1376: 
        !          1377:       /* validate the bitmaps: */
        !          1378:       _tme_suncg2_validate_bitmaps(suncg2, tlb);
        !          1379: 
        !          1380:       /* this TLB entry covers all of the bitmap memory: */
        !          1381:       address_first = TME_SUNCG2_REG_BITMAP(0);
        !          1382:       address_last = TME_SUNCG2_REG_PIXMAP - 1;
        !          1383:       memory = suncg2->tme_suncg2_raw_memory + address_first;
        !          1384: 
        !          1385:       /* the displayed memory is now invalid: */
        !          1386:       suncg2->tme_suncg2_flags |= TME_SUNCG2_FLAG_INVALID_DISPLAYED;
        !          1387:     }
        !          1388: 
        !          1389:     /* otherwise, we're displaying a bitmap: */
        !          1390:     else {
        !          1391: 
        !          1392:       /* calculate the first and last addresses of the displayed
        !          1393:         memory: */
        !          1394:       address_first = TME_SUNCG2_REG_BITMAP(suncg2->tme_suncg2_bitmap_mode_plane);
        !          1395:       address_last = address_first + (suncg2->tme_suncg2_pixel_count / 8) - 1;
        !          1396: 
        !          1397:       /* if this address is before the displayed memory, this TLB
        !          1398:         entry covers from the beginning of the bitmap memory up to
        !          1399:         the displayed memory: */
        !          1400:       if (address < address_first) {
        !          1401:        address_last = address_first - 1;
        !          1402:        address_first = TME_SUNCG2_REG_BITMAP(0);
        !          1403:        memory = suncg2->tme_suncg2_raw_memory + address_first;
        !          1404: 
        !          1405:        /* validate the bitmaps: */
        !          1406:        _tme_suncg2_validate_bitmaps(suncg2, tlb);
        !          1407:       }
        !          1408: 
        !          1409:       /* otherwise, if this address is after the displayed memory,
        !          1410:         this TLB entry covers from right after the displayed memory
        !          1411:         to the end of the bitmap memory: */
        !          1412:       else if (address > address_last) {
        !          1413:        address_first = address_last + 1;
        !          1414:        address_last = TME_SUNCG2_REG_PIXMAP - 1;
        !          1415:        memory = suncg2->tme_suncg2_raw_memory + address_first;
        !          1416: 
        !          1417:        /* validate the bitmaps: */
        !          1418:        _tme_suncg2_validate_bitmaps(suncg2, tlb);
        !          1419:       }
        !          1420: 
        !          1421:       /* otherwise, this address is in the displayed memory: */
        !          1422:       else {
        !          1423:        memory = suncg2->tme_suncg2_displayed_memory;
        !          1424:        tlb->tme_bus_tlb_cycle = _tme_suncg2_bus_cycle_displayed;
        !          1425: 
        !          1426:        /* validate the displayed memory: */
        !          1427:        _tme_suncg2_validate_displayed(suncg2, tlb);
        !          1428:       }
        !          1429:     }
        !          1430: 
        !          1431:     /* the address range: */
        !          1432:     TME_ATOMIC_WRITE(tme_bus_addr_t,
        !          1433:                     tlb->tme_bus_tlb_addr_first, 
        !          1434:                     address_first);
        !          1435:     TME_ATOMIC_WRITE(tme_bus_addr_t,
        !          1436:                     tlb->tme_bus_tlb_addr_last,
        !          1437:                     address_last);
        !          1438: 
        !          1439:     /* this TLB entry allows fast reading and fast writing: */
        !          1440:     tlb->tme_bus_tlb_emulator_off_read = memory - address_first;
        !          1441:     tlb->tme_bus_tlb_emulator_off_write = memory - address_first;
        !          1442: 
        !          1443:     /* add this TLB entry: */
        !          1444:     _tme_suncg2_tlb_add(suncg2, tlb);
        !          1445: 
        !          1446:     /* the pixmap is now invalid: */
        !          1447:     suncg2->tme_suncg2_flags |= TME_SUNCG2_FLAG_INVALID_PIXMAP;
        !          1448:   }
        !          1449:     
        !          1450:   /* if this address falls in the pixmap: */
        !          1451:   else if ((TME_SUNCG2_REG_PIXMAP
        !          1452:            <= address)
        !          1453:           && (address
        !          1454:               < (TME_SUNCG2_REG_PIXMAP + TME_SUNCG2_SIZ_PIXMAP))) {
        !          1455: 
        !          1456:     /* the cycle handler: */
        !          1457:     tlb->tme_bus_tlb_cycle = _tme_suncg2_bus_cycle_raw;
        !          1458: 
        !          1459:     /* if we're displaying the pixmap: */
        !          1460:     if (suncg2->tme_suncg2_bitmap_mode_plane == TME_SUNCG2_PLANE_MAX) {
        !          1461: 
        !          1462:       /* calculate the first and last addresses of the displayed memory: */
        !          1463:       address_first = TME_SUNCG2_REG_PIXMAP;
        !          1464:       address_last = TME_SUNCG2_REG_PIXMAP + suncg2->tme_suncg2_pixel_count - 1;
        !          1465: 
        !          1466:       /* if this address is after the displayed memory, we're in the pad: */
        !          1467:       if (address > address_last) {
        !          1468:        address_first = address_last + 1;
        !          1469:        address_last = TME_SUNCG2_REG_PIXMAP + TME_SUNCG2_SIZ_PIXMAP - 1;
        !          1470:        memory = suncg2->tme_suncg2_raw_memory + address_first;
        !          1471: 
        !          1472:        /* validate the pixmap: */
        !          1473:        _tme_suncg2_validate_pixmap(suncg2, tlb);
        !          1474:       }
        !          1475: 
        !          1476:       /* otherwise, this address is in the displayed memory: */
        !          1477:       else {
        !          1478:        memory = suncg2->tme_suncg2_displayed_memory;
        !          1479:        tlb->tme_bus_tlb_cycle = _tme_suncg2_bus_cycle_displayed;
        !          1480: 
        !          1481:        /* validate the displayed memory: */
        !          1482:        _tme_suncg2_validate_displayed(suncg2, tlb);
        !          1483:       }
        !          1484:     }
        !          1485: 
        !          1486:     /* otherwise, we're displaying a bitmap: */
        !          1487:     else {
        !          1488: 
        !          1489:       /* validate the pixmap: */
        !          1490:       _tme_suncg2_validate_pixmap(suncg2, tlb);
        !          1491: 
        !          1492:       /* this TLB covers all of pixmap memory: */
        !          1493:       address_first = TME_SUNCG2_REG_PIXMAP;
        !          1494:       address_last = TME_SUNCG2_REG_PIXMAP + TME_SUNCG2_SIZ_PIXMAP - 1;
        !          1495:       memory = suncg2->tme_suncg2_raw_memory + address_first;
        !          1496: 
        !          1497:       /* the displayed memory is now invalid: */
        !          1498:       suncg2->tme_suncg2_flags |= TME_SUNCG2_FLAG_INVALID_DISPLAYED;
        !          1499:     }
        !          1500: 
        !          1501:     /* the address range: */
        !          1502:     TME_ATOMIC_WRITE(tme_bus_addr_t,
        !          1503:                     tlb->tme_bus_tlb_addr_first, 
        !          1504:                     address_first);
        !          1505:     TME_ATOMIC_WRITE(tme_bus_addr_t,
        !          1506:                     tlb->tme_bus_tlb_addr_last,
        !          1507:                     address_last);
        !          1508: 
        !          1509:     /* this TLB entry allows fast reading and fast writing: */
        !          1510:     tlb->tme_bus_tlb_emulator_off_read = memory - address_first;
        !          1511:     tlb->tme_bus_tlb_emulator_off_write = memory - address_first;
        !          1512: 
        !          1513:     /* add this TLB entry: */
        !          1514:     _tme_suncg2_tlb_add(suncg2, tlb);
        !          1515: 
        !          1516:     /* the bitmaps are now invalid: */
        !          1517:     suncg2->tme_suncg2_flags |= TME_SUNCG2_FLAG_INVALID_BITMAPS;
        !          1518:   }
        !          1519: 
        !          1520:   /* if this address falls in the rasterop data: */
        !          1521:   else if ((TME_SUNCG2_REG_ROP_DATA
        !          1522:            <= address)
        !          1523:           && (address
        !          1524:               < TME_SUNCG2_REG_ROPC_UNIT(0))) {
        !          1525: 
        !          1526:     /* the cycle handler: */
        !          1527:     tlb->tme_bus_tlb_cycle = _tme_suncg2_bus_cycle_rop_data;
        !          1528:     
        !          1529:     /* this TLB entry covers this range: */
        !          1530:     TME_ATOMIC_WRITE(tme_bus_addr_t, 
        !          1531:                     tlb->tme_bus_tlb_addr_first,
        !          1532:                     TME_SUNCG2_REG_ROP_DATA);
        !          1533:     TME_ATOMIC_WRITE(tme_bus_addr_t, 
        !          1534:                     tlb->tme_bus_tlb_addr_last, 
        !          1535:                     (TME_SUNCG2_REG_ROPC_UNIT(0)
        !          1536:                      - 1));
        !          1537: 
        !          1538:     /* this TLB entry cannot allow fast reading or fast writing, since
        !          1539:        this is the rasterop data: */
        !          1540:   }
        !          1541: 
        !          1542:   /* if this address falls in the registers: */
        !          1543:   else if ((TME_SUNCG2_REG_ROPC_UNIT(0)
        !          1544:            <= address)
        !          1545:           && (address 
        !          1546:               < TME_SUNCG2_REG_CMAP_R)) {
        !          1547: 
        !          1548:     /* the cycle handler: */
        !          1549:     tlb->tme_bus_tlb_cycle = _tme_suncg2_bus_cycle_regs;
        !          1550: 
        !          1551:     /* this TLB entry covers this range: */
        !          1552:     TME_ATOMIC_WRITE(tme_bus_addr_t, 
        !          1553:                     tlb->tme_bus_tlb_addr_first,
        !          1554:                     TME_SUNCG2_REG_ROPC_UNIT(0));
        !          1555:     TME_ATOMIC_WRITE(tme_bus_addr_t, 
        !          1556:                     tlb->tme_bus_tlb_addr_last, 
        !          1557:                     (TME_SUNCG2_REG_CMAP_R
        !          1558:                      - 1));
        !          1559: 
        !          1560:     /* this TLB entry cannot allow fast reading or fast writing, since
        !          1561:        these are registers: */
        !          1562:   }
        !          1563: 
        !          1564:   /* if this address falls in the colormap registers: */
        !          1565:   else if ((TME_SUNCG2_REG_CMAP_R
        !          1566:            <= address)
        !          1567:           && (address 
        !          1568:               <= (TME_SUNCG2_SIZ_REGS
        !          1569:                   - 1))) {
        !          1570: 
        !          1571:     /* the cycle handler: */
        !          1572:     tlb->tme_bus_tlb_cycle = _tme_suncg2_bus_cycle_cmap;
        !          1573: 
        !          1574:     /* this TLB entry covers this range: */
        !          1575:     TME_ATOMIC_WRITE(tme_bus_addr_t,
        !          1576:                     tlb->tme_bus_tlb_addr_first, 
        !          1577:                     TME_SUNCG2_REG_CMAP_R);
        !          1578:     TME_ATOMIC_WRITE(tme_bus_addr_t,
        !          1579:                     tlb->tme_bus_tlb_addr_last,
        !          1580:                     TME_SUNCG2_SIZ_REGS - 1);
        !          1581: 
        !          1582:     /* this TLB entry allows fast reading: */
        !          1583:     tlb->tme_bus_tlb_emulator_off_read
        !          1584:       = (((tme_uint8_t *) suncg2->tme_suncg2_cmap_raw)
        !          1585:         - TME_SUNCG2_REG_CMAP_R);
        !          1586:   }
        !          1587: 
        !          1588:   /* XXX FIXME - this is a partial implementation: */
        !          1589:   else {
        !          1590:     abort();
        !          1591:   }
        !          1592: 
        !          1593:   /* unlock the mutex: */
        !          1594:   tme_mutex_unlock(&suncg2->tme_suncg2_mutex);
        !          1595: 
        !          1596:   return (TME_OK);
        !          1597: }
        !          1598: 
        !          1599: /* this makes a new framebuffer connection: */
        !          1600: static int
        !          1601: _tme_suncg2_connection_make(struct tme_connection *conn, unsigned int state)
        !          1602: {
        !          1603:   struct tme_suncg2 *suncg2;
        !          1604:   struct tme_fb_connection *conn_fb;
        !          1605:   struct tme_fb_connection *conn_fb_other;
        !          1606:   int rc;
        !          1607: 
        !          1608:   /* recover our data structures: */
        !          1609:   suncg2 = conn->tme_connection_element->tme_element_private;
        !          1610:   conn_fb = (struct tme_fb_connection *) conn;
        !          1611:   conn_fb_other = (struct tme_fb_connection *) conn->tme_connection_other;
        !          1612: 
        !          1613:   /* both sides must be framebuffer connections: */
        !          1614:   assert(conn->tme_connection_type == TME_CONNECTION_FRAMEBUFFER);
        !          1615:   assert(conn->tme_connection_other->tme_connection_type == TME_CONNECTION_FRAMEBUFFER);
        !          1616: 
        !          1617:   /* lock our mutex: */
        !          1618:   tme_mutex_lock(&suncg2->tme_suncg2_mutex);
        !          1619: 
        !          1620:   /* once the connection is made, we know whether or not the other
        !          1621:      side of the connection is supplying specific memory that it wants
        !          1622:      us to use, or if we should allocate memory ourselves: */
        !          1623:   if (conn_fb->tme_fb_connection_buffer == NULL) {
        !          1624:     rc = tme_fb_xlat_alloc_src(conn_fb);
        !          1625:     assert (rc == TME_OK);
        !          1626:   }
        !          1627:   suncg2->tme_suncg2_displayed_memory = conn_fb->tme_fb_connection_buffer;
        !          1628: 
        !          1629:   /* invalidate any outstanding TLBs: */
        !          1630:   _tme_suncg2_tlb_invalidate(suncg2, NULL);
        !          1631: 
        !          1632:   /* the displayed memory is now invalid: */
        !          1633:   suncg2->tme_suncg2_flags |= TME_SUNCG2_FLAG_INVALID_DISPLAYED;
        !          1634: 
        !          1635:   /* we're always set up to answer calls across the connection, so we
        !          1636:      only have to do work when the connection has gone full, namely
        !          1637:      taking the other side of the connection: */
        !          1638:   if (state == TME_CONNECTION_FULL) {
        !          1639: 
        !          1640:     /* save our connection: */
        !          1641:     suncg2->tme_suncg2_fb_connection = conn_fb_other;
        !          1642:   }
        !          1643: 
        !          1644:   /* unlock our mutex: */
        !          1645:   tme_mutex_unlock(&suncg2->tme_suncg2_mutex);
        !          1646: 
        !          1647:   return (TME_OK);
        !          1648: }
        !          1649: 
        !          1650: /* this breaks a connection: */
        !          1651: static int
        !          1652: _tme_suncg2_connection_break(struct tme_connection *conn, unsigned int state)
        !          1653: {
        !          1654:   abort();
        !          1655: }
        !          1656: 
        !          1657: /* this makes a new connection side for a suncg2: */
        !          1658: static int
        !          1659: _tme_suncg2_connections_new(struct tme_element *element,
        !          1660:                             const char * const *args,
        !          1661:                             struct tme_connection **_conns,
        !          1662:                             char **_output)
        !          1663: {
        !          1664:   struct tme_suncg2 *suncg2;
        !          1665:   struct tme_fb_connection *conn_fb;
        !          1666:   struct tme_connection *conn;
        !          1667:   int rc;
        !          1668: 
        !          1669:   /* recover our data structure: */
        !          1670:   suncg2 = (struct tme_suncg2 *) element->tme_element_private;
        !          1671: 
        !          1672:   /* make the generic bus device connection side: */
        !          1673:   rc = tme_bus_device_connections_new(element, args, _conns, _output);
        !          1674:   if (rc != TME_OK) {
        !          1675:     return (rc);
        !          1676:   }
        !          1677: 
        !          1678:   /* if we don't have a framebuffer connection, make one: */
        !          1679:   if (suncg2->tme_suncg2_fb_connection == NULL) {
        !          1680: 
        !          1681:     /* allocate the new framebuffer connection: */
        !          1682:     conn_fb = tme_new0(struct tme_fb_connection, 1);
        !          1683:     conn = &conn_fb->tme_fb_connection;
        !          1684:     
        !          1685:     /* fill in the generic connection: */
        !          1686:     conn->tme_connection_next = *_conns;
        !          1687:     conn->tme_connection_type = TME_CONNECTION_FRAMEBUFFER;
        !          1688:     conn->tme_connection_score = tme_fb_connection_score;
        !          1689:     conn->tme_connection_make = _tme_suncg2_connection_make;
        !          1690:     conn->tme_connection_break = _tme_suncg2_connection_break;
        !          1691: 
        !          1692:     /* fill in the framebuffer connection: */
        !          1693:     conn_fb->tme_fb_connection_mode_change = NULL;
        !          1694:     conn_fb->tme_fb_connection_update = _tme_suncg2_update;
        !          1695: 
        !          1696:     /* height and width: */
        !          1697:     conn_fb->tme_fb_connection_width = tme_sun_fb_p4_size_width(suncg2->tme_suncg2_size);
        !          1698:     conn_fb->tme_fb_connection_height = tme_sun_fb_p4_size_height(suncg2->tme_suncg2_size);
        !          1699: 
        !          1700:     /* we are color: */
        !          1701:     conn_fb->tme_fb_connection_class = TME_FB_XLAT_CLASS_COLOR;
        !          1702:     conn_fb->tme_fb_connection_depth = TME_SUNCG2_PLANE_MAX;
        !          1703:     conn_fb->tme_fb_connection_bits_per_pixel = TME_SUNCG2_PLANE_MAX;
        !          1704: 
        !          1705:     /* we skip no pixels at the start of the scanline: */
        !          1706:     conn_fb->tme_fb_connection_skipx = 0;
        !          1707: 
        !          1708:     /* we pad to 32-bit boundaries: */
        !          1709:     conn_fb->tme_fb_connection_scanline_pad = 32;
        !          1710: 
        !          1711:     /* we are big-endian: */
        !          1712:     conn_fb->tme_fb_connection_order = TME_ENDIAN_BIG;
        !          1713: 
        !          1714:     /* we don't allocate memory until the connection is made, in case
        !          1715:        the other side of the connection wants to provide us with a
        !          1716:        specific memory region to use (maybe we're on a system with a
        !          1717:        real cgtwo and we can write directly to its buffer): */
        !          1718:     conn_fb->tme_fb_connection_buffer = NULL;
        !          1719: 
        !          1720:     /* our pixels don't have subfields: */
        !          1721:     conn_fb->tme_fb_connection_mask_g = 0;
        !          1722:     conn_fb->tme_fb_connection_mask_r = 0;
        !          1723:     conn_fb->tme_fb_connection_mask_b = 0;
        !          1724: 
        !          1725:     /* intensities are eight bits and index mapped: */
        !          1726:     conn_fb->tme_fb_connection_map_bits = (8 * sizeof(suncg2->tme_suncg2_cmap[0]));
        !          1727:     conn_fb->tme_fb_connection_map_g = &suncg2->tme_suncg2_cmap[TME_SUNCG2_CMAP_INDEX(0, TME_SUNCG2_REG_CMAP_G)];
        !          1728:     conn_fb->tme_fb_connection_map_r = &suncg2->tme_suncg2_cmap[TME_SUNCG2_CMAP_INDEX(0, TME_SUNCG2_REG_CMAP_R)];
        !          1729:     conn_fb->tme_fb_connection_map_b = &suncg2->tme_suncg2_cmap[TME_SUNCG2_CMAP_INDEX(0, TME_SUNCG2_REG_CMAP_B)];
        !          1730: 
        !          1731:     /* return the connection side possibility: */
        !          1732:     *_conns = conn;
        !          1733:   }
        !          1734: 
        !          1735:   /* done: */
        !          1736:   return (TME_OK);
        !          1737: }
        !          1738: 
        !          1739: /* the new sun cgtwo function: */
        !          1740: int
        !          1741: tme_sun_cgtwo(struct tme_element *element, const char * const *args, char **_output)
        !          1742: {
        !          1743:   struct tme_suncg2 *suncg2;
        !          1744:   tme_uint32_t cg2_type;
        !          1745:   tme_uint32_t cg2_size;
        !          1746:   int arg_i;
        !          1747:   int usage;
        !          1748: 
        !          1749:   /* check our arguments: */
        !          1750:   usage = 0;
        !          1751:   cg2_type = TME_SUNCG2_TYPE_NULL;
        !          1752:   cg2_size = TME_SUN_P4_SIZE_1152_900;
        !          1753:   arg_i = 1;
        !          1754:   for (;;) {
        !          1755: 
        !          1756:     /* the framebuffer type: */
        !          1757:     if (TME_ARG_IS(args[arg_i + 0], "type")) {
        !          1758:       if (TME_ARG_IS(args[arg_i + 1], "sun3")) {
        !          1759:        cg2_type = TME_SUNCG2_TYPE_SUN3;
        !          1760:       }
        !          1761:       else {
        !          1762:        usage = TRUE;
        !          1763:        break;
        !          1764:       }
        !          1765:       arg_i += 2;
        !          1766:     }
        !          1767: 
        !          1768:     /* the framebuffer size: */
        !          1769:     else if (TME_ARG_IS(args[arg_i + 0], "size")) {
        !          1770:       cg2_size = tme_sun_fb_p4_size(args[arg_i + 1]);
        !          1771:       if (cg2_size != TME_SUN_P4_SIZE_1152_900
        !          1772:          && cg2_size != TME_SUN_P4_SIZE_1024_1024) {
        !          1773:        usage = TRUE;
        !          1774:        break;
        !          1775:       }
        !          1776:       arg_i += 2;
        !          1777:     }
        !          1778: 
        !          1779:     /* if we ran out of arguments: */
        !          1780:     else if (args[arg_i] == NULL) {
        !          1781:       break;
        !          1782:     }
        !          1783: 
        !          1784:     /* otherwise this is a bad argument: */
        !          1785:     else {
        !          1786:       tme_output_append_error(_output,
        !          1787:                              "%s %s, ",
        !          1788:                              args[arg_i],
        !          1789:                              _("unexpected"));
        !          1790:       usage = TRUE;
        !          1791:       break;
        !          1792:     }
        !          1793:   }
        !          1794: 
        !          1795:   /* a cgtwo type must have been given: */
        !          1796:   if (cg2_type == TME_SUNCG2_TYPE_NULL) {
        !          1797:     usage = TRUE;
        !          1798:   }
        !          1799: 
        !          1800:   if (usage) {
        !          1801:     tme_output_append_error(_output, 
        !          1802:                            "%s %s type sun3 [ size { 1152x900 | 1024x1024 } ]",
        !          1803:                            _("usage:"),
        !          1804:                            args[0]);
        !          1805:     return (EINVAL);
        !          1806:   }
        !          1807: 
        !          1808:   /* start the suncg2 structure: */
        !          1809:   suncg2 = tme_new0(struct tme_suncg2, 1);
        !          1810:   suncg2->tme_suncg2_element = element;
        !          1811:   tme_mutex_init(&suncg2->tme_suncg2_mutex);
        !          1812:   tme_rwlock_init(&suncg2->tme_suncg2_rwlock);
        !          1813: 
        !          1814:   /* set the cgtwo type: */
        !          1815:   suncg2->tme_suncg2_type = cg2_type;
        !          1816: 
        !          1817:   /* set the cgtwo size: */
        !          1818:   suncg2->tme_suncg2_size = cg2_size;
        !          1819: 
        !          1820:   /* start displaying the pixmap: */
        !          1821:   suncg2->tme_suncg2_bitmap_mode_plane = TME_SUNCG2_PLANE_MAX;
        !          1822: 
        !          1823:   /* set our initial CSR: */
        !          1824:   suncg2->tme_suncg2_csr
        !          1825:     = (TME_SUNCG2_CSR_ENABLE_VIDEO
        !          1826:        | (cg2_size == TME_SUN_P4_SIZE_1024_1024
        !          1827:          ? TME_SUNCG2_CSR_SIZE_1024_1024
        !          1828:          : TME_SUNCG2_CSR_SIZE_1152_900));
        !          1829: 
        !          1830:   /* if this is a sun3 cgtwo: */
        !          1831:   if (cg2_type == TME_SUNCG2_TYPE_SUN3) {
        !          1832:     /* nothing to do */
        !          1833:   }
        !          1834: 
        !          1835:   /* calculate the pixel count: */
        !          1836:   suncg2->tme_suncg2_pixel_count
        !          1837:     = (tme_sun_fb_p4_size_width(cg2_size)
        !          1838:        * tme_sun_fb_p4_size_height(cg2_size));
        !          1839: 
        !          1840:   /* allocate the raw memory: */
        !          1841:   suncg2->tme_suncg2_raw_memory
        !          1842:     = tme_new0(tme_uint8_t, TME_SUNCG2_REG_PIXMAP + TME_SUNCG2_SIZ_PIXMAP);
        !          1843: 
        !          1844:   /* initialize our simple bus device descriptor: */
        !          1845:   suncg2->tme_suncg2_device.tme_bus_device_element = element;
        !          1846:   suncg2->tme_suncg2_device.tme_bus_device_tlb_fill = _tme_suncg2_tlb_fill;
        !          1847:   suncg2->tme_suncg2_device.tme_bus_device_address_last = TME_SUNCG2_SIZ_REGS - 1;
        !          1848: 
        !          1849:   /* fill the element: */
        !          1850:   element->tme_element_private = suncg2;
        !          1851:   element->tme_element_connections_new = _tme_suncg2_connections_new;
        !          1852: 
        !          1853:   return (TME_OK);
        !          1854: }

unix.superglobalmegacorp.com

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