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

1.1.1.3 ! root        1: /* $Id: sun-fb.c,v 1.6 2010/06/05 19:19:01 fredette Exp $ */
1.1       root        2: 
                      3: /* machine/sun/sun-fb.c - Sun framebuffer emulation support: */
                      4: 
                      5: /*
1.1.1.2   root        6:  * Copyright (c) 2004, 2006 Matt Fredette
1.1       root        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-fb.c,v 1.6 2010/06/05 19:19:01 fredette Exp $");
1.1       root       38: 
                     39: /* includes: */
                     40: #include "sun-fb.h"
                     41: 
1.1.1.2   root       42: /* macros: */
                     43: 
                     44: /* P4 register framebuffer sizes: */
                     45: #define TME_SUNFB_P4_SIZE_MASK         (0x0f000000)
                     46: #define  TME_SUNFB_P4_SIZE_1600_1280   (0x00000000)
                     47: #define  TME_SUNFB_P4_SIZE_1152_900    (0x01000000)
                     48: #define  TME_SUNFB_P4_SIZE_1024_1024   (0x02000000)
                     49: #define  TME_SUNFB_P4_SIZE_1280_1024   (0x03000000)
                     50: #define  TME_SUNFB_P4_SIZE_1440_1440   (0x04000000)
                     51: #define  TME_SUNFB_P4_SIZE_640_480     (0x05000000)
                     52: 
                     53: /* P4 register bits: */
                     54:                                        /* 0x00000080 is the diagnostic bit (?) */
                     55:                                        /* 0x00000040 is the readback bit (?) */
                     56: #define TME_SUNFB_P4_REG_VIDEO_ENABLE  (0x00000020)
                     57: #define TME_SUNFB_P4_REG_SYNC_RAMDAC   (0x00000010)
                     58: #define TME_SUNFB_P4_REG_IN_VTRACE     (0x00000008)
                     59: #define TME_SUNFB_P4_REG_INT_ACTIVE    (0x00000004)
                     60: #define TME_SUNFB_P4_REG_INT_RESET     (0x00000004)
                     61: #define TME_SUNFB_P4_REG_ENABLE_INT    (0x00000002)
                     62: #define TME_SUNFB_P4_REG_IN_VTRACE_1H  (0x00000001)
                     63: #define TME_SUNFB_P4_REG_RESET         (0x00000001)
                     64: 
                     65: /* P4 register read-only bits: */
                     66: #define TME_SUNFB_P4_RO_MASK           (TME_SUNFB_P4_ID_MASK \
                     67:                                         | TME_SUNFB_P4_SIZE_MASK \
                     68:                                         | TME_SUNFB_P4_REG_IN_VTRACE \
                     69:                                         | TME_SUNFB_P4_REG_INT_ACTIVE \
                     70:                                         | TME_SUNFB_P4_REG_IN_VTRACE_1H)
                     71: 
                     72: /* S4 register offsets: */
                     73: #define TME_SUNFB_S4_REG_BT458_ADDRESS (0)
                     74: #define TME_SUNFB_S4_REG_BT458_CMAP    (4)
                     75: #define TME_SUNFB_S4_REG_BT458_CONTROL (8)
                     76: #define TME_SUNFB_S4_REG_BT458_OMAP    (12)
                     77: #define TME_SUNFB_S4_SIZ_BT458         (16)
                     78: #define TME_SUNFB_S4_SIZ_REGS          (32)
                     79: #define TME_SUNFB_S4_REG(x)                            \
                     80:   (TME_SUNFB_S4_SIZ_BT458                              \
                     81:    + (&((struct tme_sunfb *) 0)->tme_sunfb_s4_regs.x   \
                     82:       - &((struct tme_sunfb *) 0)->tme_sunfb_s4_regs.tme_sunfb_s4_regs_first))
                     83: 
                     84: /* S4 control register bits: */
                     85: #define TME_SUNFB_S4_CONTROL_INT_ENABLE                (0x80)
                     86: #define TME_SUNFB_S4_CONTROL_VIDEO_ENABLE      (0x40)
                     87: 
                     88: /* S4 status register bits: */
                     89: #define TME_SUNFB_S4_STATUS_INT_PENDING                (0x80)
                     90: #define TME_SUNFB_S4_STATUS_SIZE_MASK          (0x70)
                     91: #define  TME_SUNFB_S4_STATUS_SIZE_1024_768      (0x10)
                     92: #define  TME_SUNFB_S4_STATUS_SIZE_1152_900      (0x30)
                     93: #define  TME_SUNFB_S4_STATUS_SIZE_1280_1024     (0x40)
                     94: #define  TME_SUNFB_S4_STATUS_SIZE_1600_1280     (0x50)
                     95: #define TME_SUNFB_S4_STATUS_ID_MASK            (0x0f)
                     96: #define  TME_SUNFB_S4_STATUS_ID_COLOR           (0x01)
                     97: #define  TME_SUNFB_S4_STATUS_ID_MONO            (0x02)
                     98: #define  TME_SUNFB_S4_STATUS_ID_MONO_ECL        (0x03)
                     99: 
                    100: /* these evaluate to nonzero for different kinds of framebuffers: */
                    101: #define _TME_SUNFB_IS_BWTWO(sunfb)     ((sunfb)->tme_sunfb_class == TME_FB_XLAT_CLASS_MONOCHROME)
                    102: #define _TME_SUNFB_IS_P4(sunfb)                ((sunfb)->tme_sunfb_bus_handler_regs == tme_sunfb_bus_cycle_p4)
                    103: #define _TME_SUNFB_IS_S4(sunfb)                ((sunfb)->tme_sunfb_bus_handler_regs == tme_sunfb_bus_cycle_s4)
                    104: #define _TME_SUNFB_HAS_BT458(sunfb)    ((sunfb)->tme_sunfb_depth == 8)
                    105: 
1.1.1.3 ! root      106: /* we fill writable TLB entries for framebuffer memory for this many
        !           107:    bytes at a time: */
        !           108: #define TME_SUNFB_UPDATE_SIZE          (1024)
        !           109: 
1.1.1.2   root      110: #if 0
                    111: #define TME_SUNFB_DEBUG
                    112: #endif
                    113: 
                    114: /* this returns the sunfb size value for the given resolution: */
                    115: tme_uint32_t
                    116: tme_sunfb_size(const char *size)
1.1       root      117: {
                    118:   if (TME_ARG_IS(size, "1600x1280")) {
1.1.1.2   root      119:     return (TME_SUNFB_SIZE_1600_1280);
1.1       root      120:   }
                    121:   else if (TME_ARG_IS(size, "1152x900")) {
1.1.1.2   root      122:     return (TME_SUNFB_SIZE_1152_900);
1.1       root      123:   }
                    124:   else if (TME_ARG_IS(size, "1024x1024")) {
1.1.1.2   root      125:     return (TME_SUNFB_SIZE_1024_1024);
1.1       root      126:   }
                    127:   else if (TME_ARG_IS(size, "1280x1024")) {
1.1.1.2   root      128:     return (TME_SUNFB_SIZE_1280_1024);
1.1       root      129:   }
                    130:   else if (TME_ARG_IS(size, "1440x1440")) {
1.1.1.2   root      131:     return (TME_SUNFB_SIZE_1440_1440);
1.1       root      132:   }
                    133:   else if (TME_ARG_IS(size, "640x480")) {
1.1.1.2   root      134:     return (TME_SUNFB_SIZE_640_480);
                    135:   }
                    136:   else if (TME_ARG_IS(size, "1024x768")) {
                    137:     return (TME_SUNFB_SIZE_1024_768);
1.1       root      138:   }
1.1.1.2   root      139:   return (TME_SUNFB_SIZE_NULL);
1.1       root      140: }
                    141: 
1.1.1.2   root      142: /* this returns the width for the given sunfb size: */
1.1       root      143: tme_uint32_t
1.1.1.2   root      144: tme_sunfb_size_width(tme_uint32_t sunfb_size)
1.1       root      145: {
1.1.1.2   root      146:   switch (sunfb_size) {
                    147:   default: assert(FALSE);
                    148:   case TME_SUNFB_SIZE_640_480: return (640);
                    149:   case TME_SUNFB_SIZE_1024_768: /* FALLTHROUGH */
                    150:   case TME_SUNFB_SIZE_1024_1024: return (1024);
                    151:   case TME_SUNFB_SIZE_1152_900: return (1152);
                    152:   case TME_SUNFB_SIZE_1280_1024: return (1280);
                    153:   case TME_SUNFB_SIZE_1600_1280: return (1600);
                    154:   case TME_SUNFB_SIZE_1440_1440: return (1440);
1.1       root      155:   }
                    156: }
                    157: 
