|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.