|
|
1.1 ! root 1: /* $Id: sun-cgtwo.c,v 1.2 2005/05/09 02:01:02 fredette Exp $ */ ! 2: ! 3: /* machine/sun/sun-cgtwo.c - Sun cgtwo emulation: */ ! 4: ! 5: /* ! 6: * Copyright (c) 2003, 2004, 2005 Matt Fredette ! 7: * All rights reserved. ! 8: * ! 9: * Redistribution and use in source and binary forms, with or without ! 10: * modification, are permitted provided that the following conditions ! 11: * are met: ! 12: * 1. Redistributions of source code must retain the above copyright ! 13: * notice, this list of conditions and the following disclaimer. ! 14: * 2. Redistributions in binary form must reproduce the above copyright ! 15: * notice, this list of conditions and the following disclaimer in the ! 16: * documentation and/or other materials provided with the distribution. ! 17: * 3. All advertising materials mentioning features or use of this software ! 18: * must display the following acknowledgement: ! 19: * This product includes software developed by Matt Fredette. ! 20: * 4. The name of the author may not be used to endorse or promote products ! 21: * derived from this software without specific prior written permission. ! 22: * ! 23: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR ! 24: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ! 25: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ! 26: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, ! 27: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ! 28: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ! 29: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, ! 31: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ! 32: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ! 33: * POSSIBILITY OF SUCH DAMAGE. ! 34: */ ! 35: ! 36: #include <tme/common.h> ! 37: _TME_RCSID("$Id: sun-cgtwo.c,v 1.2 2005/05/09 02:01:02 fredette Exp $"); ! 38: ! 39: /* includes: */ ! 40: #include <tme/machine/sun.h> ! 41: #include <tme/generic/bus-device.h> ! 42: #include <tme/generic/fb.h> ! 43: #include "sun-fb.h" ! 44: ! 45: /* macros: */ ! 46: ! 47: /* cgtwo types: */ ! 48: #define TME_SUNCG2_TYPE_NULL (0) ! 49: #define TME_SUNCG2_TYPE_SUN3 (1) ! 50: ! 51: /* a cgtwo has eight planes: */ ! 52: #define TME_SUNCG2_PLANE_MAX (8) ! 53: ! 54: /* every rasterop unit has its alternate, prime registers: */ ! 55: #define TME_SUNCG2_ROPC_PRIME (9) ! 56: ! 57: /* every so many CSR reads, we fake a retrace: */ ! 58: #define TME_SUNCG2_CYCLE_RETRACE (10) ! 59: ! 60: /* this gives the index into the entire colormap of a pixel's ! 61: intensity for a given primary: */ ! 62: #define TME_SUNCG2_CMAP_INDEX(pixel, primary) ((((primary) - TME_SUNCG2_REG_CMAP_R) / sizeof(tme_uint16_t)) + (pixel)) ! 63: ! 64: /* this gives a pixel's intensity for a given primary: */ ! 65: #define TME_SUNCG2_CMAP_VALUE(suncg2, pixel, primary) \ ! 66: (tme_betoh_u16((suncg2)->tme_suncg2_cmap_raw[TME_SUNCG2_CMAP_INDEX(pixel, primary)]) & 0xff) ! 67: ! 68: /* a plane bitmap has one bit per pixel: */ ! 69: #define TME_SUNCG2_REG_BITMAP(x) (0x000000 + (TME_SUNCG2_SIZ_BITMAP * (x))) ! 70: #define TME_SUNCG2_SIZ_BITMAP ((1024 * 1024) / 8) ! 71: ! 72: /* the pixmap has one byte per pixel: */ ! 73: #define TME_SUNCG2_REG_PIXMAP (0x100000) ! 74: #define TME_SUNCG2_SIZ_PIXMAP (1024 * 1024) ! 75: ! 76: /* the raster op data: */ ! 77: #define TME_SUNCG2_REG_ROP_DATA (0x200000) ! 78: ! 79: /* register offsets and sizes. many registers are decoded at all ! 80: size-aligned addresses within a 4KB page: */ ! 81: #define TME_SUNCG2_SIZ_REG_PAGE (0x001000) ! 82: #define TME_SUNCG2_REG_ROPC_UNIT(x) (0x300000 + ((x) * TME_SUNCG2_SIZ_REG_PAGE)) ! 83: #define TME_SUNCG2_REG_ROPC_UNIT_PRIME(x) (TME_SUNCG2_REG_ROPC_UNIT(x) + 0x000800) ! 84: #define TME_SUNCG2_REG_CSR (0x309000) ! 85: #define TME_SUNCG2_REG_PLANE_MASK (0x30a000) ! 86: #define TME_SUNCG2_REG_SUN2_PAN_HI (0x30b000) ! 87: #define TME_SUNCG2_REG_SUN3_DOUBLE_BUF (0x30b000) ! 88: #define TME_SUNCG2_REG_SUN2_ZOOM (0x30c000) ! 89: #define TME_SUNCG2_REG_SUN3_DMA_BASE (0x30c000) ! 90: #define TME_SUNCG2_REG_SUN2_PAN_LO (0x30d000) ! 91: #define TME_SUNCG2_REG_SUN3_DMA_WIDTH (0x30d000) ! 92: #define TME_SUNCG2_REG_SUN2_ZOOM_VAR (0x30e000) ! 93: #define TME_SUNCG2_REG_SUN3_FRAME_COUNT (0x30e000) ! 94: #define TME_SUNCG2_REG_INTVEC (0x30f000) ! 95: #define TME_SUNCG2_REG_CMAP_R (0x310000) ! 96: #define TME_SUNCG2_REG_CMAP_G (0x310200) ! 97: #define TME_SUNCG2_REG_CMAP_B (0x310400) ! 98: #define TME_SUNCG2_SIZ_REGS (0x310600) ! 99: ! 100: /* the bits in the Control/Status register: */ ! 101: #define TME_SUNCG2_CSR_ENABLE_VIDEO (0x0001) ! 102: #define TME_SUNCG2_CSR_CMAP_UPDATE (0x0002) ! 103: #define TME_SUNCG2_CSR_INT_ENABLE (0x0004) ! 104: #define TME_SUNCG2_CSR_ROP_MODE_MASK (0x0038) ! 105: #define TME_SUNCG2_CSR_ROP_MODE_PRWWRD (0x0000) ! 106: #define TME_SUNCG2_CSR_ROP_MODE_SRWPIX (0x0008) ! 107: #define TME_SUNCG2_CSR_ROP_MODE_PWWWRD (0x0010) ! 108: #define TME_SUNCG2_CSR_ROP_MODE_SWWPIX (0x0018) ! 109: #define TME_SUNCG2_CSR_ROP_MODE_PRRWRD (0x0020) ! 110: #define TME_SUNCG2_CSR_ROP_MODE_PRWPIX (0x0028) ! 111: #define TME_SUNCG2_CSR_ROP_MODE_PWRWRD (0x0030) ! 112: #define TME_SUNCG2_CSR_ROP_MODE_PWWPIX (0x0038) ! 113: #define TME_SUNCG2_CSR_INT_ACTIVE (0x0040) ! 114: #define TME_SUNCG2_CSR_RETRACE (0x0080) ! 115: #define TME_SUNCG2_CSR_SIZE_MASK_SUN2 (0x0f00) ! 116: #define TME_SUNCG2_CSR_SIZE_MASK_SUN3 (0x0100) ! 117: #define TME_SUNCG2_CSR_SIZE_1152_900 (0x0000) ! 118: #define TME_SUNCG2_CSR_SIZE_1024_1024 (0x0100) ! 119: ! 120: /* the raster ops: */ ! 121: #define TME_SUNCG2_ROP_SRC (0xcc) ! 122: #define TME_SUNCG2_ROP_DST (0xaa) ! 123: #define TME_SUNCG2_ROP_NOT(x) ((x) ^ 0xff) ! 124: ! 125: /* the callout flags: */ ! 126: #define TME_SUNCG2_CALLOUT_CHECK (0) ! 127: #define TME_SUNCG2_CALLOUT_RUNNING TME_BIT(0) ! 128: #define TME_SUNCG2_CALLOUTS_MASK (-2) ! 129: #define TME_SUNCG2_CALLOUT_MODE_CHANGE TME_BIT(1) ! 130: #define TME_SUNCG2_CALLOUT_INT TME_BIT(2) ! 131: ! 132: /* state flags: */ ! 133: #define TME_SUNCG2_FLAG_INVALID_DISPLAYED TME_BIT(0) ! 134: #define TME_SUNCG2_FLAG_INVALID_PIXMAP TME_BIT(1) ! 135: #define TME_SUNCG2_FLAG_INVALID_BITMAPS TME_BIT(2) ! 136: #define TME_SUNCG2_FLAG_CALLOUT_THREAD_RUNNING TME_BIT(3) ! 137: ! 138: /* structures: */ ! 139: ! 140: /* the card: */ ! 141: struct tme_suncg2 { ! 142: ! 143: /* our simple bus device header: */ ! 144: struct tme_bus_device tme_suncg2_device; ! 145: #define tme_suncg2_element tme_suncg2_device.tme_bus_device_element ! 146: ! 147: /* the mutex protecting the card: */ ! 148: tme_mutex_t tme_suncg2_mutex; ! 149: ! 150: /* the rwlock protecting the card: */ ! 151: tme_rwlock_t tme_suncg2_rwlock; ! 152: ! 153: /* the framebuffer connection: */ ! 154: struct tme_fb_connection *tme_suncg2_fb_connection; ! 155: ! 156: /* the callout flags: */ ! 157: int tme_suncg2_callout_flags; ! 158: ! 159: /* the type of the cgtwo: */ ! 160: tme_uint32_t tme_suncg2_type; ! 161: ! 162: /* the size of the bwtwo: */ ! 163: tme_uint32_t tme_suncg2_size; ! 164: ! 165: /* the number of displayed pixels: */ ! 166: tme_uint32_t tme_suncg2_pixel_count; ! 167: ! 168: /* the raw memory: */ ! 169: tme_uint8_t *tme_suncg2_raw_memory; ! 170: ! 171: /* the displayed memory: */ ! 172: tme_uint8_t *tme_suncg2_displayed_memory; ! 173: ! 174: /* the rasterop registers: */ ! 175: struct { ! 176: tme_uint16_t tme_suncg2_ropc_dest; ! 177: tme_uint16_t tme_suncg2_ropc_source1; ! 178: tme_uint16_t tme_suncg2_ropc_source2; ! 179: tme_uint16_t tme_suncg2_ropc_pattern; ! 180: tme_uint16_t tme_suncg2_ropc_mask1; ! 181: tme_uint16_t tme_suncg2_ropc_mask2; ! 182: tme_uint16_t tme_suncg2_ropc_ena_shift; ! 183: tme_uint16_t tme_suncg2_ropc_op; ! 184: tme_uint16_t tme_suncg2_ropc_width; ! 185: tme_uint16_t tme_suncg2_ropc_opcount; ! 186: tme_uint16_t tme_suncg2_ropc_decoderout; ! 187: tme_uint16_t tme_suncg2_ropc_x11; ! 188: tme_uint16_t tme_suncg2_ropc_x12; ! 189: tme_uint16_t tme_suncg2_ropc_x13; ! 190: tme_uint16_t tme_suncg2_ropc_x14; ! 191: tme_uint16_t tme_suncg2_ropc_x15; ! 192: } tme_suncg2_ropc[TME_SUNCG2_ROPC_PRIME * 2]; ! 193: ! 194: /* our csr: */ ! 195: tme_uint16_t tme_suncg2_csr; ! 196: ! 197: /* our interrupt vector: */ ! 198: tme_uint16_t tme_suncg2_intvec; ! 199: ! 200: /* our plane mask: */ ! 201: tme_uint16_t tme_suncg2_plane_mask; ! 202: ! 203: /* the raw colormap: */ ! 204: tme_uint16_t tme_suncg2_cmap_raw[(1 << TME_SUNCG2_PLANE_MAX) * 3]; ! 205: ! 206: /* the cooked colormap: */ ! 207: tme_uint8_t tme_suncg2_cmap[(1 << TME_SUNCG2_PLANE_MAX) * 3]; ! 208: ! 209: /* if this is zero, the next CSR read will have the retrace bit set: */ ! 210: unsigned int tme_suncg2_cycle_retrace; ! 211: ! 212: /* if this is TME_SUNCG2_PLANE_MAX, we are displaying the pixmap, ! 213: else we are displaying this plane's bitmap: */ ! 214: unsigned int tme_suncg2_bitmap_mode_plane; ! 215: ! 216: /* state flags: */ ! 217: unsigned int tme_suncg2_flags; ! 218: ! 219: /* any outstanding TLBs: */ ! 220: struct tme_bus_tlb *tme_suncg2_tlbs[4]; ! 221: unsigned int tme_suncg2_tlb_head; ! 222: ! 223: /* a rasterop buffered SRC value: */ ! 224: tme_uint16_t tme_suncg2_rop_src_buffer; ! 225: }; ! 226: ! 227: /* globals: */ ! 228: ! 229: #ifndef TME_NO_LOG ! 230: static const char *_tme_suncg2_ropc_regs[] = ! 231: { "dest", ! 232: "source1", ! 233: "source2", ! 234: "pattern", ! 235: "mask1", ! 236: "mask2", ! 237: "ena_shift", ! 238: "op", ! 239: "width", ! 240: "opcount", ! 241: "decoderout", ! 242: "x11", ! 243: "x12", ! 244: "x13", ! 245: "x14", ! 246: "x15", ! 247: }; ! 248: #endif /* !TME_NO_LOG */ ! 249: ! 250: /* this invalidates any outstanding TLBs: */ ! 251: static void ! 252: _tme_suncg2_tlb_invalidate(struct tme_suncg2 *suncg2, struct tme_bus_tlb *tlb_valid) ! 253: { ! 254: unsigned int tlb_i; ! 255: struct tme_bus_tlb *tlb; ! 256: ! 257: if (tlb_valid != NULL) { ! 258: tlb_valid = TME_ATOMIC_READ(struct tme_bus_tlb *, ! 259: tlb_valid->tme_bus_tlb_backing_reservation); ! 260: } ! 261: ! 262: for (tlb_i = 0; tlb_i < TME_ARRAY_ELS(suncg2->tme_suncg2_tlbs); tlb_i++) { ! 263: tlb = suncg2->tme_suncg2_tlbs[tlb_i]; ! 264: suncg2->tme_suncg2_tlbs[tlb_i] = NULL; ! 265: if (tlb != NULL ! 266: && tlb != tlb_valid) { ! 267: tme_bus_tlb_invalidate(tlb); ! 268: } ! 269: } ! 270: } ! 271: ! 272: /* this adds an outstanding TLB: */ ! 273: static void ! 274: _tme_suncg2_tlb_add(struct tme_suncg2 *suncg2, struct tme_bus_tlb *tlb_valid) ! 275: { ! 276: struct tme_bus_tlb *tlb; ! 277: ! 278: tlb_valid = TME_ATOMIC_READ(struct tme_bus_tlb *, ! 279: tlb_valid->tme_bus_tlb_backing_reservation); ! 280: ! 281: tlb = suncg2->tme_suncg2_tlbs[suncg2->tme_suncg2_tlb_head % TME_ARRAY_ELS(suncg2->tme_suncg2_tlbs)]; ! 282: if (tlb != NULL ! 283: && tlb != tlb_valid) { ! 284: tme_bus_tlb_invalidate(tlb); ! 285: } ! 286: suncg2->tme_suncg2_tlbs[suncg2->tme_suncg2_tlb_head % TME_ARRAY_ELS(suncg2->tme_suncg2_tlbs)] = tlb_valid; ! 287: suncg2->tme_suncg2_tlb_head++; ! 288: } ! 289: ! 290: /* this validates the bitmaps: */ ! 291: static void ! 292: _tme_suncg2_validate_bitmaps(struct tme_suncg2 *suncg2, struct tme_bus_tlb *tlb) ! 293: { ! 294: #if SIZEOF_LONG > 4 ! 295: const unsigned long *pixmap_pointer; ! 296: unsigned long pixmap; ! 297: #else /* SIZEOF_LONG <= 4 */ ! 298: const tme_uint32_t *pixmap_pointer; ! 299: tme_uint32_t pixmap; ! 300: #endif /* SIZEOF_LONG <= 4 */ ! 301: tme_uint32_t pixmap_resid; ! 302: tme_uint32_t bitmaps_lo; ! 303: tme_uint32_t bitmaps_hi; ! 304: tme_uint8_t *bitmap_pointer; ! 305: ! 306: /* if the bitmaps are invalid: */ ! 307: if (suncg2->tme_suncg2_flags & TME_SUNCG2_FLAG_INVALID_BITMAPS) { ! 308: ! 309: /* the pixmap must not be invalid: */ ! 310: assert (!(suncg2->tme_suncg2_flags & TME_SUNCG2_FLAG_INVALID_PIXMAP)); ! 311: ! 312: /* invalidate any outstanding TLBs: */ ! 313: _tme_suncg2_tlb_invalidate(suncg2, tlb); ! 314: ! 315: /* if we are displaying the pixmap: */ ! 316: if (suncg2->tme_suncg2_bitmap_mode_plane == TME_SUNCG2_PLANE_MAX) { ! 317: ! 318: /* if the displayed memory is not invalid: */ ! 319: if (!(suncg2->tme_suncg2_flags & TME_SUNCG2_FLAG_INVALID_DISPLAYED)) { ! 320: ! 321: /* copy the displayed memory back into the pixmap: */ ! 322: memcpy((suncg2->tme_suncg2_raw_memory ! 323: + TME_SUNCG2_REG_PIXMAP), ! 324: suncg2->tme_suncg2_displayed_memory, ! 325: TME_SUNCG2_SIZ_PIXMAP); ! 326: } ! 327: } ! 328: ! 329: /* otherwise, we're displaying a bitmap: */ ! 330: else { ! 331: ! 332: /* the displayed memory must be invalid: */ ! 333: assert (suncg2->tme_suncg2_flags & TME_SUNCG2_FLAG_INVALID_DISPLAYED); ! 334: } ! 335: ! 336: /* start in the pixmap: */ ! 337: pixmap_pointer = (tme_uint32_t *) (suncg2->tme_suncg2_raw_memory + TME_SUNCG2_REG_PIXMAP); ! 338: pixmap_resid = TME_SUNCG2_SIZ_PIXMAP; ! 339: pixmap = 0; ! 340: ! 341: /* start in the bitmaps: */ ! 342: bitmap_pointer = suncg2->tme_suncg2_raw_memory + TME_SUNCG2_REG_BITMAP(0); ! 343: bitmaps_lo = 0; ! 344: bitmaps_hi = 0; ! 345: ! 346: /* do the translation: */ ! 347: do { ! 348: ! 349: /* if the pixmap data is empty, reload it: */ ! 350: if (__tme_predict_false((pixmap_resid % sizeof(pixmap)) == 0)) { ! 351: pixmap = *(pixmap_pointer++); ! 352: pixmap = tme_betoh_u32(pixmap); ! 353: } ! 354: ! 355: /* translate another pixel's bits into the bitmaps: */ ! 356: bitmaps_lo >>= 1; ! 357: if (pixmap & TME_BIT(0)) bitmaps_lo |= 0x00000080; ! 358: if (pixmap & TME_BIT(1)) bitmaps_lo |= 0x00008000; ! 359: if (pixmap & TME_BIT(2)) bitmaps_lo |= 0x00800000; ! 360: if (pixmap & TME_BIT(3)) bitmaps_lo |= 0x80000000; ! 361: bitmaps_hi >>= 1; ! 362: if (pixmap & TME_BIT(4)) bitmaps_hi |= 0x00000080; ! 363: if (pixmap & TME_BIT(5)) bitmaps_hi |= 0x00008000; ! 364: if (pixmap & TME_BIT(6)) bitmaps_hi |= 0x00800000; ! 365: if (pixmap & TME_BIT(7)) bitmaps_hi |= 0x80000000; ! 366: ! 367: /* we have translated another pixel: */ ! 368: pixmap >>= 8; ! 369: pixmap_resid--; ! 370: ! 371: /* after every eight pixels, we have another eight bytes of bitmap ! 372: data to write out: */ ! 373: if (__tme_predict_false((pixmap_resid % 8) == 0)) { ! 374: bitmap_pointer[TME_SUNCG2_SIZ_BITMAP * 0] = TME_FIELD_MASK_EXTRACTU(bitmaps_lo, 0x000000ff); ! 375: bitmap_pointer[TME_SUNCG2_SIZ_BITMAP * 1] = TME_FIELD_MASK_EXTRACTU(bitmaps_lo, 0x0000ff00); ! 376: bitmap_pointer[TME_SUNCG2_SIZ_BITMAP * 2] = TME_FIELD_MASK_EXTRACTU(bitmaps_lo, 0x00ff0000); ! 377: bitmap_pointer[TME_SUNCG2_SIZ_BITMAP * 3] = TME_FIELD_MASK_EXTRACTU(bitmaps_lo, 0xff000000); ! 378: bitmaps_lo = 0; ! 379: bitmap_pointer[TME_SUNCG2_SIZ_BITMAP * 4] = TME_FIELD_MASK_EXTRACTU(bitmaps_hi, 0x000000ff); ! 380: bitmap_pointer[TME_SUNCG2_SIZ_BITMAP * 5] = TME_FIELD_MASK_EXTRACTU(bitmaps_hi, 0x0000ff00); ! 381: bitmap_pointer[TME_SUNCG2_SIZ_BITMAP * 6] = TME_FIELD_MASK_EXTRACTU(bitmaps_hi, 0x00ff0000); ! 382: bitmap_pointer[TME_SUNCG2_SIZ_BITMAP * 7] = TME_FIELD_MASK_EXTRACTU(bitmaps_hi, 0xff000000); ! 383: bitmaps_hi = 0; ! 384: bitmap_pointer++; ! 385: } ! 386: ! 387: /* loop while we have pixmap bytes remaining: */ ! 388: } while (pixmap_resid > 0); ! 389: ! 390: /* the bitmaps are no longer invalid: */ ! 391: suncg2->tme_suncg2_flags &= ~TME_SUNCG2_FLAG_INVALID_BITMAPS; ! 392: } ! 393: ! 394: /* otherwise, the bitmaps are valid: */ ! 395: else { ! 396: ! 397: /* if our caller needs the actual raw bitmap memory valid ! 398: (indicated by tlb == NULL): */ ! 399: if (tlb == NULL) { ! 400: ! 401: /* invalidate any outstanding TLBs: */ ! 402: _tme_suncg2_tlb_invalidate(suncg2, NULL); ! 403: ! 404: /* if we're displaying a bitmap: */ ! 405: if (suncg2->tme_suncg2_bitmap_mode_plane != TME_SUNCG2_PLANE_MAX) { ! 406: ! 407: /* if the displayed memory is not invalid: */ ! 408: if (!(suncg2->tme_suncg2_flags & TME_SUNCG2_FLAG_INVALID_DISPLAYED)) { ! 409: ! 410: /* copy the displayed memory back into the bitmap: */ ! 411: memcpy((suncg2->tme_suncg2_raw_memory ! 412: + TME_SUNCG2_REG_BITMAP(suncg2->tme_suncg2_bitmap_mode_plane)), ! 413: suncg2->tme_suncg2_displayed_memory, ! 414: TME_SUNCG2_SIZ_BITMAP); ! 415: } ! 416: } ! 417: } ! 418: } ! 419: } ! 420: ! 421: /* this validates the pixmap: */ ! 422: static void ! 423: _tme_suncg2_validate_pixmap(struct tme_suncg2 *suncg2, struct tme_bus_tlb *tlb) ! 424: { ! 425: #if SIZEOF_LONG > 4 ! 426: unsigned long *pixmap_pointer; ! 427: unsigned long pixmap; ! 428: #else /* SIZEOF_LONG <= 4 */ ! 429: tme_uint32_t *pixmap_pointer; ! 430: tme_uint32_t pixmap; ! 431: #endif /* SIZEOF_LONG <= 4 */ ! 432: tme_uint32_t pixmap_resid; ! 433: tme_uint32_t bitmaps_lo; ! 434: tme_uint32_t bitmaps_hi; ! 435: const tme_uint8_t *bitmap_pointer; ! 436: ! 437: /* if the pixmap is invalid: */ ! 438: if (suncg2->tme_suncg2_flags & TME_SUNCG2_FLAG_INVALID_PIXMAP) { ! 439: ! 440: /* the bitmaps must not be invalid: */ ! 441: assert (!(suncg2->tme_suncg2_flags & TME_SUNCG2_FLAG_INVALID_BITMAPS)); ! 442: ! 443: /* invalidate any outstanding TLBs: */ ! 444: _tme_suncg2_tlb_invalidate(suncg2, tlb); ! 445: ! 446: /* if we are displaying a bitmap: */ ! 447: if (suncg2->tme_suncg2_bitmap_mode_plane != TME_SUNCG2_PLANE_MAX) { ! 448: ! 449: /* if the displayed memory is not invalid: */ ! 450: if (!(suncg2->tme_suncg2_flags & TME_SUNCG2_FLAG_INVALID_DISPLAYED)) { ! 451: ! 452: /* copy the displayed memory back into the bitmap: */ ! 453: memcpy((suncg2->tme_suncg2_raw_memory ! 454: + TME_SUNCG2_REG_BITMAP(suncg2->tme_suncg2_bitmap_mode_plane)), ! 455: suncg2->tme_suncg2_displayed_memory, ! 456: TME_SUNCG2_SIZ_BITMAP); ! 457: } ! 458: } ! 459: ! 460: /* otherwise, we're displaying the pixmap: */ ! 461: else { ! 462: ! 463: /* the displayed memory must be invalid: */ ! 464: assert (suncg2->tme_suncg2_flags & TME_SUNCG2_FLAG_INVALID_DISPLAYED); ! 465: } ! 466: ! 467: /* start in the pixmap: */ ! 468: pixmap_pointer = (tme_uint32_t *) (suncg2->tme_suncg2_raw_memory + TME_SUNCG2_REG_PIXMAP); ! 469: pixmap_resid = TME_SUNCG2_SIZ_PIXMAP; ! 470: pixmap = 0; ! 471: ! 472: /* start in the bitmaps: */ ! 473: bitmap_pointer = suncg2->tme_suncg2_raw_memory + TME_SUNCG2_REG_BITMAP(0); ! 474: bitmaps_lo = 0; ! 475: bitmaps_hi = 0; ! 476: ! 477: /* do the translation: */ ! 478: do { ! 479: ! 480: /* if the bitmap data is empty, reload it: */ ! 481: if (__tme_predict_false((pixmap_resid % 8) == 0)) { ! 482: bitmaps_lo ! 483: = ((((tme_uint32_t) bitmap_pointer[TME_SUNCG2_SIZ_BITMAP * 0]) << 0) ! 484: | (((tme_uint32_t) bitmap_pointer[TME_SUNCG2_SIZ_BITMAP * 1]) << 8) ! 485: | (((tme_uint32_t) bitmap_pointer[TME_SUNCG2_SIZ_BITMAP * 2]) << 16) ! 486: | (((tme_uint32_t) bitmap_pointer[TME_SUNCG2_SIZ_BITMAP * 3]) << 24)); ! 487: bitmaps_hi ! 488: = ((((tme_uint32_t) bitmap_pointer[TME_SUNCG2_SIZ_BITMAP * 4]) << 0) ! 489: | (((tme_uint32_t) bitmap_pointer[TME_SUNCG2_SIZ_BITMAP * 5]) << 8) ! 490: | (((tme_uint32_t) bitmap_pointer[TME_SUNCG2_SIZ_BITMAP * 6]) << 16) ! 491: | (((tme_uint32_t) bitmap_pointer[TME_SUNCG2_SIZ_BITMAP * 7]) << 24)); ! 492: bitmap_pointer++; ! 493: } ! 494: ! 495: /* we are about to translate another pixel: */ ! 496: pixmap <<= 8; ! 497: pixmap_resid--; ! 498: ! 499: /* translate another pixel's bits from the bitmaps: */ ! 500: if (bitmaps_lo & 0x00000080) pixmap |= TME_BIT(0); ! 501: if (bitmaps_lo & 0x00008000) pixmap |= TME_BIT(1); ! 502: if (bitmaps_lo & 0x00800000) pixmap |= TME_BIT(2); ! 503: if (bitmaps_lo & 0x80000000) pixmap |= TME_BIT(3); ! 504: bitmaps_lo <<= 1; ! 505: if (bitmaps_hi & 0x00000080) pixmap |= TME_BIT(4); ! 506: if (bitmaps_hi & 0x00008000) pixmap |= TME_BIT(5); ! 507: if (bitmaps_hi & 0x00800000) pixmap |= TME_BIT(6); ! 508: if (bitmaps_hi & 0x80000000) pixmap |= TME_BIT(7); ! 509: bitmaps_hi <<= 1; ! 510: ! 511: /* if the pixmap data is full, write it: */ ! 512: if (__tme_predict_false((pixmap_resid % sizeof(pixmap)) == 0)) { ! 513: *(pixmap_pointer++) = tme_htobe_u32(pixmap); ! 514: pixmap = 0; ! 515: } ! 516: ! 517: /* loop while we have pixmap bytes remaining: */ ! 518: } while (pixmap_resid > 0); ! 519: ! 520: /* the pixmap is no longer invalid, but the bitmaps are: */ ! 521: suncg2->tme_suncg2_flags &= ~TME_SUNCG2_FLAG_INVALID_PIXMAP; ! 522: } ! 523: ! 524: /* otherwise, the pixmap is valid: */ ! 525: else { ! 526: ! 527: /* if our caller needs the actual raw pixmap memory valid ! 528: (indicated by tlb == NULL): */ ! 529: if (tlb == NULL) { ! 530: ! 531: /* invalidate any outstanding TLBs: */ ! 532: _tme_suncg2_tlb_invalidate(suncg2, NULL); ! 533: ! 534: /* if we're displaying the pixmap: */ ! 535: if (suncg2->tme_suncg2_bitmap_mode_plane == TME_SUNCG2_PLANE_MAX) { ! 536: ! 537: /* if the displayed memory is not invalid: */ ! 538: if (!(suncg2->tme_suncg2_flags & TME_SUNCG2_FLAG_INVALID_DISPLAYED)) { ! 539: ! 540: /* copy the displayed memory back into the pixmap: */ ! 541: memcpy((suncg2->tme_suncg2_raw_memory ! 542: + TME_SUNCG2_REG_PIXMAP), ! 543: suncg2->tme_suncg2_displayed_memory, ! 544: TME_SUNCG2_SIZ_PIXMAP); ! 545: } ! 546: } ! 547: } ! 548: } ! 549: } ! 550: ! 551: /* this validates the displayed memory: */ ! 552: static void ! 553: _tme_suncg2_validate_displayed(struct tme_suncg2 *suncg2, struct tme_bus_tlb *tlb) ! 554: { ! 555: ! 556: /* if the displayed memory is invalid: */ ! 557: if (suncg2->tme_suncg2_flags & TME_SUNCG2_FLAG_INVALID_DISPLAYED) { ! 558: ! 559: /* if we're displaying the pixmap: */ ! 560: if (suncg2->tme_suncg2_bitmap_mode_plane == TME_SUNCG2_PLANE_MAX) { ! 561: ! 562: /* validate the pixmap: */ ! 563: _tme_suncg2_validate_pixmap(suncg2, tlb); ! 564: ! 565: /* copy the pixmap into the displayed memory: */ ! 566: memcpy(suncg2->tme_suncg2_displayed_memory, ! 567: (suncg2->tme_suncg2_raw_memory ! 568: + TME_SUNCG2_REG_PIXMAP), ! 569: TME_SUNCG2_SIZ_PIXMAP); ! 570: } ! 571: ! 572: /* otherwise, we're displaying a bitmap: */ ! 573: else { ! 574: ! 575: /* validate the bitmaps: */ ! 576: _tme_suncg2_validate_bitmaps(suncg2, tlb); ! 577: ! 578: /* copy the bitmap into the displayed memory: */ ! 579: memcpy(suncg2->tme_suncg2_displayed_memory, ! 580: (suncg2->tme_suncg2_raw_memory ! 581: + TME_SUNCG2_REG_BITMAP(suncg2->tme_suncg2_bitmap_mode_plane)), ! 582: TME_SUNCG2_SIZ_BITMAP); ! 583: } ! 584: ! 585: /* the displayed memory is no longer invalid: */ ! 586: suncg2->tme_suncg2_flags &= ~TME_SUNCG2_FLAG_INVALID_DISPLAYED; ! 587: } ! 588: } ! 589: ! 590: /* this handles a mode change callout: */ ! 591: static int ! 592: _tme_suncg2_mode_change(struct tme_suncg2 *suncg2) ! 593: { ! 594: struct tme_fb_connection *conn_fb_other; ! 595: struct tme_fb_connection *conn_fb; ! 596: unsigned int pixel_i; ! 597: unsigned int mono_mask; ! 598: tme_uint32_t color0; ! 599: tme_uint32_t color1; ! 600: tme_uint32_t color; ! 601: unsigned int bitmap_mode_plane; ! 602: unsigned int color_i; ! 603: int rc; ! 604: ! 605: /* this makes a color for a pixel: */ ! 606: #define _TME_SUNCG2_PIXEL_COLOR(pixel) \ ! 607: ((TME_SUNCG2_CMAP_VALUE(suncg2, pixel, TME_SUNCG2_REG_CMAP_G) << 0) \ ! 608: | (TME_SUNCG2_CMAP_VALUE(suncg2, pixel, TME_SUNCG2_REG_CMAP_R) << 8) \ ! 609: | (TME_SUNCG2_CMAP_VALUE(suncg2, pixel, TME_SUNCG2_REG_CMAP_B) << 16)) ! 610: ! 611: /* if we are to display a bitmap, the color for pixmap pixel zero ! 612: must be the color for bitmap pixel zero, and the color for pixmap ! 613: pixel 255 must be the color for bitmap pixel one: */ ! 614: color0 = _TME_SUNCG2_PIXEL_COLOR(0); ! 615: color1 = _TME_SUNCG2_PIXEL_COLOR(255); ! 616: ! 617: /* we don't know what the monochrome mask is yet: */ ! 618: mono_mask = 0xff; ! 619: ! 620: /* loop over the other pixels: */ ! 621: for (pixel_i = 1; pixel_i < 255; pixel_i++) { ! 622: ! 623: /* get the color for this pixel: */ ! 624: color = _TME_SUNCG2_PIXEL_COLOR(pixel_i); ! 625: ! 626: /* if this matches color0: */ ! 627: if (color == color0) { ! 628: ! 629: /* any set bits in this pixel number can't be in the monochrome ! 630: mask: */ ! 631: mono_mask &= ~pixel_i; ! 632: } ! 633: ! 634: /* else, if this matches color1: */ ! 635: else if (color == color1) { ! 636: ! 637: /* any clear bits in this pixel number can't be in the ! 638: monochrome mask: */ ! 639: mono_mask &= pixel_i; ! 640: } ! 641: ! 642: /* otherwise, this is some other color: */ ! 643: else { ! 644: ! 645: /* we can't be in bitmap mode: */ ! 646: mono_mask = 0; ! 647: break; ! 648: } ! 649: } ! 650: ! 651: /* if we completed the above loop, but our monochrome mask is zero, ! 652: the colors for all pixel values must be the same. while strange, ! 653: we tolerate this, and take the least significant bit as the ! 654: monochrome mask: */ ! 655: if (pixel_i == 255 ! 656: && mono_mask == 0) { ! 657: assert (color0 == color1); ! 658: mono_mask = 1; ! 659: } ! 660: ! 661: /* if the monochrome mask is zero, we must display the pixmap, else ! 662: we display the bitmap corresponding to the least significant set ! 663: bit in the monochrome mask: */ ! 664: if (mono_mask == 0) { ! 665: bitmap_mode_plane = TME_SUNCG2_PLANE_MAX; ! 666: } ! 667: else { ! 668: for (bitmap_mode_plane = 0; ! 669: (mono_mask & 1) == 0; ! 670: bitmap_mode_plane++, mono_mask >>= 1); ! 671: } ! 672: ! 673: #undef _TME_SUNCG2_PIXEL_COLOR ! 674: ! 675: /* get both sides of the framebuffer connection: */ ! 676: conn_fb_other = suncg2->tme_suncg2_fb_connection; ! 677: conn_fb = (struct tme_fb_connection *) conn_fb_other->tme_fb_connection.tme_connection_other; ! 678: ! 679: /* if we are displaying the pixmap: */ ! 680: if (bitmap_mode_plane == TME_SUNCG2_PLANE_MAX) { ! 681: ! 682: /* the pixmap is eight bits deep: */ ! 683: conn_fb->tme_fb_connection_depth = TME_SUNCG2_PLANE_MAX; ! 684: conn_fb->tme_fb_connection_bits_per_pixel = TME_SUNCG2_PLANE_MAX; ! 685: ! 686: /* recook the colormap: */ ! 687: for (color_i = 0; ! 688: color_i < TME_ARRAY_ELS(suncg2->tme_suncg2_cmap_raw); ! 689: color_i++) { ! 690: suncg2->tme_suncg2_cmap[color_i] = tme_betoh_u16(suncg2->tme_suncg2_cmap_raw[color_i]); ! 691: } ! 692: } ! 693: ! 694: /* otherwise, we can display a bitmap: */ ! 695: else { ! 696: ! 697: /* a bitmap is one bit deep: */ ! 698: conn_fb->tme_fb_connection_depth = 1; ! 699: conn_fb->tme_fb_connection_bits_per_pixel = 1; ! 700: ! 701: /* cook the monochrome colormap: */ ! 702: suncg2->tme_suncg2_cmap[TME_SUNCG2_CMAP_INDEX(0, TME_SUNCG2_REG_CMAP_G)] = TME_SUNCG2_CMAP_VALUE(suncg2, 0, TME_SUNCG2_REG_CMAP_G); ! 703: suncg2->tme_suncg2_cmap[TME_SUNCG2_CMAP_INDEX(0, TME_SUNCG2_REG_CMAP_R)] = TME_SUNCG2_CMAP_VALUE(suncg2, 0, TME_SUNCG2_REG_CMAP_R); ! 704: suncg2->tme_suncg2_cmap[TME_SUNCG2_CMAP_INDEX(0, TME_SUNCG2_REG_CMAP_B)] = TME_SUNCG2_CMAP_VALUE(suncg2, 0, TME_SUNCG2_REG_CMAP_B); ! 705: suncg2->tme_suncg2_cmap[TME_SUNCG2_CMAP_INDEX(1, TME_SUNCG2_REG_CMAP_G)] = TME_SUNCG2_CMAP_VALUE(suncg2, 255, TME_SUNCG2_REG_CMAP_G); ! 706: suncg2->tme_suncg2_cmap[TME_SUNCG2_CMAP_INDEX(1, TME_SUNCG2_REG_CMAP_R)] = TME_SUNCG2_CMAP_VALUE(suncg2, 255, TME_SUNCG2_REG_CMAP_R); ! 707: suncg2->tme_suncg2_cmap[TME_SUNCG2_CMAP_INDEX(1, TME_SUNCG2_REG_CMAP_B)] = TME_SUNCG2_CMAP_VALUE(suncg2, 255, TME_SUNCG2_REG_CMAP_B); ! 708: } ! 709: ! 710: /* if the display is changing: */ ! 711: if (bitmap_mode_plane != suncg2->tme_suncg2_bitmap_mode_plane) { ! 712: ! 713: /* log the change: */ ! 714: tme_log(&suncg2->tme_suncg2_element->tme_element_log_handle, ! 715: 100, TME_OK, ! 716: (&suncg2->tme_suncg2_element->tme_element_log_handle, ! 717: "display changing from plane %u to plane %u", ! 718: suncg2->tme_suncg2_bitmap_mode_plane, ! 719: bitmap_mode_plane)); ! 720: ! 721: /* if we were displaying the pixmap, validate the pixmap, else ! 722: validate the bitmaps, to copy the current displayed memory back ! 723: into the raw memory: */ ! 724: if (suncg2->tme_suncg2_bitmap_mode_plane == TME_SUNCG2_PLANE_MAX) { ! 725: _tme_suncg2_validate_pixmap(suncg2, NULL); ! 726: } ! 727: else { ! 728: _tme_suncg2_validate_bitmaps(suncg2, NULL); ! 729: } ! 730: ! 731: /* invalidate any outstanding TLBs: */ ! 732: _tme_suncg2_tlb_invalidate(suncg2, NULL); ! 733: ! 734: /* set the display: */ ! 735: suncg2->tme_suncg2_bitmap_mode_plane = bitmap_mode_plane; ! 736: ! 737: /* free any previously allocated memory: */ ! 738: if (suncg2->tme_suncg2_displayed_memory != NULL) { ! 739: tme_free(suncg2->tme_suncg2_displayed_memory); ! 740: } ! 741: ! 742: /* allocate memory for our framebuffer connection: */ ! 743: rc = tme_fb_xlat_alloc_src(conn_fb); ! 744: assert (rc == TME_OK); ! 745: suncg2->tme_suncg2_displayed_memory = conn_fb->tme_fb_connection_buffer; ! 746: ! 747: /* the displayed memory is now invalid: */ ! 748: suncg2->tme_suncg2_flags |= TME_SUNCG2_FLAG_INVALID_DISPLAYED; ! 749: } ! 750: ! 751: /* unlock the mutex: */ ! 752: tme_mutex_unlock(&suncg2->tme_suncg2_mutex); ! 753: ! 754: /* do the callout: */ ! 755: rc = (conn_fb_other != NULL ! 756: ? ((*conn_fb_other->tme_fb_connection_mode_change) ! 757: (conn_fb_other)) ! 758: : TME_OK); ! 759: ! 760: /* lock the mutex: */ ! 761: tme_mutex_lock(&suncg2->tme_suncg2_mutex); ! 762: ! 763: return (rc); ! 764: } ! 765: ! 766: /* the suncg2 callout function. it must be called with the mutex locked: */ ! 767: static void ! 768: _tme_suncg2_callout(struct tme_suncg2 *suncg2, int new_callouts) ! 769: { ! 770: int callouts, later_callouts; ! 771: int rc; ! 772: ! 773: /* add in any new callouts: */ ! 774: suncg2->tme_suncg2_callout_flags |= new_callouts; ! 775: ! 776: /* if this function is already running in another thread, simply ! 777: return now. the other thread will do our work: */ ! 778: if (suncg2->tme_suncg2_callout_flags ! 779: & TME_SUNCG2_CALLOUT_RUNNING) { ! 780: return; ! 781: } ! 782: ! 783: /* callouts are now running: */ ! 784: suncg2->tme_suncg2_callout_flags ! 785: |= TME_SUNCG2_CALLOUT_RUNNING; ! 786: ! 787: /* assume that we won't need any later callouts: */ ! 788: later_callouts = 0; ! 789: ! 790: /* loop while callouts are needed: */ ! 791: for (; ((callouts ! 792: = suncg2->tme_suncg2_callout_flags) ! 793: & TME_SUNCG2_CALLOUTS_MASK); ) { ! 794: ! 795: /* clear the needed callouts: */ ! 796: suncg2->tme_suncg2_callout_flags ! 797: = (callouts ! 798: & ~TME_SUNCG2_CALLOUTS_MASK); ! 799: callouts ! 800: &= TME_SUNCG2_CALLOUTS_MASK; ! 801: ! 802: /* if we need a mode change: */ ! 803: if (new_callouts & TME_SUNCG2_CALLOUT_MODE_CHANGE) { ! 804: ! 805: /* call out the mode change: */ ! 806: rc = _tme_suncg2_mode_change(suncg2); ! 807: ! 808: /* if the callout failed: */ ! 809: if (rc != TME_OK) { ! 810: ! 811: /* remember that this callout should be attempted again at ! 812: some later time: */ ! 813: later_callouts |= TME_SUNCG2_CALLOUT_MODE_CHANGE; ! 814: } ! 815: } ! 816: } ! 817: ! 818: /* put in any later callouts, and clear that callouts are running: */ ! 819: suncg2->tme_suncg2_callout_flags = later_callouts; ! 820: } ! 821: ! 822: /* the callout thread: */ ! 823: static void ! 824: _tme_suncg2_callout_thread(void *_suncg2) ! 825: { ! 826: struct tme_suncg2 *suncg2; ! 827: ! 828: /* recover our data structure: */ ! 829: suncg2 = _suncg2; ! 830: ! 831: /* lock the mutex: */ ! 832: tme_mutex_lock(&suncg2->tme_suncg2_mutex); ! 833: ! 834: /* the callout thread is no longer running: */ ! 835: suncg2->tme_suncg2_flags &= ~TME_SUNCG2_FLAG_CALLOUT_THREAD_RUNNING; ! 836: ! 837: /* make any callouts: */ ! 838: _tme_suncg2_callout(suncg2, 0); ! 839: ! 840: /* unlock the mutex: */ ! 841: tme_mutex_unlock(&suncg2->tme_suncg2_mutex); ! 842: } ! 843: ! 844: /* this is called before the framebuffer's display is updated: */ ! 845: static int ! 846: _tme_suncg2_update(struct tme_fb_connection *conn_fb) ! 847: { ! 848: struct tme_suncg2 *suncg2; ! 849: ! 850: /* recover our data structure: */ ! 851: suncg2 = conn_fb->tme_fb_connection.tme_connection_element->tme_element_private; ! 852: ! 853: /* lock the mutex: */ ! 854: tme_mutex_lock(&suncg2->tme_suncg2_mutex); ! 855: ! 856: /* validate the displayed memory: */ ! 857: _tme_suncg2_validate_displayed(suncg2, NULL); ! 858: ! 859: /* if we still need callouts, and the callout thread isn't running, ! 860: start it: */ ! 861: if ((suncg2->tme_suncg2_callout_flags & TME_SUNCG2_CALLOUTS_MASK) != 0 ! 862: && !(suncg2->tme_suncg2_flags & TME_SUNCG2_FLAG_CALLOUT_THREAD_RUNNING)) { ! 863: tme_thread_create(_tme_suncg2_callout_thread, suncg2); ! 864: suncg2->tme_suncg2_flags |= TME_SUNCG2_FLAG_CALLOUT_THREAD_RUNNING; ! 865: } ! 866: ! 867: /* unlock the mutex: */ ! 868: tme_mutex_unlock(&suncg2->tme_suncg2_mutex); ! 869: ! 870: return (TME_OK); ! 871: } ! 872: ! 873: /* the suncg2 displayed memory bus cycle handler: */ ! 874: static int ! 875: _tme_suncg2_bus_cycle_displayed(void *_suncg2, struct tme_bus_cycle *cycle_init) ! 876: { ! 877: struct tme_suncg2 *suncg2; ! 878: unsigned int plane_i; ! 879: tme_bus_addr_t address_first; ! 880: tme_bus_addr_t address_last; ! 881: ! 882: /* recover our data structure: */ ! 883: suncg2 = (struct tme_suncg2 *) _suncg2; ! 884: ! 885: /* lock the mutex: */ ! 886: tme_mutex_lock(&suncg2->tme_suncg2_mutex); ! 887: ! 888: /* if we're displaying the pixmap: */ ! 889: plane_i = suncg2->tme_suncg2_bitmap_mode_plane; ! 890: if (plane_i == TME_SUNCG2_PLANE_MAX) { ! 891: ! 892: /* the displayed memory is the pixmap memory: */ ! 893: address_first = TME_SUNCG2_REG_PIXMAP; ! 894: address_last = TME_SUNCG2_REG_PIXMAP + suncg2->tme_suncg2_pixel_count - 1; ! 895: } ! 896: ! 897: /* otherwise, we're in bitmap mode: */ ! 898: else { ! 899: ! 900: /* the displayed memory is the displayed bitmap memory: */ ! 901: address_first = TME_SUNCG2_REG_BITMAP(plane_i); ! 902: address_last = address_first + (suncg2->tme_suncg2_pixel_count / 8) - 1; ! 903: } ! 904: ! 905: /* run the cycle: */ ! 906: tme_bus_cycle_xfer_memory(cycle_init, ! 907: (suncg2->tme_suncg2_displayed_memory ! 908: - address_first), ! 909: address_last); ! 910: ! 911: /* unlock the mutex: */ ! 912: tme_mutex_unlock(&suncg2->tme_suncg2_mutex); ! 913: ! 914: /* no faults: */ ! 915: return (TME_OK); ! 916: } ! 917: ! 918: /* the suncg2 raw memory bus cycle handler: */ ! 919: static int ! 920: _tme_suncg2_bus_cycle_raw(void *_suncg2, struct tme_bus_cycle *cycle_init) ! 921: { ! 922: struct tme_suncg2 *suncg2; ! 923: ! 924: /* recover our data structure: */ ! 925: suncg2 = (struct tme_suncg2 *) _suncg2; ! 926: ! 927: /* lock the mutex: */ ! 928: tme_mutex_lock(&suncg2->tme_suncg2_mutex); ! 929: ! 930: /* run the cycle: */ ! 931: tme_bus_cycle_xfer_memory(cycle_init, ! 932: (suncg2->tme_suncg2_raw_memory ! 933: - TME_SUNCG2_REG_BITMAP(0)), ! 934: (TME_SUNCG2_REG_PIXMAP ! 935: + TME_SUNCG2_SIZ_PIXMAP ! 936: - 1)); ! 937: ! 938: /* unlock the mutex: */ ! 939: tme_mutex_unlock(&suncg2->tme_suncg2_mutex); ! 940: ! 941: /* no faults: */ ! 942: return (TME_OK); ! 943: } ! 944: ! 945: /* this catches unsupported rasterop configurations: */ ! 946: static void ! 947: _tme_suncg2_rop_unsupported(struct tme_suncg2 *suncg2) ! 948: { ! 949: /* nothing */ ! 950: } ! 951: ! 952: /* this does a raster op: */ ! 953: static tme_uint16_t ! 954: _tme_suncg2_rop_op(struct tme_suncg2 *suncg2, ! 955: unsigned int ropc_unit, ! 956: tme_uint16_t src, ! 957: tme_uint16_t dst) ! 958: { ! 959: switch ((tme_uint8_t) suncg2->tme_suncg2_ropc[ropc_unit].tme_suncg2_ropc_op) { ! 960: default: ! 961: _tme_suncg2_rop_unsupported(suncg2); ! 962: /* FALLTHROUGH */ ! 963: case (TME_SUNCG2_ROP_SRC): return (src); ! 964: case (TME_SUNCG2_ROP_NOT(TME_SUNCG2_ROP_DST)): return (~dst); ! 965: } ! 966: } ! 967: ! 968: /* the bus cycle handler for the rasterop data: */ ! 969: static int ! 970: _tme_suncg2_bus_cycle_rop_data(void *_suncg2, struct tme_bus_cycle *cycle_init) ! 971: { ! 972: struct tme_suncg2 *suncg2; ! 973: tme_uint32_t address; ! 974: tme_uint32_t address_aligned; ! 975: tme_uint16_t data; ! 976: tme_uint8_t src; ! 977: tme_uint8_t dst; ! 978: tme_uint8_t pixel; ! 979: int supported; ! 980: ! 981: /* recover our data structure: */ ! 982: suncg2 = (struct tme_suncg2 *) _suncg2; ! 983: ! 984: /* decode the address: */ ! 985: address ! 986: = (cycle_init->tme_bus_cycle_address ! 987: - TME_SUNCG2_REG_ROP_DATA); ! 988: address_aligned ! 989: = (address & (((tme_uint32_t) 0) - sizeof(tme_uint16_t))); ! 990: ! 991: /* assume that this access is unsupported: */ ! 992: supported = FALSE; ! 993: ! 994: /* lock the mutex: */ ! 995: tme_mutex_lock(&suncg2->tme_suncg2_mutex); ! 996: ! 997: /* if this is a read: */ ! 998: if (cycle_init->tme_bus_cycle_type == TME_BUS_CYCLE_READ) { ! 999: ! 1000: /* dispatch on the rop mode: */ ! 1001: switch (suncg2->tme_suncg2_csr & TME_SUNCG2_CSR_ROP_MODE_MASK) { ! 1002: ! 1003: default: ! 1004: _tme_suncg2_rop_unsupported(suncg2); ! 1005: data = 0; ! 1006: break; ! 1007: ! 1008: /* the single pixel, LD_SRC write, LD_DST write, mode: */ ! 1009: case TME_SUNCG2_CSR_ROP_MODE_SWWPIX: ! 1010: ! 1011: /* this mode has partial support: */ ! 1012: supported = TRUE; ! 1013: ! 1014: /* XXX FIXME does a load reset the state? */ ! 1015: ! 1016: /* just load two pixels from the pixmap: */ ! 1017: _tme_suncg2_validate_pixmap(suncg2, NULL); ! 1018: data = (suncg2->tme_suncg2_raw_memory[TME_SUNCG2_REG_PIXMAP + address_aligned] ! 1019: & ((tme_uint8_t) suncg2->tme_suncg2_plane_mask)); ! 1020: data = ((data << 8) ! 1021: | (suncg2->tme_suncg2_raw_memory[TME_SUNCG2_REG_PIXMAP + address_aligned + 1] ! 1022: & ((tme_uint8_t) suncg2->tme_suncg2_plane_mask))); ! 1023: break; ! 1024: } ! 1025: } ! 1026: ! 1027: /* do the bus cycle: */ ! 1028: tme_bus_cycle_xfer_reg(cycle_init, ! 1029: &data, ! 1030: TME_BUS16_LOG2); ! 1031: ! 1032: /* get the data: */ ! 1033: data = (((cycle_init->tme_bus_cycle_size == sizeof(tme_uint16_t) ! 1034: || (address % sizeof(tme_uint16_t)) == 1) ! 1035: ? data ! 1036: : (data >> 8)) ! 1037: & (0xffff >> (sizeof(tme_uint16_t) - cycle_init->tme_bus_cycle_size))); ! 1038: ! 1039: /* log the cycle: */ ! 1040: tme_log(&suncg2->tme_suncg2_element->tme_element_log_handle, ! 1041: 100, TME_OK, ! 1042: (&suncg2->tme_suncg2_element->tme_element_log_handle, ! 1043: ((cycle_init->tme_bus_cycle_size == sizeof(tme_uint16_t)) ! 1044: ? "rop data offset 0x%05x size 16bits %s 0x%04x" ! 1045: : "rop data offset 0x%05x size 8bits %s 0x%02x"), ! 1046: address, ! 1047: ((cycle_init->tme_bus_cycle_type == TME_BUS_CYCLE_WRITE) ! 1048: ? "<-" ! 1049: : "->"), ! 1050: data)); ! 1051: ! 1052: /* if this is a write: */ ! 1053: if (cycle_init->tme_bus_cycle_type == TME_BUS_CYCLE_WRITE) { ! 1054: ! 1055: /* dispatch on the rop mode: */ ! 1056: switch (suncg2->tme_suncg2_csr & TME_SUNCG2_CSR_ROP_MODE_MASK) { ! 1057: ! 1058: default: ! 1059: _tme_suncg2_rop_unsupported(suncg2); ! 1060: break; ! 1061: ! 1062: /* the single pixel, LD_SRC write, LD_DST write, mode: */ ! 1063: case TME_SUNCG2_CSR_ROP_MODE_SWWPIX: ! 1064: ! 1065: /* this mode has partial support: */ ! 1066: supported = TRUE; ! 1067: ! 1068: /* validate the pixmap: */ ! 1069: _tme_suncg2_validate_pixmap(suncg2, NULL); ! 1070: ! 1071: /* the current pixel value is DST: */ ! 1072: dst = suncg2->tme_suncg2_raw_memory[TME_SUNCG2_REG_PIXMAP + address]; ! 1073: ! 1074: /* the current source buffer is SRC: */ ! 1075: src = suncg2->tme_suncg2_rop_src_buffer; ! 1076: ! 1077: /* make the new pixel value: */ ! 1078: pixel = _tme_suncg2_rop_op(suncg2, ! 1079: 8, ! 1080: src, ! 1081: dst); ! 1082: ! 1083: /* store the pixel: */ ! 1084: suncg2->tme_suncg2_raw_memory[TME_SUNCG2_REG_PIXMAP + address] ! 1085: = ((dst & ((tme_uint8_t) (~suncg2->tme_suncg2_plane_mask))) ! 1086: | (pixel & ((tme_uint8_t) suncg2->tme_suncg2_plane_mask))); ! 1087: ! 1088: /* the displayed memory is now invalid: */ ! 1089: suncg2->tme_suncg2_flags |= TME_SUNCG2_FLAG_INVALID_DISPLAYED; ! 1090: ! 1091: /* load the source buffer: */ ! 1092: suncg2->tme_suncg2_rop_src_buffer = data; ! 1093: break; ! 1094: } ! 1095: } ! 1096: ! 1097: /* if this cycle was unsupported, abort: */ ! 1098: if (__tme_predict_false(!supported)) { ! 1099: _tme_suncg2_rop_unsupported(suncg2); ! 1100: } ! 1101: ! 1102: /* unlock the mutex: */ ! 1103: tme_mutex_unlock(&suncg2->tme_suncg2_mutex); ! 1104: ! 1105: /* no faults: */ ! 1106: return (TME_OK); ! 1107: } ! 1108: ! 1109: /* the bus cycle handler for the registers: */ ! 1110: static int ! 1111: _tme_suncg2_bus_cycle_regs(void *_suncg2, struct tme_bus_cycle *cycle_init) ! 1112: { ! 1113: struct tme_suncg2 *suncg2; ! 1114: tme_bus_addr_t address; ! 1115: tme_uint16_t *reg; ! 1116: tme_uint16_t reg_old, reg_new; ! 1117: tme_uint16_t junk; ! 1118: unsigned int ropc_unit; ! 1119: unsigned int ropc_unit_prime; ! 1120: unsigned int ropc_reg; ! 1121: int new_callouts; ! 1122: ! 1123: /* assume we won't need any new callouts: */ ! 1124: new_callouts = 0; ! 1125: ! 1126: /* recover our data structure: */ ! 1127: suncg2 = (struct tme_suncg2 *) _suncg2; ! 1128: ! 1129: /* coarsely decode the address: */ ! 1130: address ! 1131: = (cycle_init->tme_bus_cycle_address ! 1132: & (((tme_bus_addr_t) 0) ! 1133: - TME_SUNCG2_SIZ_REG_PAGE)); ! 1134: ! 1135: /* lock the mutex: */ ! 1136: tme_mutex_lock(&suncg2->tme_suncg2_mutex); ! 1137: ! 1138: /* the rasterop registers go from [TME_SUNCG2_REG_ROPC_UNIT(0)..TME_SUNCG2_REG_CSR): */ ! 1139: assert (address >= TME_SUNCG2_REG_ROPC_UNIT(0)); ! 1140: if (address < TME_SUNCG2_REG_CSR) { ! 1141: ! 1142: /* get the rasterop unit number: */ ! 1143: ropc_unit = (address - TME_SUNCG2_REG_ROPC_UNIT(0)) / TME_SUNCG2_SIZ_REG_PAGE; ! 1144: ! 1145: /* see if this is the prime registers: */ ! 1146: ropc_unit_prime ! 1147: = ((cycle_init->tme_bus_cycle_address & (TME_SUNCG2_SIZ_REG_PAGE / 2)) ! 1148: ? TME_SUNCG2_ROPC_PRIME ! 1149: : 0); ! 1150: ! 1151: /* get the register number: */ ! 1152: ropc_reg ! 1153: = ((cycle_init->tme_bus_cycle_address ! 1154: % sizeof(suncg2->tme_suncg2_ropc[ropc_unit_prime + ropc_unit])) ! 1155: / sizeof(tme_uint16_t)); ! 1156: ! 1157: /* get a pointer to the single register: */ ! 1158: reg = (((tme_uint16_t *) &suncg2->tme_suncg2_ropc[ropc_unit_prime + ropc_unit]) + ropc_reg); ! 1159: ! 1160: /* do the bus cycle: */ ! 1161: tme_bus_cycle_xfer_reg(cycle_init, ! 1162: reg, ! 1163: TME_BUS16_LOG2); ! 1164: ! 1165: #ifndef TME_NO_LOG ! 1166: /* log the transfer: */ ! 1167: tme_log(&suncg2->tme_suncg2_element->tme_element_log_handle, ! 1168: 100, TME_OK, ! 1169: (&suncg2->tme_suncg2_element->tme_element_log_handle, ! 1170: "ropc unit %u%s reg %s %s 0x%04x", ! 1171: ropc_unit, ! 1172: (ropc_unit_prime ! 1173: ? " PRIME" ! 1174: : ""), ! 1175: _tme_suncg2_ropc_regs[ropc_reg], ! 1176: ((cycle_init->tme_bus_cycle_type == TME_BUS_CYCLE_WRITE) ! 1177: ? "<-" ! 1178: : "->"), ! 1179: *reg)); ! 1180: #endif /* !TME_NO_LOG */ ! 1181: } ! 1182: ! 1183: /* the CSR is the entire page at TME_SUNCG2_REG_CSR: */ ! 1184: else if (address == TME_SUNCG2_REG_CSR) { ! 1185: ! 1186: /* if this is a read: */ ! 1187: if ((cycle_init->tme_bus_cycle_type & TME_BUS_CYCLE_READ) != 0) { ! 1188: ! 1189: /* if it's time to set the retrace bit, set it: */ ! 1190: if (suncg2->tme_suncg2_cycle_retrace-- == 0) { ! 1191: suncg2->tme_suncg2_csr |= TME_SUNCG2_CSR_RETRACE; ! 1192: suncg2->tme_suncg2_cycle_retrace = TME_SUNCG2_CYCLE_RETRACE; ! 1193: } ! 1194: ! 1195: /* otherwise, clear it: */ ! 1196: else { ! 1197: suncg2->tme_suncg2_csr &= ~TME_SUNCG2_CSR_RETRACE; ! 1198: } ! 1199: } ! 1200: ! 1201: /* do the bus cycle: */ ! 1202: reg_old = suncg2->tme_suncg2_csr; ! 1203: tme_bus_cycle_xfer_reg(cycle_init, ! 1204: &suncg2->tme_suncg2_csr, ! 1205: TME_BUS16_LOG2); ! 1206: reg_new = suncg2->tme_suncg2_csr; ! 1207: ! 1208: /* put back the unchanging bits: */ ! 1209: reg_new ! 1210: = ((reg_new ! 1211: & ~(TME_SUNCG2_CSR_INT_ACTIVE ! 1212: | TME_SUNCG2_CSR_RETRACE ! 1213: | 0xff00)) ! 1214: | (reg_old ! 1215: & (TME_SUNCG2_CSR_INT_ACTIVE ! 1216: | TME_SUNCG2_CSR_RETRACE ! 1217: | 0xff00))); ! 1218: suncg2->tme_suncg2_csr = reg_new; ! 1219: ! 1220: /* log the transfer: */ ! 1221: tme_log(&suncg2->tme_suncg2_element->tme_element_log_handle, ! 1222: 100, TME_OK, ! 1223: (&suncg2->tme_suncg2_element->tme_element_log_handle, ! 1224: "csr %s 0x%04x", ! 1225: ((cycle_init->tme_bus_cycle_type == TME_BUS_CYCLE_WRITE) ! 1226: ? "<-" ! 1227: : "->"), ! 1228: reg_new)); ! 1229: ! 1230: /* we do not support these bits: */ ! 1231: if ((reg_new ! 1232: ^ reg_old) ! 1233: & TME_SUNCG2_CSR_INT_ENABLE) { ! 1234: abort(); ! 1235: } ! 1236: ! 1237: /* if the cmap update bit is transitioning from a zero to a one, ! 1238: we need a mode change: */ ! 1239: if ((reg_old & TME_SUNCG2_CSR_CMAP_UPDATE) == 0 ! 1240: && (reg_new & TME_SUNCG2_CSR_CMAP_UPDATE) != 0) { ! 1241: new_callouts |= TME_SUNCG2_CALLOUT_MODE_CHANGE; ! 1242: } ! 1243: } ! 1244: ! 1245: /* if this is the interrupt vector: */ ! 1246: else if (address == TME_SUNCG2_REG_INTVEC) { ! 1247: tme_bus_cycle_xfer_reg(cycle_init, ! 1248: &suncg2->tme_suncg2_intvec, ! 1249: TME_BUS16_LOG2); ! 1250: } ! 1251: ! 1252: /* if this is the plane mask: */ ! 1253: else if (address == TME_SUNCG2_REG_PLANE_MASK) { ! 1254: ! 1255: /* do the bus cycle: */ ! 1256: tme_bus_cycle_xfer_reg(cycle_init, ! 1257: &suncg2->tme_suncg2_plane_mask, ! 1258: TME_BUS16_LOG2); ! 1259: ! 1260: /* log the transfer: */ ! 1261: tme_log(&suncg2->tme_suncg2_element->tme_element_log_handle, ! 1262: 100, TME_OK, ! 1263: (&suncg2->tme_suncg2_element->tme_element_log_handle, ! 1264: "plane mask %s 0x%04x", ! 1265: ((cycle_init->tme_bus_cycle_type == TME_BUS_CYCLE_WRITE) ! 1266: ? "<-" ! 1267: : "->"), ! 1268: suncg2->tme_suncg2_plane_mask)); ! 1269: } ! 1270: ! 1271: /* XXX FIXME - the sun3 PROM zeroes the cg3 DMA base register, ! 1272: the cg3 double buffer register, the cg3 DMA width register, ! 1273: and the cg3 frame count registers: */ ! 1274: else if (address == TME_SUNCG2_REG_SUN3_DMA_BASE ! 1275: || address == TME_SUNCG2_REG_SUN3_DOUBLE_BUF ! 1276: || address == TME_SUNCG2_REG_SUN3_DMA_WIDTH ! 1277: || address == TME_SUNCG2_REG_SUN3_FRAME_COUNT) { ! 1278: tme_bus_cycle_xfer_reg(cycle_init, ! 1279: &junk, ! 1280: TME_BUS16_LOG2); ! 1281: } ! 1282: ! 1283: /* XXX FIXME - this is a partial implementation: */ ! 1284: else { ! 1285: abort(); ! 1286: } ! 1287: ! 1288: /* make any new callouts: */ ! 1289: _tme_suncg2_callout(suncg2, new_callouts); ! 1290: ! 1291: /* unlock the mutex: */ ! 1292: tme_mutex_unlock(&suncg2->tme_suncg2_mutex); ! 1293: ! 1294: /* no faults: */ ! 1295: return (TME_OK); ! 1296: } ! 1297: ! 1298: /* the bus cycle handler for the suncg2 colormap registers: */ ! 1299: static int ! 1300: _tme_suncg2_bus_cycle_cmap(void *_suncg2, struct tme_bus_cycle *cycle_init) ! 1301: { ! 1302: struct tme_suncg2 *suncg2; ! 1303: ! 1304: /* recover our data structure: */ ! 1305: suncg2 = (struct tme_suncg2 *) _suncg2; ! 1306: ! 1307: /* lock the mutex: */ ! 1308: tme_mutex_lock(&suncg2->tme_suncg2_mutex); ! 1309: ! 1310: /* run the cycle: */ ! 1311: tme_bus_cycle_xfer_memory(cycle_init, ! 1312: (((tme_uint8_t *) suncg2->tme_suncg2_cmap_raw) ! 1313: - TME_SUNCG2_REG_CMAP_R), ! 1314: TME_SUNCG2_SIZ_REGS - 1); ! 1315: ! 1316: /* if this is a write and colormap updates are enabled, we need to ! 1317: call out a mode change. we don't make the callout now, assuming ! 1318: that more writes to the colormap are coming soon. we will ! 1319: eventually make the callout when the framebuffer updates: */ ! 1320: if ((cycle_init->tme_bus_cycle_type & TME_BUS_CYCLE_WRITE) ! 1321: && (suncg2->tme_suncg2_csr ! 1322: & TME_SUNCG2_CSR_CMAP_UPDATE)) { ! 1323: suncg2->tme_suncg2_callout_flags |= TME_SUNCG2_CALLOUT_MODE_CHANGE; ! 1324: } ! 1325: ! 1326: /* unlock the mutex: */ ! 1327: tme_mutex_unlock(&suncg2->tme_suncg2_mutex); ! 1328: ! 1329: /* no faults: */ ! 1330: return (TME_OK); ! 1331: } ! 1332: ! 1333: /* the suncg2 TLB filler: */ ! 1334: static int ! 1335: _tme_suncg2_tlb_fill(void *_suncg2, struct tme_bus_tlb *tlb, ! 1336: tme_bus_addr_t address, unsigned int cycles) ! 1337: { ! 1338: struct tme_suncg2 *suncg2; ! 1339: tme_uint8_t *memory; ! 1340: tme_bus_addr_t address_first; ! 1341: tme_bus_addr_t address_last; ! 1342: ! 1343: /* recover our data structure: */ ! 1344: suncg2 = (struct tme_suncg2 *) _suncg2; ! 1345: ! 1346: /* initialize the TLB entry: */ ! 1347: tme_bus_tlb_initialize(tlb); ! 1348: ! 1349: /* the fast reading and writing rwlock: */ ! 1350: tlb->tme_bus_tlb_rwlock = &suncg2->tme_suncg2_rwlock; ! 1351: ! 1352: /* allow reading and writing: */ ! 1353: tlb->tme_bus_tlb_cycles_ok = TME_BUS_CYCLE_READ | TME_BUS_CYCLE_WRITE; ! 1354: ! 1355: /* our bus cycle handler private data: */ ! 1356: tlb->tme_bus_tlb_cycle_private = _suncg2; ! 1357: ! 1358: /* lock the mutex: */ ! 1359: tme_mutex_lock(&suncg2->tme_suncg2_mutex); ! 1360: ! 1361: /* we require a connection: */ ! 1362: assert (suncg2->tme_suncg2_fb_connection != NULL); ! 1363: assert (suncg2->tme_suncg2_displayed_memory != NULL); ! 1364: ! 1365: /* if this address falls in a bitmap: */ ! 1366: if ((TME_SUNCG2_REG_BITMAP(0) ! 1367: <= address) ! 1368: && (address ! 1369: < TME_SUNCG2_REG_BITMAP(TME_SUNCG2_PLANE_MAX))) { ! 1370: ! 1371: /* the cycle handler: */ ! 1372: tlb->tme_bus_tlb_cycle = _tme_suncg2_bus_cycle_raw; ! 1373: ! 1374: /* if we're displaying the pixmap: */ ! 1375: if (suncg2->tme_suncg2_bitmap_mode_plane == TME_SUNCG2_PLANE_MAX) { ! 1376: ! 1377: /* validate the bitmaps: */ ! 1378: _tme_suncg2_validate_bitmaps(suncg2, tlb); ! 1379: ! 1380: /* this TLB entry covers all of the bitmap memory: */ ! 1381: address_first = TME_SUNCG2_REG_BITMAP(0); ! 1382: address_last = TME_SUNCG2_REG_PIXMAP - 1; ! 1383: memory = suncg2->tme_suncg2_raw_memory + address_first; ! 1384: ! 1385: /* the displayed memory is now invalid: */ ! 1386: suncg2->tme_suncg2_flags |= TME_SUNCG2_FLAG_INVALID_DISPLAYED; ! 1387: } ! 1388: ! 1389: /* otherwise, we're displaying a bitmap: */ ! 1390: else { ! 1391: ! 1392: /* calculate the first and last addresses of the displayed ! 1393: memory: */ ! 1394: address_first = TME_SUNCG2_REG_BITMAP(suncg2->tme_suncg2_bitmap_mode_plane); ! 1395: address_last = address_first + (suncg2->tme_suncg2_pixel_count / 8) - 1; ! 1396: ! 1397: /* if this address is before the displayed memory, this TLB ! 1398: entry covers from the beginning of the bitmap memory up to ! 1399: the displayed memory: */ ! 1400: if (address < address_first) { ! 1401: address_last = address_first - 1; ! 1402: address_first = TME_SUNCG2_REG_BITMAP(0); ! 1403: memory = suncg2->tme_suncg2_raw_memory + address_first; ! 1404: ! 1405: /* validate the bitmaps: */ ! 1406: _tme_suncg2_validate_bitmaps(suncg2, tlb); ! 1407: } ! 1408: ! 1409: /* otherwise, if this address is after the displayed memory, ! 1410: this TLB entry covers from right after the displayed memory ! 1411: to the end of the bitmap memory: */ ! 1412: else if (address > address_last) { ! 1413: address_first = address_last + 1; ! 1414: address_last = TME_SUNCG2_REG_PIXMAP - 1; ! 1415: memory = suncg2->tme_suncg2_raw_memory + address_first; ! 1416: ! 1417: /* validate the bitmaps: */ ! 1418: _tme_suncg2_validate_bitmaps(suncg2, tlb); ! 1419: } ! 1420: ! 1421: /* otherwise, this address is in the displayed memory: */ ! 1422: else { ! 1423: memory = suncg2->tme_suncg2_displayed_memory; ! 1424: tlb->tme_bus_tlb_cycle = _tme_suncg2_bus_cycle_displayed; ! 1425: ! 1426: /* validate the displayed memory: */ ! 1427: _tme_suncg2_validate_displayed(suncg2, tlb); ! 1428: } ! 1429: } ! 1430: ! 1431: /* the address range: */ ! 1432: TME_ATOMIC_WRITE(tme_bus_addr_t, ! 1433: tlb->tme_bus_tlb_addr_first, ! 1434: address_first); ! 1435: TME_ATOMIC_WRITE(tme_bus_addr_t, ! 1436: tlb->tme_bus_tlb_addr_last, ! 1437: address_last); ! 1438: ! 1439: /* this TLB entry allows fast reading and fast writing: */ ! 1440: tlb->tme_bus_tlb_emulator_off_read = memory - address_first; ! 1441: tlb->tme_bus_tlb_emulator_off_write = memory - address_first; ! 1442: ! 1443: /* add this TLB entry: */ ! 1444: _tme_suncg2_tlb_add(suncg2, tlb); ! 1445: ! 1446: /* the pixmap is now invalid: */ ! 1447: suncg2->tme_suncg2_flags |= TME_SUNCG2_FLAG_INVALID_PIXMAP; ! 1448: } ! 1449: ! 1450: /* if this address falls in the pixmap: */ ! 1451: else if ((TME_SUNCG2_REG_PIXMAP ! 1452: <= address) ! 1453: && (address ! 1454: < (TME_SUNCG2_REG_PIXMAP + TME_SUNCG2_SIZ_PIXMAP))) { ! 1455: ! 1456: /* the cycle handler: */ ! 1457: tlb->tme_bus_tlb_cycle = _tme_suncg2_bus_cycle_raw; ! 1458: ! 1459: /* if we're displaying the pixmap: */ ! 1460: if (suncg2->tme_suncg2_bitmap_mode_plane == TME_SUNCG2_PLANE_MAX) { ! 1461: ! 1462: /* calculate the first and last addresses of the displayed memory: */ ! 1463: address_first = TME_SUNCG2_REG_PIXMAP; ! 1464: address_last = TME_SUNCG2_REG_PIXMAP + suncg2->tme_suncg2_pixel_count - 1; ! 1465: ! 1466: /* if this address is after the displayed memory, we're in the pad: */ ! 1467: if (address > address_last) { ! 1468: address_first = address_last + 1; ! 1469: address_last = TME_SUNCG2_REG_PIXMAP + TME_SUNCG2_SIZ_PIXMAP - 1; ! 1470: memory = suncg2->tme_suncg2_raw_memory + address_first; ! 1471: ! 1472: /* validate the pixmap: */ ! 1473: _tme_suncg2_validate_pixmap(suncg2, tlb); ! 1474: } ! 1475: ! 1476: /* otherwise, this address is in the displayed memory: */ ! 1477: else { ! 1478: memory = suncg2->tme_suncg2_displayed_memory; ! 1479: tlb->tme_bus_tlb_cycle = _tme_suncg2_bus_cycle_displayed; ! 1480: ! 1481: /* validate the displayed memory: */ ! 1482: _tme_suncg2_validate_displayed(suncg2, tlb); ! 1483: } ! 1484: } ! 1485: ! 1486: /* otherwise, we're displaying a bitmap: */ ! 1487: else { ! 1488: ! 1489: /* validate the pixmap: */ ! 1490: _tme_suncg2_validate_pixmap(suncg2, tlb); ! 1491: ! 1492: /* this TLB covers all of pixmap memory: */ ! 1493: address_first = TME_SUNCG2_REG_PIXMAP; ! 1494: address_last = TME_SUNCG2_REG_PIXMAP + TME_SUNCG2_SIZ_PIXMAP - 1; ! 1495: memory = suncg2->tme_suncg2_raw_memory + address_first; ! 1496: ! 1497: /* the displayed memory is now invalid: */ ! 1498: suncg2->tme_suncg2_flags |= TME_SUNCG2_FLAG_INVALID_DISPLAYED; ! 1499: } ! 1500: ! 1501: /* the address range: */ ! 1502: TME_ATOMIC_WRITE(tme_bus_addr_t, ! 1503: tlb->tme_bus_tlb_addr_first, ! 1504: address_first); ! 1505: TME_ATOMIC_WRITE(tme_bus_addr_t, ! 1506: tlb->tme_bus_tlb_addr_last, ! 1507: address_last); ! 1508: ! 1509: /* this TLB entry allows fast reading and fast writing: */ ! 1510: tlb->tme_bus_tlb_emulator_off_read = memory - address_first; ! 1511: tlb->tme_bus_tlb_emulator_off_write = memory - address_first; ! 1512: ! 1513: /* add this TLB entry: */ ! 1514: _tme_suncg2_tlb_add(suncg2, tlb); ! 1515: ! 1516: /* the bitmaps are now invalid: */ ! 1517: suncg2->tme_suncg2_flags |= TME_SUNCG2_FLAG_INVALID_BITMAPS; ! 1518: } ! 1519: ! 1520: /* if this address falls in the rasterop data: */ ! 1521: else if ((TME_SUNCG2_REG_ROP_DATA ! 1522: <= address) ! 1523: && (address ! 1524: < TME_SUNCG2_REG_ROPC_UNIT(0))) { ! 1525: ! 1526: /* the cycle handler: */ ! 1527: tlb->tme_bus_tlb_cycle = _tme_suncg2_bus_cycle_rop_data; ! 1528: ! 1529: /* this TLB entry covers this range: */ ! 1530: TME_ATOMIC_WRITE(tme_bus_addr_t, ! 1531: tlb->tme_bus_tlb_addr_first, ! 1532: TME_SUNCG2_REG_ROP_DATA); ! 1533: TME_ATOMIC_WRITE(tme_bus_addr_t, ! 1534: tlb->tme_bus_tlb_addr_last, ! 1535: (TME_SUNCG2_REG_ROPC_UNIT(0) ! 1536: - 1)); ! 1537: ! 1538: /* this TLB entry cannot allow fast reading or fast writing, since ! 1539: this is the rasterop data: */ ! 1540: } ! 1541: ! 1542: /* if this address falls in the registers: */ ! 1543: else if ((TME_SUNCG2_REG_ROPC_UNIT(0) ! 1544: <= address) ! 1545: && (address ! 1546: < TME_SUNCG2_REG_CMAP_R)) { ! 1547: ! 1548: /* the cycle handler: */ ! 1549: tlb->tme_bus_tlb_cycle = _tme_suncg2_bus_cycle_regs; ! 1550: ! 1551: /* this TLB entry covers this range: */ ! 1552: TME_ATOMIC_WRITE(tme_bus_addr_t, ! 1553: tlb->tme_bus_tlb_addr_first, ! 1554: TME_SUNCG2_REG_ROPC_UNIT(0)); ! 1555: TME_ATOMIC_WRITE(tme_bus_addr_t, ! 1556: tlb->tme_bus_tlb_addr_last, ! 1557: (TME_SUNCG2_REG_CMAP_R ! 1558: - 1)); ! 1559: ! 1560: /* this TLB entry cannot allow fast reading or fast writing, since ! 1561: these are registers: */ ! 1562: } ! 1563: ! 1564: /* if this address falls in the colormap registers: */ ! 1565: else if ((TME_SUNCG2_REG_CMAP_R ! 1566: <= address) ! 1567: && (address ! 1568: <= (TME_SUNCG2_SIZ_REGS ! 1569: - 1))) { ! 1570: ! 1571: /* the cycle handler: */ ! 1572: tlb->tme_bus_tlb_cycle = _tme_suncg2_bus_cycle_cmap; ! 1573: ! 1574: /* this TLB entry covers this range: */ ! 1575: TME_ATOMIC_WRITE(tme_bus_addr_t, ! 1576: tlb->tme_bus_tlb_addr_first, ! 1577: TME_SUNCG2_REG_CMAP_R); ! 1578: TME_ATOMIC_WRITE(tme_bus_addr_t, ! 1579: tlb->tme_bus_tlb_addr_last, ! 1580: TME_SUNCG2_SIZ_REGS - 1); ! 1581: ! 1582: /* this TLB entry allows fast reading: */ ! 1583: tlb->tme_bus_tlb_emulator_off_read ! 1584: = (((tme_uint8_t *) suncg2->tme_suncg2_cmap_raw) ! 1585: - TME_SUNCG2_REG_CMAP_R); ! 1586: } ! 1587: ! 1588: /* XXX FIXME - this is a partial implementation: */ ! 1589: else { ! 1590: abort(); ! 1591: } ! 1592: ! 1593: /* unlock the mutex: */ ! 1594: tme_mutex_unlock(&suncg2->tme_suncg2_mutex); ! 1595: ! 1596: return (TME_OK); ! 1597: } ! 1598: ! 1599: /* this makes a new framebuffer connection: */ ! 1600: static int ! 1601: _tme_suncg2_connection_make(struct tme_connection *conn, unsigned int state) ! 1602: { ! 1603: struct tme_suncg2 *suncg2; ! 1604: struct tme_fb_connection *conn_fb; ! 1605: struct tme_fb_connection *conn_fb_other; ! 1606: int rc; ! 1607: ! 1608: /* recover our data structures: */ ! 1609: suncg2 = conn->tme_connection_element->tme_element_private; ! 1610: conn_fb = (struct tme_fb_connection *) conn; ! 1611: conn_fb_other = (struct tme_fb_connection *) conn->tme_connection_other; ! 1612: ! 1613: /* both sides must be framebuffer connections: */ ! 1614: assert(conn->tme_connection_type == TME_CONNECTION_FRAMEBUFFER); ! 1615: assert(conn->tme_connection_other->tme_connection_type == TME_CONNECTION_FRAMEBUFFER); ! 1616: ! 1617: /* lock our mutex: */ ! 1618: tme_mutex_lock(&suncg2->tme_suncg2_mutex); ! 1619: ! 1620: /* once the connection is made, we know whether or not the other ! 1621: side of the connection is supplying specific memory that it wants ! 1622: us to use, or if we should allocate memory ourselves: */ ! 1623: if (conn_fb->tme_fb_connection_buffer == NULL) { ! 1624: rc = tme_fb_xlat_alloc_src(conn_fb); ! 1625: assert (rc == TME_OK); ! 1626: } ! 1627: suncg2->tme_suncg2_displayed_memory = conn_fb->tme_fb_connection_buffer; ! 1628: ! 1629: /* invalidate any outstanding TLBs: */ ! 1630: _tme_suncg2_tlb_invalidate(suncg2, NULL); ! 1631: ! 1632: /* the displayed memory is now invalid: */ ! 1633: suncg2->tme_suncg2_flags |= TME_SUNCG2_FLAG_INVALID_DISPLAYED; ! 1634: ! 1635: /* we're always set up to answer calls across the connection, so we ! 1636: only have to do work when the connection has gone full, namely ! 1637: taking the other side of the connection: */ ! 1638: if (state == TME_CONNECTION_FULL) { ! 1639: ! 1640: /* save our connection: */ ! 1641: suncg2->tme_suncg2_fb_connection = conn_fb_other; ! 1642: } ! 1643: ! 1644: /* unlock our mutex: */ ! 1645: tme_mutex_unlock(&suncg2->tme_suncg2_mutex); ! 1646: ! 1647: return (TME_OK); ! 1648: } ! 1649: ! 1650: /* this breaks a connection: */ ! 1651: static int ! 1652: _tme_suncg2_connection_break(struct tme_connection *conn, unsigned int state) ! 1653: { ! 1654: abort(); ! 1655: } ! 1656: ! 1657: /* this makes a new connection side for a suncg2: */ ! 1658: static int ! 1659: _tme_suncg2_connections_new(struct tme_element *element, ! 1660: const char * const *args, ! 1661: struct tme_connection **_conns, ! 1662: char **_output) ! 1663: { ! 1664: struct tme_suncg2 *suncg2; ! 1665: struct tme_fb_connection *conn_fb; ! 1666: struct tme_connection *conn; ! 1667: int rc; ! 1668: ! 1669: /* recover our data structure: */ ! 1670: suncg2 = (struct tme_suncg2 *) element->tme_element_private; ! 1671: ! 1672: /* make the generic bus device connection side: */ ! 1673: rc = tme_bus_device_connections_new(element, args, _conns, _output); ! 1674: if (rc != TME_OK) { ! 1675: return (rc); ! 1676: } ! 1677: ! 1678: /* if we don't have a framebuffer connection, make one: */ ! 1679: if (suncg2->tme_suncg2_fb_connection == NULL) { ! 1680: ! 1681: /* allocate the new framebuffer connection: */ ! 1682: conn_fb = tme_new0(struct tme_fb_connection, 1); ! 1683: conn = &conn_fb->tme_fb_connection; ! 1684: ! 1685: /* fill in the generic connection: */ ! 1686: conn->tme_connection_next = *_conns; ! 1687: conn->tme_connection_type = TME_CONNECTION_FRAMEBUFFER; ! 1688: conn->tme_connection_score = tme_fb_connection_score; ! 1689: conn->tme_connection_make = _tme_suncg2_connection_make; ! 1690: conn->tme_connection_break = _tme_suncg2_connection_break; ! 1691: ! 1692: /* fill in the framebuffer connection: */ ! 1693: conn_fb->tme_fb_connection_mode_change = NULL; ! 1694: conn_fb->tme_fb_connection_update = _tme_suncg2_update; ! 1695: ! 1696: /* height and width: */ ! 1697: conn_fb->tme_fb_connection_width = tme_sun_fb_p4_size_width(suncg2->tme_suncg2_size); ! 1698: conn_fb->tme_fb_connection_height = tme_sun_fb_p4_size_height(suncg2->tme_suncg2_size); ! 1699: ! 1700: /* we are color: */ ! 1701: conn_fb->tme_fb_connection_class = TME_FB_XLAT_CLASS_COLOR; ! 1702: conn_fb->tme_fb_connection_depth = TME_SUNCG2_PLANE_MAX; ! 1703: conn_fb->tme_fb_connection_bits_per_pixel = TME_SUNCG2_PLANE_MAX; ! 1704: ! 1705: /* we skip no pixels at the start of the scanline: */ ! 1706: conn_fb->tme_fb_connection_skipx = 0; ! 1707: ! 1708: /* we pad to 32-bit boundaries: */ ! 1709: conn_fb->tme_fb_connection_scanline_pad = 32; ! 1710: ! 1711: /* we are big-endian: */ ! 1712: conn_fb->tme_fb_connection_order = TME_ENDIAN_BIG; ! 1713: ! 1714: /* we don't allocate memory until the connection is made, in case ! 1715: the other side of the connection wants to provide us with a ! 1716: specific memory region to use (maybe we're on a system with a ! 1717: real cgtwo and we can write directly to its buffer): */ ! 1718: conn_fb->tme_fb_connection_buffer = NULL; ! 1719: ! 1720: /* our pixels don't have subfields: */ ! 1721: conn_fb->tme_fb_connection_mask_g = 0; ! 1722: conn_fb->tme_fb_connection_mask_r = 0; ! 1723: conn_fb->tme_fb_connection_mask_b = 0; ! 1724: ! 1725: /* intensities are eight bits and index mapped: */ ! 1726: conn_fb->tme_fb_connection_map_bits = (8 * sizeof(suncg2->tme_suncg2_cmap[0])); ! 1727: conn_fb->tme_fb_connection_map_g = &suncg2->tme_suncg2_cmap[TME_SUNCG2_CMAP_INDEX(0, TME_SUNCG2_REG_CMAP_G)]; ! 1728: conn_fb->tme_fb_connection_map_r = &suncg2->tme_suncg2_cmap[TME_SUNCG2_CMAP_INDEX(0, TME_SUNCG2_REG_CMAP_R)]; ! 1729: conn_fb->tme_fb_connection_map_b = &suncg2->tme_suncg2_cmap[TME_SUNCG2_CMAP_INDEX(0, TME_SUNCG2_REG_CMAP_B)]; ! 1730: ! 1731: /* return the connection side possibility: */ ! 1732: *_conns = conn; ! 1733: } ! 1734: ! 1735: /* done: */ ! 1736: return (TME_OK); ! 1737: } ! 1738: ! 1739: /* the new sun cgtwo function: */ ! 1740: int ! 1741: tme_sun_cgtwo(struct tme_element *element, const char * const *args, char **_output) ! 1742: { ! 1743: struct tme_suncg2 *suncg2; ! 1744: tme_uint32_t cg2_type; ! 1745: tme_uint32_t cg2_size; ! 1746: int arg_i; ! 1747: int usage; ! 1748: ! 1749: /* check our arguments: */ ! 1750: usage = 0; ! 1751: cg2_type = TME_SUNCG2_TYPE_NULL; ! 1752: cg2_size = TME_SUN_P4_SIZE_1152_900; ! 1753: arg_i = 1; ! 1754: for (;;) { ! 1755: ! 1756: /* the framebuffer type: */ ! 1757: if (TME_ARG_IS(args[arg_i + 0], "type")) { ! 1758: if (TME_ARG_IS(args[arg_i + 1], "sun3")) { ! 1759: cg2_type = TME_SUNCG2_TYPE_SUN3; ! 1760: } ! 1761: else { ! 1762: usage = TRUE; ! 1763: break; ! 1764: } ! 1765: arg_i += 2; ! 1766: } ! 1767: ! 1768: /* the framebuffer size: */ ! 1769: else if (TME_ARG_IS(args[arg_i + 0], "size")) { ! 1770: cg2_size = tme_sun_fb_p4_size(args[arg_i + 1]); ! 1771: if (cg2_size != TME_SUN_P4_SIZE_1152_900 ! 1772: && cg2_size != TME_SUN_P4_SIZE_1024_1024) { ! 1773: usage = TRUE; ! 1774: break; ! 1775: } ! 1776: arg_i += 2; ! 1777: } ! 1778: ! 1779: /* if we ran out of arguments: */ ! 1780: else if (args[arg_i] == NULL) { ! 1781: break; ! 1782: } ! 1783: ! 1784: /* otherwise this is a bad argument: */ ! 1785: else { ! 1786: tme_output_append_error(_output, ! 1787: "%s %s, ", ! 1788: args[arg_i], ! 1789: _("unexpected")); ! 1790: usage = TRUE; ! 1791: break; ! 1792: } ! 1793: } ! 1794: ! 1795: /* a cgtwo type must have been given: */ ! 1796: if (cg2_type == TME_SUNCG2_TYPE_NULL) { ! 1797: usage = TRUE; ! 1798: } ! 1799: ! 1800: if (usage) { ! 1801: tme_output_append_error(_output, ! 1802: "%s %s type sun3 [ size { 1152x900 | 1024x1024 } ]", ! 1803: _("usage:"), ! 1804: args[0]); ! 1805: return (EINVAL); ! 1806: } ! 1807: ! 1808: /* start the suncg2 structure: */ ! 1809: suncg2 = tme_new0(struct tme_suncg2, 1); ! 1810: suncg2->tme_suncg2_element = element; ! 1811: tme_mutex_init(&suncg2->tme_suncg2_mutex); ! 1812: tme_rwlock_init(&suncg2->tme_suncg2_rwlock); ! 1813: ! 1814: /* set the cgtwo type: */ ! 1815: suncg2->tme_suncg2_type = cg2_type; ! 1816: ! 1817: /* set the cgtwo size: */ ! 1818: suncg2->tme_suncg2_size = cg2_size; ! 1819: ! 1820: /* start displaying the pixmap: */ ! 1821: suncg2->tme_suncg2_bitmap_mode_plane = TME_SUNCG2_PLANE_MAX; ! 1822: ! 1823: /* set our initial CSR: */ ! 1824: suncg2->tme_suncg2_csr ! 1825: = (TME_SUNCG2_CSR_ENABLE_VIDEO ! 1826: | (cg2_size == TME_SUN_P4_SIZE_1024_1024 ! 1827: ? TME_SUNCG2_CSR_SIZE_1024_1024 ! 1828: : TME_SUNCG2_CSR_SIZE_1152_900)); ! 1829: ! 1830: /* if this is a sun3 cgtwo: */ ! 1831: if (cg2_type == TME_SUNCG2_TYPE_SUN3) { ! 1832: /* nothing to do */ ! 1833: } ! 1834: ! 1835: /* calculate the pixel count: */ ! 1836: suncg2->tme_suncg2_pixel_count ! 1837: = (tme_sun_fb_p4_size_width(cg2_size) ! 1838: * tme_sun_fb_p4_size_height(cg2_size)); ! 1839: ! 1840: /* allocate the raw memory: */ ! 1841: suncg2->tme_suncg2_raw_memory ! 1842: = tme_new0(tme_uint8_t, TME_SUNCG2_REG_PIXMAP + TME_SUNCG2_SIZ_PIXMAP); ! 1843: ! 1844: /* initialize our simple bus device descriptor: */ ! 1845: suncg2->tme_suncg2_device.tme_bus_device_element = element; ! 1846: suncg2->tme_suncg2_device.tme_bus_device_tlb_fill = _tme_suncg2_tlb_fill; ! 1847: suncg2->tme_suncg2_device.tme_bus_device_address_last = TME_SUNCG2_SIZ_REGS - 1; ! 1848: ! 1849: /* fill the element: */ ! 1850: element->tme_element_private = suncg2; ! 1851: element->tme_element_connections_new = _tme_suncg2_connections_new; ! 1852: ! 1853: return (TME_OK); ! 1854: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.