1 /* $Id: sun-cgtwo.c,v 1.8 2010/06/05 19:18:05 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.8 2010/06/05 19:18:05 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_token *tme_suncg2_tlb_tokens[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
_tme_suncg2_tlb_invalidate(struct tme_suncg2 * suncg2,struct tme_bus_tlb * tlb_valid)252 _tme_suncg2_tlb_invalidate(struct tme_suncg2 *suncg2, struct tme_bus_tlb *tlb_valid)
253 {
254   unsigned int tlb_i;
255   struct tme_token *token_valid;
256   struct tme_token *token;
257 
258   token_valid = NULL;
259   if (tlb_valid != NULL) {
260     token_valid = tlb_valid->tme_bus_tlb_token;
261   }
262 
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);
269     }
270   }
271 }
272 
273 /* this adds an outstanding TLB: */
274 static void
_tme_suncg2_tlb_add(struct tme_suncg2 * suncg2,struct tme_bus_tlb * tlb_valid)275 _tme_suncg2_tlb_add(struct tme_suncg2 *suncg2, struct tme_bus_tlb *tlb_valid)
276 {
277   struct tme_token *token_valid;
278   struct tme_token *token;
279 
280   token_valid = tlb_valid->tme_bus_tlb_token;
281 
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);
286   }
287   suncg2->tme_suncg2_tlb_tokens[suncg2->tme_suncg2_tlb_head % TME_ARRAY_ELS(suncg2->tme_suncg2_tlb_tokens)] = token_valid;
288   suncg2->tme_suncg2_tlb_head++;
289 }
290 
291 /* this validates the bitmaps: */
292 static void
_tme_suncg2_validate_bitmaps(struct tme_suncg2 * suncg2,struct tme_bus_tlb * tlb)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: */
333     pixmap_pointer = (tme_uint32_t *) (suncg2->tme_suncg2_raw_memory + TME_SUNCG2_REG_PIXMAP + TME_SUNCG2_SIZ_PIXMAP);
334     pixmap_resid = TME_SUNCG2_SIZ_PIXMAP;
335     pixmap = 0;
336 
337     /* start in the bitmaps: */
338     bitmap_pointer = suncg2->tme_suncg2_raw_memory + TME_SUNCG2_REG_BITMAP(0) + TME_SUNCG2_SIZ_BITMAP;
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)) {
347 	pixmap = *(--pixmap_pointer);
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)) {
370 	bitmap_pointer--;
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
_tme_suncg2_validate_pixmap(struct tme_suncg2 * suncg2,struct tme_bus_tlb * tlb)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
_tme_suncg2_validate_displayed(struct tme_suncg2 * suncg2,struct tme_bus_tlb * tlb)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
_tme_suncg2_mode_change(struct tme_suncg2 * suncg2)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: */
645   if (mono_mask == 0
646       || (mono_mask & (mono_mask - 1)) != 0) {
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
_tme_suncg2_callout(struct tme_suncg2 * suncg2,int new_callouts)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: */
785     if (callouts & TME_SUNCG2_CALLOUT_MODE_CHANGE) {
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
_tme_suncg2_callout_thread(void * _suncg2)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
_tme_suncg2_update(struct tme_fb_connection * conn_fb)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
_tme_suncg2_bus_cycle_displayed(void * _suncg2,struct tme_bus_cycle * cycle_init)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;
861   tme_bus_addr32_t address_first;
862   tme_bus_addr32_t address_last;
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
_tme_suncg2_bus_cycle_raw(void * _suncg2,struct tme_bus_cycle * cycle_init)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
_tme_suncg2_rop_unsupported(struct tme_suncg2 * suncg2)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
_tme_suncg2_rop_op(struct tme_suncg2 * suncg2,unsigned int ropc_unit,tme_uint16_t src,tme_uint16_t dst)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
_tme_suncg2_bus_cycle_rop_data(void * _suncg2,struct tme_bus_cycle * cycle_init)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
_tme_suncg2_bus_cycle_regs(void * _suncg2,struct tme_bus_cycle * cycle_init)1093 _tme_suncg2_bus_cycle_regs(void *_suncg2, struct tme_bus_cycle *cycle_init)
1094 {
1095   struct tme_suncg2 *suncg2;
1096   tme_bus_addr32_t address;
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
1114        & (((tme_bus_addr32_t) 0)
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
_tme_suncg2_bus_cycle_cmap(void * _suncg2,struct tme_bus_cycle * cycle_init)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
_tme_suncg2_tlb_fill(void * _suncg2,struct tme_bus_tlb * tlb,tme_bus_addr_t address_wider,unsigned int cycles)1317 _tme_suncg2_tlb_fill(void *_suncg2, struct tme_bus_tlb *tlb,
1318 		     tme_bus_addr_t address_wider, unsigned int cycles)
1319 {
1320   struct tme_suncg2 *suncg2;
1321   tme_uint8_t *memory;
1322   tme_bus_addr32_t address;
1323   tme_bus_addr32_t address_first;
1324   tme_bus_addr32_t address_last;
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 
1332   /* get the normal-width address: */
1333   address = address_wider;
1334   assert (address == address_wider);
1335 
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: */
1419     tlb->tme_bus_tlb_addr_first = address_first;
1420     tlb->tme_bus_tlb_addr_last = address_last;
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: */
1485     tlb->tme_bus_tlb_addr_first = address_first;
1486     tlb->tme_bus_tlb_addr_last = address_last;
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: */
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);
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: */
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);
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: */
1544     tlb->tme_bus_tlb_addr_first = TME_SUNCG2_REG_CMAP_R;
1545     tlb->tme_bus_tlb_addr_last = TME_SUNCG2_SIZ_REGS - 1;
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
_tme_suncg2_connection_make(struct tme_connection * conn,unsigned int state)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
_tme_suncg2_connection_break(struct tme_connection * conn,unsigned int state)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
_tme_suncg2_connections_new(struct tme_element * element,const char * const * args,struct tme_connection ** _conns,char ** _output)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: */
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);
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
tme_sun_cgtwo(struct tme_element * element,const char * const * args,char ** _output)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;
1717   cg2_size = TME_SUNFB_SIZE_1152_900;
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")) {
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) {
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
1791        | (cg2_size == TME_SUNFB_SIZE_1024_1024
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
1802     = (tme_sunfb_size_width(cg2_size)
1803        * tme_sunfb_size_height(cg2_size));
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 }
1820