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