1.1.1.2   root      158: /* this returns the height for the given sunfb size: */
1.1       root      159: tme_uint32_t
1.1.1.2   root      160: tme_sunfb_size_height(tme_uint32_t sunfb_size)
                    161: {
                    162:   switch (sunfb_size) {
                    163:   default: assert(FALSE);
                    164:   case TME_SUNFB_SIZE_640_480: return (480);
                    165:   case TME_SUNFB_SIZE_1024_768: return (768);
                    166:   case TME_SUNFB_SIZE_1152_900: return (900);
                    167:   case TME_SUNFB_SIZE_1024_1024: /* FALLTHROUGH */
                    168:   case TME_SUNFB_SIZE_1280_1024: return (1024);
                    169:   case TME_SUNFB_SIZE_1600_1280: return (1280);
                    170:   case TME_SUNFB_SIZE_1440_1440: return (1440);
                    171:   }
                    172: }
                    173: 
                    174: /* XXX FIXME - this should be in a tme/ic/bt458.c: */
                    175: /* this determines the closest regular colormap indices for the
                    176:    overlay map: */
                    177: int
                    178: tme_bt458_omap_best(struct tme_bt458 *bt458)
                    179: {
                    180:   unsigned int omap_i;
                    181:   unsigned int cmap_i;
                    182:   tme_int32_t score;
                    183:   unsigned int cmap_i_best;
                    184:   tme_int32_t score_best;
                    185:   tme_int32_t score_part;
                    186:   int changed;
                    187: 
                    188:   /* loop over the overlay map indices: */
                    189:   changed = FALSE;
                    190:   for (omap_i = 0;
                    191:        omap_i < TME_ARRAY_ELS(bt458->tme_bt458_omap_primaries[0]);
                    192:        omap_i++) {
                    193: 
                    194:     /* silence gcc -Wuninitialized: */
                    195:     cmap_i_best = 0;
                    196: 
                    197:     /* loop over the regular colormap indices: */
                    198:     score_best = (256 * 256 * 256);
                    199:     for (cmap_i = 0;
                    200:         cmap_i < 256;
                    201:         cmap_i++) {
                    202: 
                    203:       /* score this colormap entry, by taking the product of the
                    204:         distances between this colormap entry's primaries and this
                    205:         overlay map entry's primaries: */
                    206:       score = bt458->tme_bt458_omap_r[omap_i];
                    207:       score -= (bt458->tme_bt458_cmap_r)[cmap_i];
                    208:       score_part = bt458->tme_bt458_omap_g[omap_i];
                    209:       score_part -= (bt458->tme_bt458_cmap_g)[cmap_i];
                    210:       score *= score_part;
                    211:       score_part = bt458->tme_bt458_omap_b[omap_i];
                    212:       score_part -= (bt458->tme_bt458_cmap_b)[cmap_i];
                    213:       score *= score_part;
                    214:       if (score < 0) {
                    215:        score = -score;
                    216:       }
                    217: 
                    218:       /* update the best colormap entry: */
                    219:       if (score < score_best) {
                    220:        score_best = score;
                    221:        cmap_i_best = cmap_i;
                    222:       }
                    223:     }
                    224: 
                    225:     /* save the closest index: */
                    226:     changed |= bt458->tme_bt458_omap_cmap_indices[omap_i] - cmap_i_best;
                    227:     bt458->tme_bt458_omap_cmap_indices[omap_i] = cmap_i_best;
                    228:   }
                    229: 
                    230:   return (changed);
                    231: }
                    232: 
                    233: /* this handles a mode change callout: */
                    234: static int
                    235: _tme_sunfb_mode_change(struct tme_sunfb *sunfb)
                    236: {
                    237:   struct tme_fb_connection *conn_fb_other;
                    238:   struct tme_fb_connection *conn_fb;
                    239:   int rc;
                    240: 
                    241:   /* if this framebuffer has a Bt458: */
                    242:   if (_TME_SUNFB_HAS_BT458(sunfb)) {
                    243: 
                    244:     /* update the best regular colormap indices for the colors in the
                    245:        overlay map.  if any of them have changed, we may have do to a
                    246:        full update: */
                    247:     if (tme_bt458_omap_best(&sunfb->tme_sunfb_bt458)) {
                    248: 
                    249:       /* if this framebuffer has an update-full function, call it: */
                    250:       if (sunfb->tme_sunfb_update_full != NULL) {
                    251:        (*sunfb->tme_sunfb_update_full)(sunfb);
                    252:       }
                    253:     }
                    254:   }
                    255: 
                    256:   /* get both sides of the framebuffer connection: */
                    257:   conn_fb_other = sunfb->tme_sunfb_fb_connection;
                    258:   conn_fb = (struct tme_fb_connection *) conn_fb_other->tme_fb_connection.tme_connection_other;
                    259: 
                    260:   /* unlock the mutex: */
                    261:   tme_mutex_unlock(&sunfb->tme_sunfb_mutex);
                    262:       
                    263:   /* do the callout: */
                    264:   rc = (conn_fb_other != NULL
                    265:        ? ((*conn_fb_other->tme_fb_connection_mode_change)
                    266:           (conn_fb_other))
                    267:        : TME_OK);
                    268:       
                    269:   /* lock the mutex: */
                    270:   tme_mutex_lock(&sunfb->tme_sunfb_mutex);
                    271: 
                    272:   return (rc);
                    273: }
                    274: 
                    275: /* the sunfb callout function.  it must be called with the mutex locked: */
                    276: static void
                    277: _tme_sunfb_callout(struct tme_sunfb *sunfb)
                    278: {
                    279:   struct tme_bus_connection *conn_bus;
                    280:   int int_asserted;
                    281:   int callouts_blocked;
                    282:   int rc;
                    283: 
                    284:   /* if this function is already running in another thread, simply
                    285:      return now.  the other thread will do our work: */
                    286:   if (sunfb->tme_sunfb_callout_flags
                    287:       & TME_SUNFB_CALLOUT_RUNNING) {
                    288:     return;
                    289:   }
                    290: 
                    291:   /* callouts are now running: */
                    292:   sunfb->tme_sunfb_callout_flags
                    293:     |= TME_SUNFB_CALLOUT_RUNNING;
                    294: 
                    295:   /* initially, no callouts are blocked: */
                    296:   callouts_blocked = 0;
                    297: 
                    298:   /* loop forever: */
                    299:   for (;;) {
                    300: 
                    301:     /* any callout, successful or not, will clear this bit.  if we get
                    302:        to the bottom of the loop and this bit is still set, there are
                    303:        no more (unblocked) callouts to make, so we can stop: */
                    304:     callouts_blocked |= TME_SUNFB_CALLOUT_RUNNING;
                    305: 
                    306:     /* we always clear the interrupt callout flag, because we only
                    307:        need it to get callouts to run at all: */
                    308:     sunfb->tme_sunfb_callout_flags &= ~TME_SUNFB_CALLOUT_INT;
                    309: 
                    310:     /* if our interrupt signal has changed, and this callout isn't
                    311:        blocked: */
                    312:     int_asserted
                    313:       = (_TME_SUNFB_IS_S4(sunfb)
                    314:         ? ((sunfb->tme_sunfb_s4_regs.tme_sunfb_s4_regs_control
                    315:             & TME_SUNFB_S4_CONTROL_INT_ENABLE)
                    316:            && (sunfb->tme_sunfb_s4_regs.tme_sunfb_s4_regs_status
                    317:                & TME_SUNFB_S4_STATUS_INT_PENDING))
                    318:         : FALSE);
                    319:     if ((!int_asserted != !sunfb->tme_sunfb_int_asserted)
                    320:        && (callouts_blocked & TME_SUNFB_CALLOUT_INT) == 0) {
                    321: 
                    322:       /* get our bus connection: */
                    323:       conn_bus = tme_memory_atomic_pointer_read(struct tme_bus_connection *,
                    324:                                                sunfb->tme_sunfb_device.tme_bus_device_connection,
                    325:                                                &sunfb->tme_sunfb_device.tme_bus_device_connection_rwlock);
                    326: 
                    327:       /* unlock our mutex: */
                    328:       tme_mutex_unlock(&sunfb->tme_sunfb_mutex);
                    329:       
                    330:       /* call out the bus interrupt signal edge: */
                    331:       rc = (*conn_bus->tme_bus_signal)
                    332:        (conn_bus,
1.1.1.3 ! root      333:         sunfb->tme_sunfb_bus_signal_int
        !           334:         | TME_BUS_SIGNAL_EDGE
1.1.1.2   root      335:         | (int_asserted
                    336:            ? TME_BUS_SIGNAL_LEVEL_ASSERTED
                    337:            : TME_BUS_SIGNAL_LEVEL_NEGATED));
                    338: 
                    339:       /* lock our mutex: */
                    340:       tme_mutex_lock(&sunfb->tme_sunfb_mutex);
                    341: 
                    342:       /* unblock all callouts: */
                    343:       callouts_blocked = 0;
                    344: 
                    345:       /* if this callout failed: */
                    346:       if (rc != TME_OK) {
                    347: 
                    348:        /* reschedule this callout but block it until some other
                    349:            callout succeeds: */
                    350:        sunfb->tme_sunfb_callout_flags |= TME_SUNFB_CALLOUT_INT;
                    351:        callouts_blocked |= TME_SUNFB_CALLOUT_INT;
                    352:        continue;
                    353:       }
                    354:       
                    355:       /* note the new state of the interrupt signal: */
                    356:       sunfb->tme_sunfb_int_asserted = int_asserted;
                    357:     }
                    358: 
                    359:     /* if we need to call out a mode change, and this callout isn't
                    360:        blocked: */
                    361:     if ((sunfb->tme_sunfb_callout_flags & TME_SUNFB_CALLOUT_MODE_CHANGE)
                    362:        && (callouts_blocked & TME_SUNFB_CALLOUT_MODE_CHANGE) == 0) {
                    363: 
                    364:       /* clear this callout: */
                    365:       sunfb->tme_sunfb_callout_flags &= ~TME_SUNFB_CALLOUT_MODE_CHANGE;
                    366: 
                    367:       /* call out the mode change: */
                    368:       rc = _tme_sunfb_mode_change(sunfb);
                    369: 
                    370:       /* unblock all callouts: */
                    371:       callouts_blocked = 0;
                    372: 
                    373:       /* if the callout failed: */
                    374:       if (rc != TME_OK) {
                    375: 
                    376:        /* reschedule this callout but block it until some other
                    377:            callout succeeds: */
                    378:        sunfb->tme_sunfb_callout_flags |= TME_SUNFB_CALLOUT_MODE_CHANGE;
                    379:        callouts_blocked |= TME_SUNFB_CALLOUT_MODE_CHANGE;
                    380:        continue;
                    381:       }
                    382:     }
                    383: 
                    384:     /* if no more (unblocked) callouts can run, we can stop: */
                    385:     if (callouts_blocked & TME_SUNFB_CALLOUT_RUNNING) {
                    386:       break;
                    387:     }
                    388:   }
                    389: 
                    390:   /* clear that callouts are running: */
                    391:   sunfb->tme_sunfb_callout_flags &= ~TME_SUNFB_CALLOUT_RUNNING;
                    392: }
                    393: 
                    394: /* the callout thread: */
                    395: static void
                    396: _tme_sunfb_callout_thread(void *_sunfb)
                    397: {
                    398:   struct tme_sunfb *sunfb;
                    399: 
                    400:   /* recover our data structure: */
                    401:   sunfb = _sunfb;
                    402: 
                    403:   /* lock the mutex: */
                    404:   tme_mutex_lock(&sunfb->tme_sunfb_mutex);
                    405: 
                    406:   /* loop forever: */
                    407:   for (;;) {
                    408: 
                    409:     /* make any callouts: */
                    410:     _tme_sunfb_callout(sunfb);
                    411: 
                    412:     /* wait on the condition: */
                    413:     tme_cond_wait_yield(&sunfb->tme_sunfb_callout_cond,
                    414:                        &sunfb->tme_sunfb_mutex);
                    415:   }
                    416:   /* NOTREACHED */
                    417: }
                    418: 
                    419: /* this is called before the framebuffer's display is updated: */
                    420: int
                    421: tme_sunfb_memory_update(struct tme_fb_connection *conn_fb)
                    422: {
                    423:   struct tme_sunfb *sunfb;
                    424:   int int_asserted;
1.1.1.3 ! root      425:   struct tme_token *tlb_token;
1.1.1.2   root      426: 
                    427:   /* recover our data structure: */
                    428:   sunfb = conn_fb->tme_fb_connection.tme_connection_element->tme_element_private;
                    429: 
                    430:   /* lock the mutex: */
                    431:   tme_mutex_lock(&sunfb->tme_sunfb_mutex);
                    432: 
                    433:   /* if this framebuffer supports interrupts, one is now pending.  the
                    434:      interrupt should also be asserted if it's enabled: */
                    435:   if (_TME_SUNFB_IS_S4(sunfb)) {
                    436:     sunfb->tme_sunfb_s4_regs.tme_sunfb_s4_regs_status
                    437:       |= TME_SUNFB_S4_STATUS_INT_PENDING;
                    438:     int_asserted
                    439:       = ((sunfb->tme_sunfb_s4_regs.tme_sunfb_s4_regs_control
                    440:          & TME_SUNFB_S4_CONTROL_INT_ENABLE) != 0);
                    441:   }
                    442:   else {
                    443:     int_asserted = FALSE;
                    444:   }
                    445: 
                    446:   /* if this interrupt should be asserted and it isn't already, or if
                    447:      we have other callouts to make, notify the callout thread: */
                    448:   if ((int_asserted && !sunfb->tme_sunfb_int_asserted)
                    449:       || (sunfb->tme_sunfb_callout_flags & TME_SUNFB_CALLOUTS_MASK) != 0) {
                    450:     tme_cond_notify(&sunfb->tme_sunfb_callout_cond, FALSE);
                    451:   }
                    452:       
1.1.1.3 ! root      453:   /* set the offsets of the first and last bytes updated in the real
        !           454:      framebuffer memory: */
        !           455:   conn_fb->tme_fb_connection_offset_updated_first = sunfb->tme_sunfb_offset_updated_first;
        !           456:   conn_fb->tme_fb_connection_offset_updated_last = sunfb->tme_sunfb_offset_updated_last;
        !           457: 
        !           458:   /* reset the offsets of the first and last bytes updated in the real
        !           459:      framebuffer memory: */
        !           460:   sunfb->tme_sunfb_offset_updated_first = 0 - (tme_uint32_t) 1;
        !           461:   sunfb->tme_sunfb_offset_updated_last = 0;
        !           462:   
        !           463:   /* invalidate any outstanding writable TLB entry: */
        !           464:   tlb_token = sunfb->tme_sunfb_tlb_token;
        !           465:   if (tlb_token != NULL) {
        !           466:     tme_token_invalidate(tlb_token);
        !           467:     sunfb->tme_sunfb_tlb_token = NULL;
        !           468:   }
        !           469: 
1.1.1.2   root      470:   /* unlock the mutex: */
                    471:   tme_mutex_unlock(&sunfb->tme_sunfb_mutex);
                    472: 
                    473:   return (TME_OK);
                    474: }
                    475: 
                    476: /* the sunfb memory bus cycle handler: */
                    477: static int
                    478: _tme_sunfb_bus_cycle_memory(void *_sunfb, struct tme_bus_cycle *cycle_init)
                    479: {
                    480:   struct tme_sunfb *sunfb;
                    481: 
                    482:   /* recover our data structure: */
                    483:   sunfb = (struct tme_sunfb *) _sunfb;
                    484: 
                    485:   /* lock the mutex: */
                    486:   tme_mutex_lock(&sunfb->tme_sunfb_mutex);
                    487: 
                    488:   /* run the cycle: */
                    489:   assert (cycle_init->tme_bus_cycle_address
                    490:          >= sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_first);
                    491:   tme_bus_cycle_xfer_memory(cycle_init, 
                    492:                            (sunfb->tme_sunfb_memory
                    493:                             - sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_first),
                    494:                            sunfb->tme_sunfb_memory_address_last_displayed);
                    495:   
                    496:   /* unlock the mutex: */
                    497:   tme_mutex_unlock(&sunfb->tme_sunfb_mutex);
                    498: 
                    499:   /* no faults: */
                    500:   return (TME_OK);
                    501: }
                    502: 
                    503: /* the sunfb memory pad bus cycle handler: */
                    504: static int
                    505: _tme_sunfb_bus_cycle_memory_pad(void *_sunfb, struct tme_bus_cycle *cycle_init)
                    506: {
                    507:   struct tme_sunfb *sunfb;
                    508: 
                    509:   /* recover our data structure: */
                    510:   sunfb = (struct tme_sunfb *) _sunfb;
                    511: 
                    512:   /* lock the mutex: */
                    513:   tme_mutex_lock(&sunfb->tme_sunfb_mutex);
                    514: 
                    515:   /* run the cycle: */
                    516:   assert (cycle_init->tme_bus_cycle_address
                    517:          > sunfb->tme_sunfb_memory_address_last_displayed);
                    518:   tme_bus_cycle_xfer_memory(cycle_init, 
                    519:                            (sunfb->tme_sunfb_memory_pad
                    520:                             - (sunfb->tme_sunfb_memory_address_last_displayed
                    521:                                + 1)),
                    522:                            sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_last);
                    523: 
                    524:   /* unlock the mutex: */
                    525:   tme_mutex_unlock(&sunfb->tme_sunfb_mutex);
                    526: 
                    527:   /* no faults: */
                    528:   return (TME_OK);
                    529: }
                    530: 
                    531: /* the sunfb P4 bus cycle handler: */
                    532: int
                    533: tme_sunfb_bus_cycle_p4(void *_sunfb, struct tme_bus_cycle *cycle_init)
                    534: {
                    535:   struct tme_sunfb *sunfb;
                    536:   tme_uint32_t p4_old, p4_new;
1.1.1.3 ! root      537:   tme_bus_addr32_t undecoded;
1.1.1.2   root      538: 
                    539:   /* recover our data structure: */
                    540:   sunfb = (struct tme_sunfb *) _sunfb;
                    541: 
                    542:   /* lock the mutex: */
                    543:   tme_mutex_lock(&sunfb->tme_sunfb_mutex);
                    544: 
                    545:   /* get the old P4 value: */
                    546:   p4_old = tme_betoh_u32(sunfb->tme_sunfb_p4);
                    547: 
                    548:   /* the entire register bus subregion is all decoded (or, rather, not
                    549:      decoded) as the P4: */
                    550:   undecoded
                    551:     = (cycle_init->tme_bus_cycle_address
                    552:        & (sunfb->tme_sunfb_bus_subregion_regs.tme_bus_subregion_address_last
                    553:          - sunfb->tme_sunfb_bus_subregion_regs.tme_bus_subregion_address_first
                    554:          - sizeof(sunfb->tme_sunfb_p4)));
                    555:   cycle_init->tme_bus_cycle_address
                    556:     -= undecoded;
                    557: 
                    558:   /* run the cycle: */
                    559:   assert (cycle_init->tme_bus_cycle_address
                    560:          >= sunfb->tme_sunfb_bus_subregion_regs.tme_bus_subregion_address_first);
                    561:   tme_bus_cycle_xfer_memory(cycle_init, 
                    562:                            (((tme_uint8_t *) &sunfb->tme_sunfb_p4)
                    563:                             - sunfb->tme_sunfb_bus_subregion_regs.tme_bus_subregion_address_first),
                    564:                            (sunfb->tme_sunfb_bus_subregion_regs.tme_bus_subregion_address_first
                    565:                             + sizeof(sunfb->tme_sunfb_p4)
                    566:                             - 1));
                    567:   cycle_init->tme_bus_cycle_address
                    568:     += undecoded;
                    569: 
                    570:   /* get the new P4 value: */
                    571:   p4_new = tme_betoh_u32(sunfb->tme_sunfb_p4);
                    572: 
                    573:   /* put back the unchanging bits: */
                    574:   p4_new
                    575:     = ((p4_new
                    576:        & ~TME_SUNFB_P4_RO_MASK)
                    577:        | (p4_old
                    578:          & TME_SUNFB_P4_RO_MASK));
                    579: 
                    580:   /* we do not support these bits: */
                    581:   if (p4_new
                    582:       & (TME_SUNFB_P4_REG_SYNC_RAMDAC
                    583:         | TME_SUNFB_P4_REG_ENABLE_INT)) {
                    584:     abort();
                    585:   }
                    586: 
                    587:   /* set the new P4 value: */
                    588:   sunfb->tme_sunfb_p4 = tme_htobe_u32(p4_new);
                    589: 
                    590:   /* unlock the mutex: */
                    591:   tme_mutex_unlock(&sunfb->tme_sunfb_mutex);
                    592: 
                    593:   /* no faults: */
                    594:   return (TME_OK);
                    595: }
                    596: 
                    597: /* the Brooktree BT458 bus cycle handler: */
                    598: int
                    599: tme_sunfb_bus_cycle_bt458(void *_sunfb, struct tme_bus_cycle *cycle_init)
                    600: {
                    601:   struct tme_sunfb *sunfb;
                    602:   struct tme_bt458 *bt458;
                    603:   unsigned int reg;
                    604:   tme_uint32_t value_packed;
                    605:   tme_uint8_t value;
                    606:   unsigned int byte_count;
                    607:   unsigned int bt458_address;
                    608:   unsigned int bt458_rgb;
                    609:   unsigned int map_count;
                    610: 
                    611:   /* recover our data structure: */
                    612:   sunfb = (struct tme_sunfb *) _sunfb;
                    613: 
                    614:   /* we only emulate 8-bit and aligned 32-bit accesses: */
                    615:   reg = cycle_init->tme_bus_cycle_address % TME_SUNFB_S4_SIZ_BT458;
                    616:   if (cycle_init->tme_bus_cycle_size != sizeof(tme_uint8_t)
                    617:       && (cycle_init->tme_bus_cycle_size != sizeof(tme_uint32_t)
                    618:          || (reg % sizeof(tme_uint32_t)) != 0)) {
                    619:     abort();
                    620:   }
                    621:   reg &= (TME_SUNFB_S4_SIZ_BT458 - sizeof(tme_uint32_t));
                    622: 
                    623:   /* lock the mutex: */
                    624:   tme_mutex_lock(&sunfb->tme_sunfb_mutex);
                    625: 
                    626:   /* get the Bt458 address registers: */
                    627:   bt458 = &sunfb->tme_sunfb_bt458;
                    628:   bt458_address = bt458->tme_bt458_address;
                    629:   bt458_rgb = bt458->tme_bt458_rgb;
                    630: 
                    631:   /* set the number of colormap values per read and write: */
                    632:   map_count = ((sunfb->tme_sunfb_flags & TME_SUNFB_FLAG_BT458_CMAP_PACKED)
                    633:               ? cycle_init->tme_bus_cycle_size
                    634:               : sizeof(tme_uint8_t));
                    635: 
                    636:   /* if this is a write: */
                    637:   if (cycle_init->tme_bus_cycle_type == TME_BUS_CYCLE_WRITE) {
                    638: 
                    639:     /* run the bus cycle: */
                    640:     if (cycle_init->tme_bus_cycle_size == sizeof(tme_uint32_t)) {
                    641:       tme_bus_cycle_xfer_reg(cycle_init, 
                    642:                             &value_packed,
                    643:                             TME_BUS32_LOG2);
                    644: 
                    645:       /* for a 32-bit write to an 8-bit register, a framebuffer either
                    646:         uses byte lane D24..D31 or byte lane D0..D7: */
                    647:       value
                    648:        = (value_packed
                    649:           >> (((sunfb->tme_sunfb_flags
                    650:                 & (TME_SUNFB_FLAG_BT458_BYTE_D0_D7
                    651:                    | TME_SUNFB_FLAG_BT458_BYTE_D24_D31))
                    652:                == TME_SUNFB_FLAG_BT458_BYTE_D24_D31)
                    653:               ? 24
                    654:               : 0));
                    655:     }
                    656:     else {
                    657:       tme_bus_cycle_xfer_reg(cycle_init,
                    658:                             &value,
                    659:                             TME_BUS8_LOG2);
                    660:       value_packed = value;
                    661:       value_packed <<= 24;
                    662:     }
                    663: 
                    664:     /* if this is a write to the address register: */
                    665:     if (reg == TME_SUNFB_S4_REG_BT458_ADDRESS) {
                    666: 
                    667:       /* set the Bt458 address register: */
                    668:       bt458_address = value;
                    669:     }
                    670: 
                    671:     /* if this is a write to the colormap register: */
                    672:     else if (reg == TME_SUNFB_S4_REG_BT458_CMAP) {
                    673:       
                    674:       /* write the colormap: */
                    675:       do {
                    676: 
                    677:        /* write one colormap primary: */
                    678:        (bt458->tme_bt458_cmap_primaries[bt458_rgb])[bt458_address] = value_packed >> 24;
                    679: 
                    680:        /* advance the packed value: */
                    681:        value_packed <<= 8;
                    682: 
                    683:        /* advance the Bt458 address registers: */
                    684:        bt458_rgb++;
                    685:        if (bt458_rgb == TME_ARRAY_ELS(bt458->tme_bt458_cmap_primaries)) {
                    686:          bt458_address++;
                    687:          bt458_rgb = 0;
                    688:        }
                    689:       } while (--map_count > 0);
                    690: 
                    691:       /* calling out a mode change on every colormap register write is
                    692:         expensive and unnecessary.  instead, arrange for the update
                    693:         function to eventually cause a mode change: */
                    694:       sunfb->tme_sunfb_callout_flags |= TME_SUNFB_CALLOUT_MODE_CHANGE;
                    695:     }
                    696: 
                    697:     /* if this is a write to the control register: */
                    698:     else if (reg == TME_SUNFB_S4_REG_BT458_CONTROL) {
                    699: 
                    700:       /* dispatch on the address: */
                    701:       switch (bt458_address) {
                    702: 
                    703:        /* the read mask register: */
                    704:       case TME_BT458_REG_CONTROL_MASK_READ:
                    705:        /* all planes must be on: */
                    706:        if (value != 0xff) {
                    707:          abort();
                    708:        }
                    709:        break;
                    710: 
                    711:        /* the blink mask register: */
                    712:       case TME_BT458_REG_CONTROL_MASK_BLINK:
                    713:        /* no planes must be blinking: */
                    714:        if (value != 0x00) {
                    715:          abort();
                    716:        }
                    717:        break;
                    718: 
                    719:        /* the command register: */
                    720:       case TME_BT458_REG_CONTROL_COMMAND:
                    721: 
                    722:        /* XXX FIXME - we should validate values written to the
                    723:            command register: */
                    724:        break;
                    725: 
                    726:        /* the test register: */
                    727:       case TME_BT458_REG_CONTROL_TEST:
                    728:        break;
                    729: 
                    730:       default:
1.1.1.3 ! root      731:        break;
1.1.1.2   root      732:       }
1.1.1.3 ! root      733: 
        !           734:       /* the Bt458 datasheet says, "If an invalid address is loaded
        !           735:         into the address register, data written to the device will
        !           736:         be ignored and invalid data will be read by the MPU." */
        !           737:       if (bt458_address >= TME_BT458_REG_CONTROL_FIRST
        !           738:          && bt458_address <= TME_BT458_REG_CONTROL_LAST) {
1.1.1.2   root      739:        
1.1.1.3 ! root      740:        /* write this register: */
        !           741:        bt458->tme_bt458_regs[bt458_address - TME_BT458_REG_CONTROL_FIRST] = value;
        !           742:       }
1.1.1.2   root      743:     }
                    744: 
                    745:     /* this must be a write to the overlay map register: */
                    746:     else {
                    747:       assert (reg == TME_SUNFB_S4_REG_BT458_OMAP);
                    748: 
                    749:       /* write the overlay map: */
                    750:       do {
                    751: 
                    752:        /* if the Bt458 address isn't in the overlay map: */
                    753:        if (bt458_address >= 4) {
                    754:          abort();
                    755:        }
                    756: 
                    757:        /* write one overlay map primary: */
                    758:        bt458->tme_bt458_omap_primaries[bt458_rgb][bt458_address] = value_packed >> 24;
                    759: 
                    760:        /* advance the packed value: */
                    761:        value_packed <<= 8;
                    762: 
                    763:        /* advance the Bt458 address registers: */
                    764:        bt458_rgb++;
                    765:        if (bt458_rgb == TME_ARRAY_ELS(bt458->tme_bt458_omap_primaries)) {
                    766:          bt458_address++;
                    767:          bt458_rgb = 0;
                    768:        }
                    769:       } while (--map_count > 0);
                    770: 
                    771:       /* calling out a mode change on every overlap map register write
                    772:         is expensive and unnecessary.  instead, arrange for the
                    773:         update function to eventually cause a mode change: */
                    774:       sunfb->tme_sunfb_callout_flags |= TME_SUNFB_CALLOUT_MODE_CHANGE;
                    775:     }
                    776:   }
                    777: 
                    778:   /* otherwise, this is a read: */
                    779:   else {
                    780:     assert (cycle_init->tme_bus_cycle_type == TME_BUS_CYCLE_READ);
                    781:   
                    782:     /* zero the value read: */
                    783:     value_packed = 0;
                    784: 
                    785:     /* assume only one byte will be read: */
                    786:     byte_count = sizeof(tme_uint8_t);
                    787: 
                    788:     /* if this is a read of the address register: */
                    789:     if (reg == TME_SUNFB_S4_REG_BT458_ADDRESS) {
                    790: 
                    791:       /* read the Bt458 address register: */
                    792:       value_packed = bt458_address;
                    793:     }
                    794: 
                    795:     /* if this is a read to the colormap register: */
                    796:     else if (reg == TME_SUNFB_S4_REG_BT458_CMAP) {
                    797:       
                    798:       /* read the colormap: */
                    799:       byte_count = map_count;
                    800:       do {
                    801: 
                    802:        /* advance the packed value: */
                    803:        value_packed <<= 8;
                    804: 
                    805:        /* read one colormap primary: */
                    806:        value_packed |= (bt458->tme_bt458_cmap_primaries[bt458_rgb])[bt458_address];
                    807: 
                    808:        /* advance the Bt458 address registers: */
                    809:        bt458_rgb++;
                    810:        if (bt458_rgb == TME_ARRAY_ELS(bt458->tme_bt458_cmap_primaries)) {
                    811:          bt458_address++;
                    812:          bt458_rgb = 0;
                    813:        }
                    814:       } while (--map_count > 0);
                    815:     }
                    816:   
                    817:     /* if this is a read of the control register: */
                    818:     else if (reg == TME_SUNFB_S4_REG_BT458_CONTROL) {
                    819: 
1.1.1.3 ! root      820:       /* the Bt458 datasheet says, "If an invalid address is loaded
        !           821:         into the address register, data written to the device will
        !           822:         be ignored and invalid data will be read by the MPU." */
        !           823:       if (bt458_address >= TME_BT458_REG_CONTROL_FIRST
        !           824:          && bt458_address <= TME_BT458_REG_CONTROL_LAST) {
1.1.1.2   root      825:        
1.1.1.3 ! root      826:        /* read this register: */
        !           827:        value_packed = bt458->tme_bt458_regs[bt458_address - TME_BT458_REG_CONTROL_FIRST];
        !           828:       }
1.1.1.2   root      829:     }
                    830: 
                    831:     /* this must be a read of the overlay map register: */
                    832:     else {
                    833:       assert (reg == TME_SUNFB_S4_REG_BT458_OMAP);
                    834: 
                    835:       /* read the overlay map: */
                    836:       byte_count = map_count;
                    837:       do {
                    838: 
                    839:        /* if the Bt458 address isn't in the overlay map: */
                    840:        if (bt458_address >= 4) {
                    841:          abort();
                    842:        }
                    843: 
                    844:        /* advance the packed value: */
                    845:        value_packed <<= 8;
                    846: 
                    847:        /* read one overlay map primary: */
                    848:        value_packed |= bt458->tme_bt458_omap_primaries[bt458_rgb][bt458_address];
                    849: 
                    850:        /* advance the Bt458 address registers: */
                    851:        bt458_rgb++;
                    852:        if (bt458_rgb == TME_ARRAY_ELS(bt458->tme_bt458_omap_primaries)) {
                    853:          bt458_address++;
                    854:          bt458_rgb = 0;
                    855:        }
                    856:       } while (--map_count > 0);
                    857:     }
                    858: 
                    859:     /* run the bus cycle: */
                    860:     if (cycle_init->tme_bus_cycle_size == sizeof(tme_uint32_t)) {
                    861:       if (byte_count == sizeof(tme_uint8_t)) {
                    862:        value_packed |= (value_packed << 8);
                    863:        value_packed |= (value_packed << 16);
                    864:       }
                    865:       tme_bus_cycle_xfer_reg(cycle_init, 
                    866:                             &value_packed,
                    867:                             TME_BUS32_LOG2);
                    868:     }
                    869:     else {
                    870:       value = value_packed;
                    871:       tme_bus_cycle_xfer_reg(cycle_init, 
                    872:                             &value,
                    873:                             TME_BUS8_LOG2);
                    874:     }
                    875:   }
                    876:     
                    877:   /* update the Bt458 address registers: */
                    878:   bt458->tme_bt458_address = bt458_address;
                    879:   bt458->tme_bt458_rgb = ((reg == TME_SUNFB_S4_REG_BT458_CMAP
                    880:                           || reg == TME_SUNFB_S4_REG_BT458_OMAP)
                    881:                          ? bt458_rgb
                    882:                          : 0);
                    883: 
                    884:   /* unlock the mutex: */
                    885:   tme_mutex_unlock(&sunfb->tme_sunfb_mutex);
                    886: 
                    887:   /* no faults: */
                    888:   return (TME_OK);
                    889: }
                    890: 
                    891: /* the sunfb S4 bus cycle handler: */
                    892: int
                    893: tme_sunfb_bus_cycle_s4(void *_sunfb, struct tme_bus_cycle *cycle_init)
                    894: {
                    895:   struct tme_sunfb *sunfb;
1.1.1.3 ! root      896:   tme_bus_addr32_t undecoded;
1.1.1.2   root      897:   tme_uint8_t sunfb_s4_status;
                    898: 
                    899:   /* if this bus cycle happened in the Bt458 registers: */
                    900:   if ((cycle_init->tme_bus_cycle_address % TME_SUNFB_S4_SIZ_REGS)
                    901:       < TME_SUNFB_S4_SIZ_BT458) {
                    902: 
                    903:     /* call the Bt458 cycle handler: */
                    904:     return (tme_sunfb_bus_cycle_bt458(_sunfb, cycle_init));
                    905:   }
                    906: 
                    907:   /* recover our data structure: */
                    908:   sunfb = (struct tme_sunfb *) _sunfb;
                    909: 
                    910:   /* lock the mutex: */
                    911:   tme_mutex_lock(&sunfb->tme_sunfb_mutex);
                    912: 
                    913:   /* the entire register bus subregion is all decoded (or, rather, not
                    914:      decoded) as the S4 registers: */
                    915:   undecoded
                    916:     = (cycle_init->tme_bus_cycle_address
1.1.1.3 ! root      917:        & (((tme_bus_addr32_t) 0)
1.1.1.2   root      918:          - TME_SUNFB_S4_SIZ_REGS));
                    919: 
                    920:   /* save the status register: */
                    921:   sunfb_s4_status = sunfb->tme_sunfb_s4_regs.tme_sunfb_s4_regs_status;
                    922: 
                    923:   /* if this is a write, and an interrupt is pending, and this write
                    924:      covers the status register: */
                    925:   if (cycle_init->tme_bus_cycle_type == TME_BUS_CYCLE_WRITE
                    926:       && (sunfb_s4_status & TME_SUNFB_S4_STATUS_INT_PENDING)
                    927:       && (cycle_init->tme_bus_cycle_address
                    928:          <= (undecoded
                    929:              + TME_SUNFB_S4_REG(tme_sunfb_s4_regs_status)))
                    930:       && (cycle_init->tme_bus_cycle_size
                    931:          > ((undecoded
                    932:              + TME_SUNFB_S4_REG(tme_sunfb_s4_regs_status))
                    933:             - cycle_init->tme_bus_cycle_address))) {
                    934:     
                    935:     /* clear the interrupt: */
                    936:     sunfb_s4_status &= ~TME_SUNFB_S4_STATUS_INT_PENDING;
                    937:   }
                    938: 
                    939:   /* run the cycle: */
                    940:   assert (cycle_init->tme_bus_cycle_address
                    941:          >= sunfb->tme_sunfb_bus_subregion_regs.tme_bus_subregion_address_first);
                    942:   tme_bus_cycle_xfer_memory(cycle_init, 
                    943:                            (((tme_uint8_t *) &sunfb->tme_sunfb_s4_regs)
                    944:                             - TME_SUNFB_S4_SIZ_BT458
                    945:                             - undecoded),
                    946:                            (undecoded
                    947:                             | (TME_SUNFB_S4_SIZ_REGS - 1)));
                    948: 
                    949:   /* restore the status register: */
                    950:   sunfb->tme_sunfb_s4_regs.tme_sunfb_s4_regs_status = sunfb_s4_status;
                    951: 
                    952:   /* make any callouts: */
                    953:   _tme_sunfb_callout(sunfb);
                    954: 
                    955:   /* unlock the mutex: */
                    956:   tme_mutex_unlock(&sunfb->tme_sunfb_mutex);
                    957: 
                    958:   /* no faults: */
                    959:   return (TME_OK);  
                    960: }
                    961: 
                    962: /* the sunfb TLB filler: */
                    963: static int
                    964: _tme_sunfb_tlb_fill(void *_sunfb,
                    965:                    struct tme_bus_tlb *tlb, 
1.1.1.3 ! root      966:                    tme_bus_addr_t address_wider,
1.1.1.2   root      967:                    unsigned int cycles)
                    968: {
                    969:   struct tme_sunfb *sunfb;
1.1.1.3 ! root      970:   tme_bus_addr32_t address;
        !           971:   struct tme_token *tlb_token;
        !           972:   struct tme_token *tlb_token_other;
        !           973:   tme_uint32_t offset_updated_first;
        !           974:   tme_uint32_t offset_updated_last;
1.1.1.2   root      975:   unsigned int subregion_i;
                    976: 
                    977:   /* recover our data structure: */
                    978:   sunfb = (struct tme_sunfb *) _sunfb;
                    979: 
                    980:   /* initialize the TLB entry: */
                    981:   tme_bus_tlb_initialize(tlb);
                    982: 
1.1.1.3 ! root      983:   /* get the normal-width address: */
        !           984:   address = address_wider;
        !           985:   assert (address == address_wider);
        !           986: 
1.1.1.2   root      987:   /* if this address falls in the bus subregion for memory: */
                    988:   if ((sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_first
                    989:        <= address)
                    990:       && (address
                    991:          <= sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_last)) {
                    992: 
                    993:     /* if this address falls in the memory pad: */
                    994:     if (address > sunfb->tme_sunfb_memory_address_last_displayed) {
                    995: 
                    996:       /* this TLB entry covers this range: */
                    997:       tlb->tme_bus_tlb_addr_first = (sunfb->tme_sunfb_memory_address_last_displayed + 1);
                    998:       tlb->tme_bus_tlb_addr_last = sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_last;
                    999: 
                   1000:       /* bus cycles to this range are to the memory pad and can be
                   1001:          fast: */
                   1002:       tlb->tme_bus_tlb_cycle = _tme_sunfb_bus_cycle_memory_pad;
1.1.1.3 ! root     1003:       tlb->tme_bus_tlb_emulator_off_write
        !          1004:        = (sunfb->tme_sunfb_memory_pad
        !          1005:           - tlb->tme_bus_tlb_addr_first);
1.1.1.2   root     1006:     }
                   1007: 
                   1008:     /* otherwise, this address does not fall in the memory pad: */
                   1009:     else {
                   1010: 
1.1.1.3 ! root     1011:       /* if this TLB entry is not for writing: */
        !          1012:       if ((cycles & TME_BUS_CYCLE_WRITE) == 0) {
        !          1013: 
        !          1014:        /* this TLB entry covers this range: */
        !          1015:        tlb->tme_bus_tlb_addr_first = sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_first;
        !          1016:        tlb->tme_bus_tlb_addr_last = sunfb->tme_sunfb_memory_address_last_displayed;
        !          1017: 
        !          1018:        /* this TLB entry allows only (fast) reading to the memory: */
        !          1019:        tlb->tme_bus_tlb_emulator_off_read = sunfb->tme_sunfb_memory - tlb->tme_bus_tlb_addr_first;
        !          1020:        tlb->tme_bus_tlb_rwlock = &sunfb->tme_sunfb_rwlock;
        !          1021:        tlb->tme_bus_tlb_cycles_ok = TME_BUS_CYCLE_READ;
        !          1022:        tlb->tme_bus_tlb_cycle = _tme_sunfb_bus_cycle_memory;
        !          1023:        tlb->tme_bus_tlb_cycle_private = _sunfb;
        !          1024:        return (TME_OK);
        !          1025:       }
        !          1026: 
        !          1027:       /* get the token for this writable TLB entry: */
        !          1028:       tlb_token = tlb->tme_bus_tlb_token;
        !          1029: 
        !          1030:       /* if a different writable TLB entry's token is outstanding: */
        !          1031:       tlb_token_other = sunfb->tme_sunfb_tlb_token;
        !          1032:       if (__tme_predict_true(tlb_token_other != NULL)) {
        !          1033:        if (tlb_token_other != tlb_token) {
        !          1034: 
        !          1035:          /* invalidate this other TLB entry: */
        !          1036:          tme_token_invalidate(tlb_token_other);
        !          1037:        }
        !          1038:       }
        !          1039: 
        !          1040:       /* save the token for this writable TLB entry: */
        !          1041:       sunfb->tme_sunfb_tlb_token = tlb_token;
        !          1042: 
        !          1043:       /* update the offsets of the first and last bytes updated in the
        !          1044:         real framebuffer memory: */
        !          1045:       offset_updated_first = address;
        !          1046:       offset_updated_first -= (tme_uint32_t) sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_first;
        !          1047:       offset_updated_last = offset_updated_first + TME_SUNFB_UPDATE_SIZE;
        !          1048:       offset_updated_first
        !          1049:        = TME_MIN(offset_updated_first,
        !          1050:                  sunfb->tme_sunfb_offset_updated_first);
        !          1051:       offset_updated_last
        !          1052:        = TME_MAX(offset_updated_last,
        !          1053:                  sunfb->tme_sunfb_offset_updated_last);
        !          1054:       offset_updated_last
        !          1055:        = TME_MIN(offset_updated_last,
        !          1056:                  (((tme_uint32_t)
        !          1057:                    sunfb->tme_sunfb_memory_address_last_displayed)
        !          1058:                   - ((tme_uint32_t)
        !          1059:                      sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_first)));
        !          1060:       sunfb->tme_sunfb_offset_updated_first = offset_updated_first;
        !          1061:       sunfb->tme_sunfb_offset_updated_last = offset_updated_last;
        !          1062: 
1.1.1.2   root     1063:       /* this TLB entry covers this range: */
1.1.1.3 ! root     1064:       tlb->tme_bus_tlb_addr_first
        !          1065:        = (sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_first
        !          1066:           + offset_updated_first);
        !          1067:       tlb->tme_bus_tlb_addr_last
        !          1068:        = (sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_first
        !          1069:           + offset_updated_last);
1.1.1.2   root     1070: 
                   1071:       /* bus cycles to this range are to the memory and can be fast: */
                   1072:       tlb->tme_bus_tlb_cycle = _tme_sunfb_bus_cycle_memory;
1.1.1.3 ! root     1073:       tlb->tme_bus_tlb_emulator_off_write
        !          1074:        = (sunfb->tme_sunfb_memory
        !          1075:           - sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_first);
1.1.1.2   root     1076:     }
                   1077: 
                   1078:     /* this TLB entry allows fast reading and writing: */
                   1079:     tlb->tme_bus_tlb_emulator_off_read = tlb->tme_bus_tlb_emulator_off_write;
                   1080:   }
                   1081: 
                   1082:   /* otherwise, this address doesn't fall in the bus subregion for memory: */
                   1083:   else {
                   1084: 
                   1085:     /* search the other bus subregions: */
                   1086:     for (subregion_i = 0;; subregion_i++) {
                   1087: 
                   1088:       /* this address must be in some subregion: */
                   1089:       assert (subregion_i < TME_SUNFB_BUS_SUBREGIONS_MAX);
                   1090: 
                   1091:       /* if this subregion is defined, and this address falls in it: */
                   1092:       if (sunfb->tme_sunfb_bus_handlers[subregion_i] != NULL
                   1093:          && (sunfb->tme_sunfb_bus_subregions[subregion_i].tme_bus_subregion_address_first
                   1094:              <= address)
                   1095:          && (address
                   1096:              <= sunfb->tme_sunfb_bus_subregions[subregion_i].tme_bus_subregion_address_last)) {
                   1097: 
                   1098:        /* this TLB entry covers this range: */
                   1099:        tlb->tme_bus_tlb_addr_first = sunfb->tme_sunfb_bus_subregions[subregion_i].tme_bus_subregion_address_first;
                   1100:        tlb->tme_bus_tlb_addr_last = sunfb->tme_sunfb_bus_subregions[subregion_i].tme_bus_subregion_address_last;
                   1101: 
                   1102:        /* bus cycles to this range are handled by this handler: */
                   1103:        tlb->tme_bus_tlb_cycle = sunfb->tme_sunfb_bus_handlers[subregion_i];
                   1104: 
                   1105:        break;
                   1106:       }
                   1107:     }
                   1108:   }
                   1109: 
                   1110:   /* the fast reading and writing rwlock: */
                   1111:   tlb->tme_bus_tlb_rwlock = &sunfb->tme_sunfb_rwlock;
                   1112: 
                   1113:   /* allow reading and writing: */
                   1114:   tlb->tme_bus_tlb_cycles_ok = TME_BUS_CYCLE_READ | TME_BUS_CYCLE_WRITE;
                   1115: 
                   1116:   /* our bus cycle handler private data: */
                   1117:   tlb->tme_bus_tlb_cycle_private = _sunfb;
                   1118: 
                   1119:   return (TME_OK);
                   1120: }
                   1121: 
