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

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

unix.superglobalmegacorp.com

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