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

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

unix.superglobalmegacorp.com

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