1.1.1.3 ! root     1122: #if TME_SUNFB_BUS_TRANSITION
        !          1123: 
        !          1124: /* this is the bus cycle transition glue: */
        !          1125: int
        !          1126: tme_sunfb_bus_cycle_transition(void *_sunfb,
        !          1127:                               struct tme_bus_cycle *master_cycle,
        !          1128:                               void (*handler) _TME_P((struct tme_sunfb *,
        !          1129:                                                       struct tme_bus_cycle *,
        !          1130:                                                       tme_uint32_t *,
        !          1131:                                                       struct tme_completion *)))
        !          1132: {
        !          1133:   struct tme_completion completion_buffer;
        !          1134:   struct tme_sunfb *sunfb;
        !          1135:   tme_uint32_t master_fast_cycle_types;
        !          1136: 
        !          1137:   /* initialize the completion buffer: */
        !          1138:   tme_completion_init(&completion_buffer);
        !          1139: 
        !          1140: #ifndef NDEBUG
        !          1141: 
        !          1142:   /* initialize the completion: */
        !          1143:   completion_buffer.tme_completion_error = 0x71aa;
        !          1144: 
        !          1145: #endif /* NDEBUG */
        !          1146: 
        !          1147:   /* recover our data structure: */
        !          1148:   sunfb = (struct tme_sunfb *) _sunfb;
        !          1149: 
        !          1150:   /* lock the mutex: */
        !          1151:   tme_mutex_lock(&sunfb->tme_sunfb_mutex);
        !          1152: 
        !          1153:   /* run the cycle handler: */
        !          1154:   (*handler)
        !          1155:     (sunfb,
        !          1156:      master_cycle,
        !          1157:      &master_fast_cycle_types,
        !          1158:      &completion_buffer);
        !          1159: 
        !          1160:   /* unlock the mutex: */
        !          1161:   tme_mutex_unlock(&sunfb->tme_sunfb_mutex);
        !          1162: 
        !          1163:   /* check the completion: */
        !          1164:   assert (completion_buffer.tme_completion_error != (int) 0x71aa);
        !          1165: 
        !          1166:   return (completion_buffer.tme_completion_error);
        !          1167: }
        !          1168: 
        !          1169: #endif /* TME_SUNFB_BUS_TRANSITION */
        !          1170: 
