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