|
|
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.