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

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

unix.superglobalmegacorp.com

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