Annotation of tme/machine/sun/sun-cgtwo.c, revision 1.1.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.