1.1.1.2   root     1171: /* this makes a new framebuffer connection: */
                   1172: static int
                   1173: _tme_sunfb_connection_make(struct tme_connection *conn, unsigned int state)
1.1       root     1174: {
1.1.1.2   root     1175:   struct tme_sunfb *sunfb;
                   1176:   struct tme_fb_connection *conn_fb;
                   1177:   struct tme_fb_connection *conn_fb_other;
                   1178:   int rc;
                   1179: 
                   1180:   /* recover our data structures: */
                   1181:   sunfb = conn->tme_connection_element->tme_element_private;
                   1182:   conn_fb = (struct tme_fb_connection *) conn;
                   1183:   conn_fb_other = (struct tme_fb_connection *) conn->tme_connection_other;
                   1184: 
                   1185:   /* both sides must be framebuffer connections: */
                   1186:   assert(conn->tme_connection_type == TME_CONNECTION_FRAMEBUFFER);
                   1187:   assert(conn->tme_connection_other->tme_connection_type == TME_CONNECTION_FRAMEBUFFER);
                   1188: 
                   1189:   /* lock our mutex: */
                   1190:   tme_mutex_lock(&sunfb->tme_sunfb_mutex);
                   1191: 
                   1192:   /* we're always set up to answer calls across the connection, so we
                   1193:      only have to do work when the connection has gone full, namely
                   1194:      taking the other side of the connection: */
                   1195:   if (state == TME_CONNECTION_FULL) {
                   1196: 
                   1197:     /* if the other side of the connection is not supplying specific
                   1198:        displayed memory that it wants us to use: */
                   1199:     if (conn_fb->tme_fb_connection_buffer == NULL) {
                   1200: 
                   1201:       /* allocate displayed memory: */
                   1202:       rc = tme_fb_xlat_alloc_src(conn_fb);
                   1203:       assert (rc == TME_OK);
                   1204:     }
                   1205: 
                   1206:     /* if this framebuffer just maps the displayed memory on the bus,
                   1207:        do that: */
                   1208:     if (sunfb->tme_sunfb_memory == NULL) {
                   1209:       sunfb->tme_sunfb_memory = conn_fb->tme_fb_connection_buffer;
                   1210:     }
                   1211: 
                   1212:     /* save our connection: */
                   1213:     sunfb->tme_sunfb_fb_connection = conn_fb_other;
1.1       root     1214:   }
1.1.1.2   root     1215: 
                   1216:   /* unlock our mutex: */
                   1217:   tme_mutex_unlock(&sunfb->tme_sunfb_mutex);
                   1218: 
                   1219:   return (TME_OK);
                   1220: }
                   1221: 
                   1222: /* this breaks a connection: */
                   1223: static int
                   1224: _tme_sunfb_connection_break(struct tme_connection *conn, unsigned int state)
                   1225: {
                   1226:   abort();
                   1227: }
                   1228: 
                   1229: /* this makes a new connection side for a sunfb: */
                   1230: static int
                   1231: _tme_sunfb_connections_new(struct tme_element *element,
                   1232:                           const char * const *args,
                   1233:                           struct tme_connection **_conns,
                   1234:                           char **_output)
                   1235: {
                   1236:   struct tme_sunfb *sunfb;
                   1237:   struct tme_fb_connection *conn_fb;
                   1238:   struct tme_connection *conn;
                   1239:   int rc;
                   1240: 
                   1241:   /* recover our data structure: */
                   1242:   sunfb = (struct tme_sunfb *) element->tme_element_private;
                   1243: 
                   1244:   /* make the generic bus device connection side: */
                   1245:   rc = tme_bus_device_connections_new(element, args, _conns, _output);
                   1246:   if (rc != TME_OK) {
                   1247:     return (rc);
                   1248:   }
                   1249: 
                   1250:   /* if we don't have a framebuffer connection, make one: */
                   1251:   if (sunfb->tme_sunfb_fb_connection == NULL) {
                   1252: 
                   1253:     /* allocate the new framebuffer connection: */
                   1254:     conn_fb = tme_new0(struct tme_fb_connection, 1);
                   1255:     conn = &conn_fb->tme_fb_connection;
                   1256:     
                   1257:     /* fill in the generic connection: */
                   1258:     conn->tme_connection_next = *_conns;
                   1259:     conn->tme_connection_type = TME_CONNECTION_FRAMEBUFFER;
                   1260:     conn->tme_connection_score = tme_fb_connection_score;
                   1261:     conn->tme_connection_make = _tme_sunfb_connection_make;
                   1262:     conn->tme_connection_break = _tme_sunfb_connection_break;
                   1263: 
                   1264:     /* fill in the framebuffer connection: */
                   1265:     conn_fb->tme_fb_connection_mode_change = NULL;
                   1266:     conn_fb->tme_fb_connection_update = NULL;
                   1267: 
                   1268:     /* class: */
                   1269:     conn_fb->tme_fb_connection_class = sunfb->tme_sunfb_class;
                   1270: 
                   1271:     /* depth: */
                   1272:     conn_fb->tme_fb_connection_depth = sunfb->tme_sunfb_depth;
                   1273: 
                   1274:     /* width and height: */
                   1275:     conn_fb->tme_fb_connection_width = tme_sunfb_size_width(sunfb->tme_sunfb_size);
                   1276:     conn_fb->tme_fb_connection_height = tme_sunfb_size_height(sunfb->tme_sunfb_size);
                   1277: 
                   1278:     /* we skip no pixels at the start of the scanline: */
                   1279:     conn_fb->tme_fb_connection_skipx = 0;
                   1280: 
                   1281:     /* we pad to 32-bit boundaries: */
                   1282:     conn_fb->tme_fb_connection_scanline_pad = 32;
                   1283: 
                   1284:     /* we are big-endian: */
                   1285:     conn_fb->tme_fb_connection_order = TME_ENDIAN_BIG;
                   1286: 
                   1287:     /* we don't allocate memory until the connection is made, in case
                   1288:        the other side of the connection wants to provide us with a
                   1289:        specific memory region to use (maybe we're on a system with 
                   1290:        real matching hardware and we can write directly to its buffer): */
                   1291:     conn_fb->tme_fb_connection_buffer = NULL;
                   1292: 
                   1293:     /* assume that bits per pixel is the same as depth: */
                   1294:     conn_fb->tme_fb_connection_bits_per_pixel = sunfb->tme_sunfb_depth;
                   1295: 
                   1296:     /* assume that our pixels don't have subfields: */
                   1297:     conn_fb->tme_fb_connection_mask_g = 0;
                   1298:     conn_fb->tme_fb_connection_mask_r = 0;
                   1299:     conn_fb->tme_fb_connection_mask_b = 0;
                   1300: 
                   1301:     /* set any update function: */
                   1302:     conn_fb->tme_fb_connection_update = sunfb->tme_sunfb_memory_update;
                   1303: 
                   1304:     /* if this is a bwtwo: */
                   1305:     if (_TME_SUNFB_IS_BWTWO(sunfb)) {
                   1306: 
                   1307:       /* intensities are a single bit, linearly mapped, but inverted: */
                   1308:       conn_fb->tme_fb_connection_map_bits = 1;
                   1309:       conn_fb->tme_fb_connection_map_g = NULL;
                   1310:       conn_fb->tme_fb_connection_map_r = NULL;
                   1311:       conn_fb->tme_fb_connection_map_b = NULL;
                   1312:       conn_fb->tme_fb_connection_inverted = TRUE;
                   1313:     }
                   1314: 
                   1315:     /* otherwise, this is one of the eight-bit color framebuffers: */
                   1316:     else {
                   1317: 
                   1318:       /* intensities are eight bits and index mapped: */
                   1319:       conn_fb->tme_fb_connection_map_bits = 8;
                   1320:       conn_fb->tme_fb_connection_map_g = sunfb->tme_sunfb_cmap_g;
                   1321:       conn_fb->tme_fb_connection_map_r = sunfb->tme_sunfb_cmap_r;
                   1322:       conn_fb->tme_fb_connection_map_b = sunfb->tme_sunfb_cmap_b;
                   1323:     }
                   1324: 
                   1325:     /* return the connection side possibility: */
                   1326:     *_conns = conn;
                   1327:   }
                   1328: 
                   1329:   /* done: */
                   1330:   return (TME_OK);
                   1331: }
                   1332: 
                   1333: /* the new Sun framebuffer function: */
                   1334: int
                   1335: tme_sunfb_new(struct tme_sunfb *sunfb, 
                   1336:              const char * const *args,
                   1337:              char **_output)
                   1338: {
                   1339:   struct tme_bus_subregion *subregion;
                   1340:   const struct tme_bus_subregion **_subregion_prev;
                   1341:   unsigned int subregion_i;
                   1342:   const char *sunfb_type_string;
                   1343:   const char *sunfb_size_string;
                   1344:   tme_uint32_t sunfb_size;
                   1345:   tme_bus_addr_t fb_size;
                   1346:   tme_uint32_t sunfb_p4;
                   1347:   tme_uint8_t sunfb_s4_status;
                   1348:   int arg_i;
                   1349:   int usage;
                   1350: 
                   1351:   /* check our arguments: */
                   1352:   usage = 0;
                   1353:   sunfb_type_string = NULL;
                   1354:   sunfb_size_string = NULL;
                   1355:   arg_i = 1;
                   1356:   for (;;) {
                   1357: 
                   1358:     /* the framebuffer type: */
                   1359:     if (TME_ARG_IS(args[arg_i + 0], "type")
                   1360:        && sunfb_type_string == NULL
                   1361:        && sunfb->tme_sunfb_type_set != NULL) {
                   1362:       sunfb_type_string = args[arg_i + 1];
                   1363:       if (sunfb_type_string == NULL
                   1364:          || (*sunfb->tme_sunfb_type_set)(sunfb, sunfb_type_string) != NULL) {
                   1365:        usage = TRUE;
                   1366:        break;
                   1367:       }
                   1368:       arg_i += 2;
                   1369:     }
                   1370: 
                   1371:     /* the framebuffer size: */
                   1372:     else if (TME_ARG_IS(args[arg_i + 0], "size")
                   1373:             && sunfb_size_string == NULL) {
                   1374:       sunfb_size_string = args[arg_i + 1];
                   1375:       if (sunfb_size_string == NULL) {
                   1376:        usage = TRUE;
                   1377:        break;
                   1378:       }
                   1379:       arg_i += 2;
                   1380:     }
                   1381: 
                   1382:     /* if we ran out of arguments: */
                   1383:     else if (args[arg_i] == NULL) {
                   1384: 
                   1385:       break;
                   1386:     }
                   1387: 
                   1388:     /* otherwise this is a bad argument: */
                   1389:     else {
                   1390:       tme_output_append_error(_output,
                   1391:                              "%s %s, ",
                   1392:                              args[arg_i],
                   1393:                              _("unexpected"));
                   1394:       usage = TRUE;
                   1395:       break;
                   1396:     }
                   1397:   }
                   1398: 
                   1399:   /* set some common defaults based on framebuffer type: */
                   1400: 
                   1401:   /* if this is a P4 framebuffer: */
                   1402:   if (_TME_SUNFB_IS_P4(sunfb)) {
                   1403: 
                   1404:     /* default possible P4 sizes: */
                   1405:     if (sunfb->tme_sunfb_size == 0) {
                   1406:       sunfb->tme_sunfb_size
                   1407:        = (TME_SUNFB_SIZE_1600_1280
                   1408:           | TME_SUNFB_SIZE_1152_900
                   1409:           | TME_SUNFB_SIZE_1024_1024
                   1410:           | TME_SUNFB_SIZE_1280_1024
                   1411:           | TME_SUNFB_SIZE_1440_1440);
                   1412:     }
                   1413: 
                   1414:     /* the memory address can't be zero: */
                   1415:     assert (sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_first != 0);
                   1416: 
                   1417:     /* the P4 register is always at the same offset: */
                   1418:     sunfb->tme_sunfb_bus_subregion_regs.tme_bus_subregion_address_first = TME_SUNFB_P4_OFFSET_P4;
                   1419: 
                   1420:     /* the default size of the P4 register bus subregion: */
                   1421:     if (sunfb->tme_sunfb_bus_subregion_regs.tme_bus_subregion_address_last == 0) {
                   1422:       sunfb->tme_sunfb_bus_subregion_regs.tme_bus_subregion_address_last
                   1423:        = (sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_first
                   1424:           - 1);
                   1425:     }
                   1426:   }
                   1427:   
                   1428: 
                   1429:   /* if this is an S4 framebuffer: */
                   1430:   if (_TME_SUNFB_IS_S4(sunfb)) {
                   1431: 
                   1432:     /* default possible S4 framebuffer sizes: */
                   1433:     if (sunfb->tme_sunfb_size == 0) {
                   1434:       sunfb->tme_sunfb_size
                   1435:        = (TME_SUNFB_SIZE_1024_768
                   1436:           | TME_SUNFB_SIZE_1152_900
                   1437:           | TME_SUNFB_SIZE_1280_1024
                   1438:           | TME_SUNFB_SIZE_1600_1280);
                   1439:     }
                   1440: 
                   1441:     /* the default memory address: */
                   1442:     if (sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_first == 0) {
                   1443:       sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_first = TME_SUNFB_S4_OFFSET_MEMORY;
                   1444:     }
                   1445: 
                   1446:     /* the S4 registers are always at the same offset: */
                   1447:     sunfb->tme_sunfb_bus_subregion_regs.tme_bus_subregion_address_first = TME_SUNFB_S4_OFFSET_REGS;
                   1448: 
                   1449:     /* the default size of the S4 register bus subregion: */
                   1450:     if (sunfb->tme_sunfb_bus_subregion_regs.tme_bus_subregion_address_last == 0) {
                   1451:       sunfb->tme_sunfb_bus_subregion_regs.tme_bus_subregion_address_last
                   1452:        = (sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_first
                   1453:           - 1);
                   1454:     }
                   1455:   }
                   1456: 
                   1457:   /* we must have some possible sizes: */
                   1458:   assert (sunfb->tme_sunfb_size != 0 || usage);
                   1459: 
                   1460:   /* if no specific size is given: */
                   1461:   if (sunfb_size_string == NULL) {
                   1462: 
                   1463:     /* use the first size supported by this framebuffer, which will
                   1464:        usually be 1152x900: */
                   1465:     sunfb_size = sunfb->tme_sunfb_size;
                   1466:     sunfb_size = (sunfb_size & ~(sunfb_size - 1));
                   1467:   }
                   1468: 
                   1469:   /* otherwise, convert the specific size: */
                   1470:   else {
                   1471:     sunfb_size = tme_sunfb_size(sunfb_size_string);
                   1472:   }
                   1473: 
                   1474:   /* if the size is not supported by this framebuffer: */
                   1475:   if ((sunfb->tme_sunfb_size & sunfb_size) == 0) {
                   1476:     usage = TRUE;
                   1477:   }
                   1478: 
                   1479:   if (usage) {
                   1480: 
                   1481:     /* start the usage message: */
                   1482:     tme_output_append_error(_output,
                   1483:                            "%s %s",
                   1484:                            _("usage"),
                   1485:                            args[0]);
                   1486: 
                   1487:     /* if this framebuffer has types, append a type argument to the
                   1488:        usage message: */
                   1489:     if (sunfb->tme_sunfb_type_set != NULL) {
                   1490:       sunfb_type_string = (*sunfb->tme_sunfb_type_set)(sunfb, NULL);
                   1491:       tme_output_append_error(_output, " type { %s }", sunfb_type_string);
                   1492:     }
                   1493: 
                   1494:     /* append the supported types to the usage message: */
                   1495:     tme_output_append_error(_output,
                   1496:                            " [ size {");
                   1497:     for (sunfb_size = sunfb->tme_sunfb_size;
                   1498:         sunfb_size != 0;
                   1499:         sunfb_size &= (sunfb_size - 1)) {
                   1500:       switch (sunfb_size & ~(sunfb_size - 1)) {
                   1501:       default: assert(FALSE);
                   1502:       case TME_SUNFB_SIZE_1152_900: sunfb_size_string = "1152x900"; break;
                   1503:       case TME_SUNFB_SIZE_1024_1024: sunfb_size_string = "1024x1024"; break;
                   1504:       case TME_SUNFB_SIZE_1280_1024: sunfb_size_string = "1280x1024"; break;
                   1505:       case TME_SUNFB_SIZE_1600_1280: sunfb_size_string = "1600x1280"; break;
                   1506:       case TME_SUNFB_SIZE_1440_1440: sunfb_size_string = "1440x1440"; break;
                   1507:       case TME_SUNFB_SIZE_1024_768: sunfb_size_string = "1024x768"; break;
                   1508:       case TME_SUNFB_SIZE_640_480: sunfb_size_string = "640x480"; break;
                   1509:       }
                   1510:       tme_output_append_error(_output, " %s", sunfb_size_string);
                   1511:     }
                   1512:     tme_output_append_error(_output, " } ]");
                   1513: 
                   1514:     /* return the error: */
                   1515:     return (EINVAL);
                   1516:   }
                   1517: 
                   1518:   /* finish initializing the sunfb structure: */
                   1519:   tme_mutex_init(&sunfb->tme_sunfb_mutex);
                   1520:   tme_rwlock_init(&sunfb->tme_sunfb_rwlock);
                   1521: 
                   1522:   /* set the size: */
                   1523:   sunfb->tme_sunfb_size = sunfb_size;
                   1524: 
                   1525:   /* calculate the number of bytes of displayed framebuffer memory: */
                   1526:   fb_size = tme_sunfb_size_width(sunfb->tme_sunfb_size);
                   1527:   fb_size *= tme_sunfb_size_height(sunfb->tme_sunfb_size);
                   1528:   if (_TME_SUNFB_IS_BWTWO(sunfb)) {
                   1529:     fb_size /= 8;
                   1530:   }
                   1531: 
                   1532:   /* set the (relative) bus address of the last byte of displayed
                   1533:      memory: */
                   1534:   sunfb->tme_sunfb_memory_address_last_displayed
                   1535:     = (sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_first
                   1536:        + fb_size
                   1537:        - 1);
                   1538: 
                   1539:   /* assume that the real number of bytes of memory is the number of
                   1540:      bytes displayed, rounded up to the nearest power of two: */
                   1541:   if ((fb_size & (fb_size - 1)) != 0) {
                   1542:     for (; (fb_size & (fb_size - 1)) != 0; fb_size &= (fb_size - 1));
                   1543:     fb_size <<= 1;
                   1544:   }
                   1545: 
                   1546:   /* set the (relative) bus address of the last byte of memory: */
                   1547:   sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_last
                   1548:     = (sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_first
                   1549:        + fb_size
                   1550:        - 1);
                   1551: 
                   1552:   /* if we need to, allocate pad (undisplayed) framebuffer memory: */
                   1553:   if (sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_last
                   1554:       > sunfb->tme_sunfb_memory_address_last_displayed) {
                   1555: 
                   1556:     /* allocate the pad memory: */
                   1557:     sunfb->tme_sunfb_memory_pad
                   1558:       = tme_new0(tme_uint8_t,
                   1559:                 (sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_last
                   1560:                  - sunfb->tme_sunfb_memory_address_last_displayed));
                   1561:   }
                   1562: 
                   1563:   /* if this is a P4 framebuffer: */
                   1564:   if (_TME_SUNFB_IS_P4(sunfb)) {
                   1565: 
                   1566:     /* get our initial P4 register: */
                   1567:     sunfb_p4 = tme_betoh_u32(sunfb->tme_sunfb_p4);
                   1568: 
                   1569:     /* if the P4 register doesn't already have something in the size
                   1570:        field, add it: */
                   1571:     if ((sunfb_p4 & TME_SUNFB_P4_SIZE_MASK) == 0) {
                   1572:       switch (sunfb_size) {
                   1573:       default: assert(FALSE);
                   1574:       case TME_SUNFB_SIZE_1152_900: sunfb_p4 |= TME_SUNFB_P4_SIZE_1152_900; break;
                   1575:       case TME_SUNFB_SIZE_1024_1024: sunfb_p4 |= TME_SUNFB_P4_SIZE_1024_1024; break;
                   1576:       case TME_SUNFB_SIZE_1280_1024: sunfb_p4 |= TME_SUNFB_P4_SIZE_1280_1024; break;
                   1577:       case TME_SUNFB_SIZE_1600_1280: sunfb_p4 |= TME_SUNFB_P4_SIZE_1600_1280; break;
                   1578:       case TME_SUNFB_SIZE_1440_1440: sunfb_p4 |= TME_SUNFB_P4_SIZE_1440_1440; break;
                   1579:       case TME_SUNFB_SIZE_640_480: sunfb_p4 |= TME_SUNFB_P4_SIZE_640_480; break;
                   1580:       }
                   1581:     }
                   1582: 
                   1583:     /* set video as enabled: */
                   1584:     sunfb_p4 |= TME_SUNFB_P4_REG_VIDEO_ENABLE;
                   1585: 
                   1586:     /* set the initial P4 register: */
                   1587:     sunfb->tme_sunfb_p4 = tme_htobe_u32(sunfb_p4);
                   1588:   }
                   1589: 
                   1590:   /* if this is an S4 framebuffer: */
                   1591:   if (_TME_SUNFB_IS_S4(sunfb)) {
                   1592: 
                   1593:     /* set the initial S4 control register: */
                   1594:     sunfb->tme_sunfb_s4_regs.tme_sunfb_s4_regs_control
                   1595:       = (TME_SUNFB_S4_CONTROL_VIDEO_ENABLE);
                   1596: 
                   1597:     /* set the initial S4 status register: */
                   1598:     switch (sunfb_size) {
                   1599:     default: assert(FALSE);
                   1600:     case TME_SUNFB_SIZE_1152_900: sunfb_s4_status = TME_SUNFB_S4_STATUS_SIZE_1152_900; break;
                   1601:     case TME_SUNFB_SIZE_1024_768: sunfb_s4_status = TME_SUNFB_S4_STATUS_SIZE_1024_768; break;
                   1602:     case TME_SUNFB_SIZE_1280_1024: sunfb_s4_status = TME_SUNFB_S4_STATUS_SIZE_1280_1024; break;
                   1603:     case TME_SUNFB_SIZE_1600_1280: sunfb_s4_status = TME_SUNFB_S4_STATUS_SIZE_1600_1280; break;
                   1604:     }
                   1605:     sunfb->tme_sunfb_s4_regs.tme_sunfb_s4_regs_status
                   1606:       = (sunfb_s4_status
                   1607:         | (_TME_SUNFB_IS_BWTWO(sunfb)
                   1608:            ? TME_SUNFB_S4_STATUS_ID_MONO
                   1609:            : TME_SUNFB_S4_STATUS_ID_COLOR));
                   1610:   }
                   1611: 
1.1.1.3 ! root     1612:   /* make sure that the interrupt signal has been defined.  no known
        !          1613:      framebuffer uses a priority zero interrupt: */
        !          1614: #if TME_BUS_SIGNAL_INT(0) != 0
        !          1615: #error "TME_BUS_SIGNAL_INT() changed"
        !          1616: #endif
        !          1617:   assert (sunfb->tme_sunfb_bus_signal_int != TME_BUS_SIGNAL_INT(0));
        !          1618: 
1.1.1.2   root     1619:   /* if this is a color framebuffer: */
                   1620:   if (!_TME_SUNFB_IS_BWTWO(sunfb)) {
                   1621: 
                   1622:     /* if we don't have a specific memory update function, use the
                   1623:        default: */
                   1624:     if (sunfb->tme_sunfb_memory_update == NULL) {
                   1625:       sunfb->tme_sunfb_memory_update = tme_sunfb_memory_update;
                   1626:     }
                   1627:   }
                   1628: 
                   1629:   /* make all of the defined subregions into a list.  the memory
                   1630:      subregion is always in the list, and it is first: */
                   1631:   _subregion_prev = &sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_next;
                   1632:   for (subregion_i = 0;
                   1633:        subregion_i < TME_SUNFB_BUS_SUBREGIONS_MAX;
                   1634:        subregion_i++) {
                   1635:     if (sunfb->tme_sunfb_bus_handlers[subregion_i] != NULL) {
                   1636:       subregion = &sunfb->tme_sunfb_bus_subregions[subregion_i];
                   1637:       *_subregion_prev = subregion;
                   1638:       _subregion_prev = &subregion->tme_bus_subregion_next;
                   1639:     }
                   1640:   }
                   1641:   *_subregion_prev = NULL;
                   1642: 
                   1643:   /* initialize our simple bus device descriptor: */
                   1644:   sunfb->tme_sunfb_device.tme_bus_device_tlb_fill = _tme_sunfb_tlb_fill;
                   1645: 
                   1646:   /* fill the element: */
                   1647:   sunfb->tme_sunfb_element->tme_element_private = sunfb;
                   1648:   sunfb->tme_sunfb_element->tme_element_connections_new = _tme_sunfb_connections_new;
                   1649: 
                   1650:   /* initialize the timeout thread condition: */
                   1651:   tme_cond_init(&sunfb->tme_sunfb_callout_cond);
                   1652: 
                   1653:   /* start the callout thread: */
                   1654:   tme_thread_create((tme_thread_t) _tme_sunfb_callout_thread, sunfb);
                   1655: 
                   1656:   return (TME_OK);
                   1657: }
                   1658: 
                   1659: /* the new sun cgthree function: */
                   1660: int
                   1661: tme_sun_cgthree(struct tme_element *element, const char * const *args, char **_output)
                   1662: {
                   1663:   struct tme_sunfb *sunfb;
                   1664:   tme_uint8_t *cmap;
                   1665:   int rc;
                   1666: 
                   1667:   /* start the sunfb structure: */
                   1668:   sunfb = tme_new0(struct tme_sunfb, 1);
                   1669:   sunfb->tme_sunfb_element = element;
                   1670: 
                   1671:   /* initialize the sunfb structure: */
                   1672:   sunfb->tme_sunfb_class = TME_FB_XLAT_CLASS_COLOR;
                   1673:   sunfb->tme_sunfb_depth = 8;
                   1674:   sunfb->tme_sunfb_bus_handler_regs = tme_sunfb_bus_cycle_s4;
                   1675:   sunfb->tme_sunfb_flags
                   1676:     |= (TME_SUNFB_FLAG_BT458_CMAP_PACKED
                   1677:        | TME_SUNFB_FLAG_BT458_BYTE_D0_D7);
1.1.1.3 ! root     1678:   sunfb->tme_sunfb_bus_signal_int = TME_BUS_SIGNAL_INT(5);
1.1.1.2   root     1679: 
                   1680:   /* if the generic initialization fails: */
                   1681:   rc = tme_sunfb_new(sunfb, args, _output);
                   1682:   if (rc) {
                   1683: 
                   1684:     /* free the sunfb structure and return the error: */
                   1685:     tme_free(sunfb);
                   1686:     return (rc);
                   1687:   }
                   1688: 
                   1689:   /* allocate the colormap arrays: */
                   1690:   cmap = tme_new0(tme_uint8_t, 256 * 3);
                   1691:   sunfb->tme_sunfb_cmap_g = &cmap[256 * 0];
                   1692:   sunfb->tme_sunfb_cmap_r = &cmap[256 * 1];
                   1693:   sunfb->tme_sunfb_cmap_b = &cmap[256 * 2];
                   1694:   sunfb->tme_sunfb_bt458.tme_bt458_cmap_g = sunfb->tme_sunfb_cmap_g;
                   1695:   sunfb->tme_sunfb_bt458.tme_bt458_cmap_r = sunfb->tme_sunfb_cmap_r;
                   1696:   sunfb->tme_sunfb_bt458.tme_bt458_cmap_b = sunfb->tme_sunfb_cmap_b;
                   1697: 
                   1698:   return (TME_OK);
1.1       root     1699: }

unix.superglobalmegacorp.com

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