1 /* $Id: sun-fb.c,v 1.6 2010/06/05 19:19:01 fredette Exp $ */
2 
3 /* machine/sun/sun-fb.c - Sun framebuffer emulation support: */
4 
5 /*
6  * Copyright (c) 2004, 2006 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-fb.c,v 1.6 2010/06/05 19:19:01 fredette Exp $");
38 
39 /* includes: */
40 #include "sun-fb.h"
41 
42 /* macros: */
43 
44 /* P4 register framebuffer sizes: */
45 #define TME_SUNFB_P4_SIZE_MASK		(0x0f000000)
46 #define  TME_SUNFB_P4_SIZE_1600_1280	(0x00000000)
47 #define  TME_SUNFB_P4_SIZE_1152_900	(0x01000000)
48 #define  TME_SUNFB_P4_SIZE_1024_1024	(0x02000000)
49 #define  TME_SUNFB_P4_SIZE_1280_1024	(0x03000000)
50 #define  TME_SUNFB_P4_SIZE_1440_1440	(0x04000000)
51 #define  TME_SUNFB_P4_SIZE_640_480	(0x05000000)
52 
53 /* P4 register bits: */
54 					/* 0x00000080 is the diagnostic bit (?) */
55 					/* 0x00000040 is the readback bit (?) */
56 #define TME_SUNFB_P4_REG_VIDEO_ENABLE	(0x00000020)
57 #define TME_SUNFB_P4_REG_SYNC_RAMDAC	(0x00000010)
58 #define TME_SUNFB_P4_REG_IN_VTRACE	(0x00000008)
59 #define TME_SUNFB_P4_REG_INT_ACTIVE	(0x00000004)
60 #define TME_SUNFB_P4_REG_INT_RESET	(0x00000004)
61 #define TME_SUNFB_P4_REG_ENABLE_INT	(0x00000002)
62 #define TME_SUNFB_P4_REG_IN_VTRACE_1H	(0x00000001)
63 #define TME_SUNFB_P4_REG_RESET		(0x00000001)
64 
65 /* P4 register read-only bits: */
66 #define TME_SUNFB_P4_RO_MASK		(TME_SUNFB_P4_ID_MASK \
67 					 | TME_SUNFB_P4_SIZE_MASK \
68 					 | TME_SUNFB_P4_REG_IN_VTRACE \
69 					 | TME_SUNFB_P4_REG_INT_ACTIVE \
70 					 | TME_SUNFB_P4_REG_IN_VTRACE_1H)
71 
72 /* S4 register offsets: */
73 #define TME_SUNFB_S4_REG_BT458_ADDRESS	(0)
74 #define TME_SUNFB_S4_REG_BT458_CMAP	(4)
75 #define TME_SUNFB_S4_REG_BT458_CONTROL	(8)
76 #define TME_SUNFB_S4_REG_BT458_OMAP	(12)
77 #define TME_SUNFB_S4_SIZ_BT458		(16)
78 #define TME_SUNFB_S4_SIZ_REGS		(32)
79 #define TME_SUNFB_S4_REG(x)				\
80   (TME_SUNFB_S4_SIZ_BT458				\
81    + (&((struct tme_sunfb *) 0)->tme_sunfb_s4_regs.x	\
82       - &((struct tme_sunfb *) 0)->tme_sunfb_s4_regs.tme_sunfb_s4_regs_first))
83 
84 /* S4 control register bits: */
85 #define TME_SUNFB_S4_CONTROL_INT_ENABLE		(0x80)
86 #define TME_SUNFB_S4_CONTROL_VIDEO_ENABLE	(0x40)
87 
88 /* S4 status register bits: */
89 #define TME_SUNFB_S4_STATUS_INT_PENDING		(0x80)
90 #define TME_SUNFB_S4_STATUS_SIZE_MASK		(0x70)
91 #define  TME_SUNFB_S4_STATUS_SIZE_1024_768	 (0x10)
92 #define  TME_SUNFB_S4_STATUS_SIZE_1152_900	 (0x30)
93 #define  TME_SUNFB_S4_STATUS_SIZE_1280_1024	 (0x40)
94 #define  TME_SUNFB_S4_STATUS_SIZE_1600_1280	 (0x50)
95 #define TME_SUNFB_S4_STATUS_ID_MASK		(0x0f)
96 #define  TME_SUNFB_S4_STATUS_ID_COLOR		 (0x01)
97 #define  TME_SUNFB_S4_STATUS_ID_MONO		 (0x02)
98 #define  TME_SUNFB_S4_STATUS_ID_MONO_ECL	 (0x03)
99 
100 /* these evaluate to nonzero for different kinds of framebuffers: */
101 #define _TME_SUNFB_IS_BWTWO(sunfb)	((sunfb)->tme_sunfb_class == TME_FB_XLAT_CLASS_MONOCHROME)
102 #define _TME_SUNFB_IS_P4(sunfb)		((sunfb)->tme_sunfb_bus_handler_regs == tme_sunfb_bus_cycle_p4)
103 #define _TME_SUNFB_IS_S4(sunfb)		((sunfb)->tme_sunfb_bus_handler_regs == tme_sunfb_bus_cycle_s4)
104 #define _TME_SUNFB_HAS_BT458(sunfb)	((sunfb)->tme_sunfb_depth == 8)
105 
106 /* we fill writable TLB entries for framebuffer memory for this many
107    bytes at a time: */
108 #define TME_SUNFB_UPDATE_SIZE		(1024)
109 
110 #if 0
111 #define TME_SUNFB_DEBUG
112 #endif
113 
114 /* this returns the sunfb size value for the given resolution: */
115 tme_uint32_t
tme_sunfb_size(const char * size)116 tme_sunfb_size(const char *size)
117 {
118   if (TME_ARG_IS(size, "1600x1280")) {
119     return (TME_SUNFB_SIZE_1600_1280);
120   }
121   else if (TME_ARG_IS(size, "1152x900")) {
122     return (TME_SUNFB_SIZE_1152_900);
123   }
124   else if (TME_ARG_IS(size, "1024x1024")) {
125     return (TME_SUNFB_SIZE_1024_1024);
126   }
127   else if (TME_ARG_IS(size, "1280x1024")) {
128     return (TME_SUNFB_SIZE_1280_1024);
129   }
130   else if (TME_ARG_IS(size, "1440x1440")) {
131     return (TME_SUNFB_SIZE_1440_1440);
132   }
133   else if (TME_ARG_IS(size, "640x480")) {
134     return (TME_SUNFB_SIZE_640_480);
135   }
136   else if (TME_ARG_IS(size, "1024x768")) {
137     return (TME_SUNFB_SIZE_1024_768);
138   }
139   return (TME_SUNFB_SIZE_NULL);
140 }
141 
142 /* this returns the width for the given sunfb size: */
143 tme_uint32_t
tme_sunfb_size_width(tme_uint32_t sunfb_size)144 tme_sunfb_size_width(tme_uint32_t sunfb_size)
145 {
146   switch (sunfb_size) {
147   default: assert(FALSE);
148   case TME_SUNFB_SIZE_640_480: return (640);
149   case TME_SUNFB_SIZE_1024_768: /* FALLTHROUGH */
150   case TME_SUNFB_SIZE_1024_1024: return (1024);
151   case TME_SUNFB_SIZE_1152_900: return (1152);
152   case TME_SUNFB_SIZE_1280_1024: return (1280);
153   case TME_SUNFB_SIZE_1600_1280: return (1600);
154   case TME_SUNFB_SIZE_1440_1440: return (1440);
155   }
156 }
157 
158 /* this returns the height for the given sunfb size: */
159 tme_uint32_t
tme_sunfb_size_height(tme_uint32_t sunfb_size)160 tme_sunfb_size_height(tme_uint32_t sunfb_size)
161 {
162   switch (sunfb_size) {
163   default: assert(FALSE);
164   case TME_SUNFB_SIZE_640_480: return (480);
165   case TME_SUNFB_SIZE_1024_768: return (768);
166   case TME_SUNFB_SIZE_1152_900: return (900);
167   case TME_SUNFB_SIZE_1024_1024: /* FALLTHROUGH */
168   case TME_SUNFB_SIZE_1280_1024: return (1024);
169   case TME_SUNFB_SIZE_1600_1280: return (1280);
170   case TME_SUNFB_SIZE_1440_1440: return (1440);
171   }
172 }
173 
174 /* XXX FIXME - this should be in a tme/ic/bt458.c: */
175 /* this determines the closest regular colormap indices for the
176    overlay map: */
177 int
tme_bt458_omap_best(struct tme_bt458 * bt458)178 tme_bt458_omap_best(struct tme_bt458 *bt458)
179 {
180   unsigned int omap_i;
181   unsigned int cmap_i;
182   tme_int32_t score;
183   unsigned int cmap_i_best;
184   tme_int32_t score_best;
185   tme_int32_t score_part;
186   int changed;
187 
188   /* loop over the overlay map indices: */
189   changed = FALSE;
190   for (omap_i = 0;
191        omap_i < TME_ARRAY_ELS(bt458->tme_bt458_omap_primaries[0]);
192        omap_i++) {
193 
194     /* silence gcc -Wuninitialized: */
195     cmap_i_best = 0;
196 
197     /* loop over the regular colormap indices: */
198     score_best = (256 * 256 * 256);
199     for (cmap_i = 0;
200 	 cmap_i < 256;
201 	 cmap_i++) {
202 
203       /* score this colormap entry, by taking the product of the
204 	 distances between this colormap entry's primaries and this
205 	 overlay map entry's primaries: */
206       score = bt458->tme_bt458_omap_r[omap_i];
207       score -= (bt458->tme_bt458_cmap_r)[cmap_i];
208       score_part = bt458->tme_bt458_omap_g[omap_i];
209       score_part -= (bt458->tme_bt458_cmap_g)[cmap_i];
210       score *= score_part;
211       score_part = bt458->tme_bt458_omap_b[omap_i];
212       score_part -= (bt458->tme_bt458_cmap_b)[cmap_i];
213       score *= score_part;
214       if (score < 0) {
215 	score = -score;
216       }
217 
218       /* update the best colormap entry: */
219       if (score < score_best) {
220 	score_best = score;
221 	cmap_i_best = cmap_i;
222       }
223     }
224 
225     /* save the closest index: */
226     changed |= bt458->tme_bt458_omap_cmap_indices[omap_i] - cmap_i_best;
227     bt458->tme_bt458_omap_cmap_indices[omap_i] = cmap_i_best;
228   }
229 
230   return (changed);
231 }
232 
233 /* this handles a mode change callout: */
234 static int
_tme_sunfb_mode_change(struct tme_sunfb * sunfb)235 _tme_sunfb_mode_change(struct tme_sunfb *sunfb)
236 {
237   struct tme_fb_connection *conn_fb_other;
238   struct tme_fb_connection *conn_fb;
239   int rc;
240 
241   /* if this framebuffer has a Bt458: */
242   if (_TME_SUNFB_HAS_BT458(sunfb)) {
243 
244     /* update the best regular colormap indices for the colors in the
245        overlay map.  if any of them have changed, we may have do to a
246        full update: */
247     if (tme_bt458_omap_best(&sunfb->tme_sunfb_bt458)) {
248 
249       /* if this framebuffer has an update-full function, call it: */
250       if (sunfb->tme_sunfb_update_full != NULL) {
251 	(*sunfb->tme_sunfb_update_full)(sunfb);
252       }
253     }
254   }
255 
256   /* get both sides of the framebuffer connection: */
257   conn_fb_other = sunfb->tme_sunfb_fb_connection;
258   conn_fb = (struct tme_fb_connection *) conn_fb_other->tme_fb_connection.tme_connection_other;
259 
260   /* unlock the mutex: */
261   tme_mutex_unlock(&sunfb->tme_sunfb_mutex);
262 
263   /* do the callout: */
264   rc = (conn_fb_other != NULL
265 	? ((*conn_fb_other->tme_fb_connection_mode_change)
266 	   (conn_fb_other))
267 	: TME_OK);
268 
269   /* lock the mutex: */
270   tme_mutex_lock(&sunfb->tme_sunfb_mutex);
271 
272   return (rc);
273 }
274 
275 /* the sunfb callout function.  it must be called with the mutex locked: */
276 static void
_tme_sunfb_callout(struct tme_sunfb * sunfb)277 _tme_sunfb_callout(struct tme_sunfb *sunfb)
278 {
279   struct tme_bus_connection *conn_bus;
280   int int_asserted;
281   int callouts_blocked;
282   int rc;
283 
284   /* if this function is already running in another thread, simply
285      return now.  the other thread will do our work: */
286   if (sunfb->tme_sunfb_callout_flags
287       & TME_SUNFB_CALLOUT_RUNNING) {
288     return;
289   }
290 
291   /* callouts are now running: */
292   sunfb->tme_sunfb_callout_flags
293     |= TME_SUNFB_CALLOUT_RUNNING;
294 
295   /* initially, no callouts are blocked: */
296   callouts_blocked = 0;
297 
298   /* loop forever: */
299   for (;;) {
300 
301     /* any callout, successful or not, will clear this bit.  if we get
302        to the bottom of the loop and this bit is still set, there are
303        no more (unblocked) callouts to make, so we can stop: */
304     callouts_blocked |= TME_SUNFB_CALLOUT_RUNNING;
305 
306     /* we always clear the interrupt callout flag, because we only
307        need it to get callouts to run at all: */
308     sunfb->tme_sunfb_callout_flags &= ~TME_SUNFB_CALLOUT_INT;
309 
310     /* if our interrupt signal has changed, and this callout isn't
311        blocked: */
312     int_asserted
313       = (_TME_SUNFB_IS_S4(sunfb)
314 	 ? ((sunfb->tme_sunfb_s4_regs.tme_sunfb_s4_regs_control
315 	     & TME_SUNFB_S4_CONTROL_INT_ENABLE)
316 	    && (sunfb->tme_sunfb_s4_regs.tme_sunfb_s4_regs_status
317 		& TME_SUNFB_S4_STATUS_INT_PENDING))
318 	 : FALSE);
319     if ((!int_asserted != !sunfb->tme_sunfb_int_asserted)
320 	&& (callouts_blocked & TME_SUNFB_CALLOUT_INT) == 0) {
321 
322       /* get our bus connection: */
323       conn_bus = tme_memory_atomic_pointer_read(struct tme_bus_connection *,
324 						sunfb->tme_sunfb_device.tme_bus_device_connection,
325 						&sunfb->tme_sunfb_device.tme_bus_device_connection_rwlock);
326 
327       /* unlock our mutex: */
328       tme_mutex_unlock(&sunfb->tme_sunfb_mutex);
329 
330       /* call out the bus interrupt signal edge: */
331       rc = (*conn_bus->tme_bus_signal)
332 	(conn_bus,
333 	 sunfb->tme_sunfb_bus_signal_int
334 	 | TME_BUS_SIGNAL_EDGE
335 	 | (int_asserted
336 	    ? TME_BUS_SIGNAL_LEVEL_ASSERTED
337 	    : TME_BUS_SIGNAL_LEVEL_NEGATED));
338 
339       /* lock our mutex: */
340       tme_mutex_lock(&sunfb->tme_sunfb_mutex);
341 
342       /* unblock all callouts: */
343       callouts_blocked = 0;
344 
345       /* if this callout failed: */
346       if (rc != TME_OK) {
347 
348 	/* reschedule this callout but block it until some other
349            callout succeeds: */
350 	sunfb->tme_sunfb_callout_flags |= TME_SUNFB_CALLOUT_INT;
351 	callouts_blocked |= TME_SUNFB_CALLOUT_INT;
352 	continue;
353       }
354 
355       /* note the new state of the interrupt signal: */
356       sunfb->tme_sunfb_int_asserted = int_asserted;
357     }
358 
359     /* if we need to call out a mode change, and this callout isn't
360        blocked: */
361     if ((sunfb->tme_sunfb_callout_flags & TME_SUNFB_CALLOUT_MODE_CHANGE)
362 	&& (callouts_blocked & TME_SUNFB_CALLOUT_MODE_CHANGE) == 0) {
363 
364       /* clear this callout: */
365       sunfb->tme_sunfb_callout_flags &= ~TME_SUNFB_CALLOUT_MODE_CHANGE;
366 
367       /* call out the mode change: */
368       rc = _tme_sunfb_mode_change(sunfb);
369 
370       /* unblock all callouts: */
371       callouts_blocked = 0;
372 
373       /* if the callout failed: */
374       if (rc != TME_OK) {
375 
376 	/* reschedule this callout but block it until some other
377            callout succeeds: */
378 	sunfb->tme_sunfb_callout_flags |= TME_SUNFB_CALLOUT_MODE_CHANGE;
379 	callouts_blocked |= TME_SUNFB_CALLOUT_MODE_CHANGE;
380 	continue;
381       }
382     }
383 
384     /* if no more (unblocked) callouts can run, we can stop: */
385     if (callouts_blocked & TME_SUNFB_CALLOUT_RUNNING) {
386       break;
387     }
388   }
389 
390   /* clear that callouts are running: */
391   sunfb->tme_sunfb_callout_flags &= ~TME_SUNFB_CALLOUT_RUNNING;
392 }
393 
394 /* the callout thread: */
395 static void
_tme_sunfb_callout_thread(void * _sunfb)396 _tme_sunfb_callout_thread(void *_sunfb)
397 {
398   struct tme_sunfb *sunfb;
399 
400   /* recover our data structure: */
401   sunfb = _sunfb;
402 
403   /* lock the mutex: */
404   tme_mutex_lock(&sunfb->tme_sunfb_mutex);
405 
406   /* loop forever: */
407   for (;;) {
408 
409     /* make any callouts: */
410     _tme_sunfb_callout(sunfb);
411 
412     /* wait on the condition: */
413     tme_cond_wait_yield(&sunfb->tme_sunfb_callout_cond,
414 			&sunfb->tme_sunfb_mutex);
415   }
416   /* NOTREACHED */
417 }
418 
419 /* this is called before the framebuffer's display is updated: */
420 int
tme_sunfb_memory_update(struct tme_fb_connection * conn_fb)421 tme_sunfb_memory_update(struct tme_fb_connection *conn_fb)
422 {
423   struct tme_sunfb *sunfb;
424   int int_asserted;
425   struct tme_token *tlb_token;
426 
427   /* recover our data structure: */
428   sunfb = conn_fb->tme_fb_connection.tme_connection_element->tme_element_private;
429 
430   /* lock the mutex: */
431   tme_mutex_lock(&sunfb->tme_sunfb_mutex);
432 
433   /* if this framebuffer supports interrupts, one is now pending.  the
434      interrupt should also be asserted if it's enabled: */
435   if (_TME_SUNFB_IS_S4(sunfb)) {
436     sunfb->tme_sunfb_s4_regs.tme_sunfb_s4_regs_status
437       |= TME_SUNFB_S4_STATUS_INT_PENDING;
438     int_asserted
439       = ((sunfb->tme_sunfb_s4_regs.tme_sunfb_s4_regs_control
440 	  & TME_SUNFB_S4_CONTROL_INT_ENABLE) != 0);
441   }
442   else {
443     int_asserted = FALSE;
444   }
445 
446   /* if this interrupt should be asserted and it isn't already, or if
447      we have other callouts to make, notify the callout thread: */
448   if ((int_asserted && !sunfb->tme_sunfb_int_asserted)
449       || (sunfb->tme_sunfb_callout_flags & TME_SUNFB_CALLOUTS_MASK) != 0) {
450     tme_cond_notify(&sunfb->tme_sunfb_callout_cond, FALSE);
451   }
452 
453   /* set the offsets of the first and last bytes updated in the real
454      framebuffer memory: */
455   conn_fb->tme_fb_connection_offset_updated_first = sunfb->tme_sunfb_offset_updated_first;
456   conn_fb->tme_fb_connection_offset_updated_last = sunfb->tme_sunfb_offset_updated_last;
457 
458   /* reset the offsets of the first and last bytes updated in the real
459      framebuffer memory: */
460   sunfb->tme_sunfb_offset_updated_first = 0 - (tme_uint32_t) 1;
461   sunfb->tme_sunfb_offset_updated_last = 0;
462 
463   /* invalidate any outstanding writable TLB entry: */
464   tlb_token = sunfb->tme_sunfb_tlb_token;
465   if (tlb_token != NULL) {
466     tme_token_invalidate(tlb_token);
467     sunfb->tme_sunfb_tlb_token = NULL;
468   }
469 
470   /* unlock the mutex: */
471   tme_mutex_unlock(&sunfb->tme_sunfb_mutex);
472 
473   return (TME_OK);
474 }
475 
476 /* the sunfb memory bus cycle handler: */
477 static int
_tme_sunfb_bus_cycle_memory(void * _sunfb,struct tme_bus_cycle * cycle_init)478 _tme_sunfb_bus_cycle_memory(void *_sunfb, struct tme_bus_cycle *cycle_init)
479 {
480   struct tme_sunfb *sunfb;
481 
482   /* recover our data structure: */
483   sunfb = (struct tme_sunfb *) _sunfb;
484 
485   /* lock the mutex: */
486   tme_mutex_lock(&sunfb->tme_sunfb_mutex);
487 
488   /* run the cycle: */
489   assert (cycle_init->tme_bus_cycle_address
490 	  >= sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_first);
491   tme_bus_cycle_xfer_memory(cycle_init,
492 			    (sunfb->tme_sunfb_memory
493 			     - sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_first),
494 			    sunfb->tme_sunfb_memory_address_last_displayed);
495 
496   /* unlock the mutex: */
497   tme_mutex_unlock(&sunfb->tme_sunfb_mutex);
498 
499   /* no faults: */
500   return (TME_OK);
501 }
502 
503 /* the sunfb memory pad bus cycle handler: */
504 static int
_tme_sunfb_bus_cycle_memory_pad(void * _sunfb,struct tme_bus_cycle * cycle_init)505 _tme_sunfb_bus_cycle_memory_pad(void *_sunfb, struct tme_bus_cycle *cycle_init)
506 {
507   struct tme_sunfb *sunfb;
508 
509   /* recover our data structure: */
510   sunfb = (struct tme_sunfb *) _sunfb;
511 
512   /* lock the mutex: */
513   tme_mutex_lock(&sunfb->tme_sunfb_mutex);
514 
515   /* run the cycle: */
516   assert (cycle_init->tme_bus_cycle_address
517 	  > sunfb->tme_sunfb_memory_address_last_displayed);
518   tme_bus_cycle_xfer_memory(cycle_init,
519 			    (sunfb->tme_sunfb_memory_pad
520 			     - (sunfb->tme_sunfb_memory_address_last_displayed
521 				+ 1)),
522 			    sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_last);
523 
524   /* unlock the mutex: */
525   tme_mutex_unlock(&sunfb->tme_sunfb_mutex);
526 
527   /* no faults: */
528   return (TME_OK);
529 }
530 
531 /* the sunfb P4 bus cycle handler: */
532 int
tme_sunfb_bus_cycle_p4(void * _sunfb,struct tme_bus_cycle * cycle_init)533 tme_sunfb_bus_cycle_p4(void *_sunfb, struct tme_bus_cycle *cycle_init)
534 {
535   struct tme_sunfb *sunfb;
536   tme_uint32_t p4_old, p4_new;
537   tme_bus_addr32_t undecoded;
538 
539   /* recover our data structure: */
540   sunfb = (struct tme_sunfb *) _sunfb;
541 
542   /* lock the mutex: */
543   tme_mutex_lock(&sunfb->tme_sunfb_mutex);
544 
545   /* get the old P4 value: */
546   p4_old = tme_betoh_u32(sunfb->tme_sunfb_p4);
547 
548   /* the entire register bus subregion is all decoded (or, rather, not
549      decoded) as the P4: */
550   undecoded
551     = (cycle_init->tme_bus_cycle_address
552        & (sunfb->tme_sunfb_bus_subregion_regs.tme_bus_subregion_address_last
553 	  - sunfb->tme_sunfb_bus_subregion_regs.tme_bus_subregion_address_first
554 	  - sizeof(sunfb->tme_sunfb_p4)));
555   cycle_init->tme_bus_cycle_address
556     -= undecoded;
557 
558   /* run the cycle: */
559   assert (cycle_init->tme_bus_cycle_address
560 	  >= sunfb->tme_sunfb_bus_subregion_regs.tme_bus_subregion_address_first);
561   tme_bus_cycle_xfer_memory(cycle_init,
562 			    (((tme_uint8_t *) &sunfb->tme_sunfb_p4)
563 			     - sunfb->tme_sunfb_bus_subregion_regs.tme_bus_subregion_address_first),
564 			    (sunfb->tme_sunfb_bus_subregion_regs.tme_bus_subregion_address_first
565 			     + sizeof(sunfb->tme_sunfb_p4)
566 			     - 1));
567   cycle_init->tme_bus_cycle_address
568     += undecoded;
569 
570   /* get the new P4 value: */
571   p4_new = tme_betoh_u32(sunfb->tme_sunfb_p4);
572 
573   /* put back the unchanging bits: */
574   p4_new
575     = ((p4_new
576 	& ~TME_SUNFB_P4_RO_MASK)
577        | (p4_old
578 	  & TME_SUNFB_P4_RO_MASK));
579 
580   /* we do not support these bits: */
581   if (p4_new
582       & (TME_SUNFB_P4_REG_SYNC_RAMDAC
583 	 | TME_SUNFB_P4_REG_ENABLE_INT)) {
584     abort();
585   }
586 
587   /* set the new P4 value: */
588   sunfb->tme_sunfb_p4 = tme_htobe_u32(p4_new);
589 
590   /* unlock the mutex: */
591   tme_mutex_unlock(&sunfb->tme_sunfb_mutex);
592 
593   /* no faults: */
594   return (TME_OK);
595 }
596 
597 /* the Brooktree BT458 bus cycle handler: */
598 int
tme_sunfb_bus_cycle_bt458(void * _sunfb,struct tme_bus_cycle * cycle_init)599 tme_sunfb_bus_cycle_bt458(void *_sunfb, struct tme_bus_cycle *cycle_init)
600 {
601   struct tme_sunfb *sunfb;
602   struct tme_bt458 *bt458;
603   unsigned int reg;
604   tme_uint32_t value_packed;
605   tme_uint8_t value;
606   unsigned int byte_count;
607   unsigned int bt458_address;
608   unsigned int bt458_rgb;
609   unsigned int map_count;
610 
611   /* recover our data structure: */
612   sunfb = (struct tme_sunfb *) _sunfb;
613 
614   /* we only emulate 8-bit and aligned 32-bit accesses: */
615   reg = cycle_init->tme_bus_cycle_address % TME_SUNFB_S4_SIZ_BT458;
616   if (cycle_init->tme_bus_cycle_size != sizeof(tme_uint8_t)
617       && (cycle_init->tme_bus_cycle_size != sizeof(tme_uint32_t)
618 	  || (reg % sizeof(tme_uint32_t)) != 0)) {
619     abort();
620   }
621   reg &= (TME_SUNFB_S4_SIZ_BT458 - sizeof(tme_uint32_t));
622 
623   /* lock the mutex: */
624   tme_mutex_lock(&sunfb->tme_sunfb_mutex);
625 
626   /* get the Bt458 address registers: */
627   bt458 = &sunfb->tme_sunfb_bt458;
628   bt458_address = bt458->tme_bt458_address;
629   bt458_rgb = bt458->tme_bt458_rgb;
630 
631   /* set the number of colormap values per read and write: */
632   map_count = ((sunfb->tme_sunfb_flags & TME_SUNFB_FLAG_BT458_CMAP_PACKED)
633 	       ? cycle_init->tme_bus_cycle_size
634 	       : sizeof(tme_uint8_t));
635 
636   /* if this is a write: */
637   if (cycle_init->tme_bus_cycle_type == TME_BUS_CYCLE_WRITE) {
638 
639     /* run the bus cycle: */
640     if (cycle_init->tme_bus_cycle_size == sizeof(tme_uint32_t)) {
641       tme_bus_cycle_xfer_reg(cycle_init,
642 			     &value_packed,
643 			     TME_BUS32_LOG2);
644 
645       /* for a 32-bit write to an 8-bit register, a framebuffer either
646 	 uses byte lane D24..D31 or byte lane D0..D7: */
647       value
648 	= (value_packed
649 	   >> (((sunfb->tme_sunfb_flags
650 		 & (TME_SUNFB_FLAG_BT458_BYTE_D0_D7
651 		    | TME_SUNFB_FLAG_BT458_BYTE_D24_D31))
652 		== TME_SUNFB_FLAG_BT458_BYTE_D24_D31)
653 	       ? 24
654 	       : 0));
655     }
656     else {
657       tme_bus_cycle_xfer_reg(cycle_init,
658 			     &value,
659 			     TME_BUS8_LOG2);
660       value_packed = value;
661       value_packed <<= 24;
662     }
663 
664     /* if this is a write to the address register: */
665     if (reg == TME_SUNFB_S4_REG_BT458_ADDRESS) {
666 
667       /* set the Bt458 address register: */
668       bt458_address = value;
669     }
670 
671     /* if this is a write to the colormap register: */
672     else if (reg == TME_SUNFB_S4_REG_BT458_CMAP) {
673 
674       /* write the colormap: */
675       do {
676 
677 	/* write one colormap primary: */
678 	(bt458->tme_bt458_cmap_primaries[bt458_rgb])[bt458_address] = value_packed >> 24;
679 
680 	/* advance the packed value: */
681 	value_packed <<= 8;
682 
683 	/* advance the Bt458 address registers: */
684 	bt458_rgb++;
685 	if (bt458_rgb == TME_ARRAY_ELS(bt458->tme_bt458_cmap_primaries)) {
686 	  bt458_address++;
687 	  bt458_rgb = 0;
688 	}
689       } while (--map_count > 0);
690 
691       /* calling out a mode change on every colormap register write is
692 	 expensive and unnecessary.  instead, arrange for the update
693 	 function to eventually cause a mode change: */
694       sunfb->tme_sunfb_callout_flags |= TME_SUNFB_CALLOUT_MODE_CHANGE;
695     }
696 
697     /* if this is a write to the control register: */
698     else if (reg == TME_SUNFB_S4_REG_BT458_CONTROL) {
699 
700       /* dispatch on the address: */
701       switch (bt458_address) {
702 
703 	/* the read mask register: */
704       case TME_BT458_REG_CONTROL_MASK_READ:
705 	/* all planes must be on: */
706 	if (value != 0xff) {
707 	  abort();
708 	}
709 	break;
710 
711 	/* the blink mask register: */
712       case TME_BT458_REG_CONTROL_MASK_BLINK:
713 	/* no planes must be blinking: */
714 	if (value != 0x00) {
715 	  abort();
716 	}
717 	break;
718 
719 	/* the command register: */
720       case TME_BT458_REG_CONTROL_COMMAND:
721 
722 	/* XXX FIXME - we should validate values written to the
723            command register: */
724 	break;
725 
726 	/* the test register: */
727       case TME_BT458_REG_CONTROL_TEST:
728 	break;
729 
730       default:
731 	break;
732       }
733 
734       /* the Bt458 datasheet says, "If an invalid address is loaded
735 	 into the address register, data written to the device will
736 	 be ignored and invalid data will be read by the MPU." */
737       if (bt458_address >= TME_BT458_REG_CONTROL_FIRST
738 	  && bt458_address <= TME_BT458_REG_CONTROL_LAST) {
739 
740 	/* write this register: */
741 	bt458->tme_bt458_regs[bt458_address - TME_BT458_REG_CONTROL_FIRST] = value;
742       }
743     }
744 
745     /* this must be a write to the overlay map register: */
746     else {
747       assert (reg == TME_SUNFB_S4_REG_BT458_OMAP);
748 
749       /* write the overlay map: */
750       do {
751 
752 	/* if the Bt458 address isn't in the overlay map: */
753 	if (bt458_address >= 4) {
754 	  abort();
755 	}
756 
757 	/* write one overlay map primary: */
758 	bt458->tme_bt458_omap_primaries[bt458_rgb][bt458_address] = value_packed >> 24;
759 
760 	/* advance the packed value: */
761 	value_packed <<= 8;
762 
763 	/* advance the Bt458 address registers: */
764 	bt458_rgb++;
765 	if (bt458_rgb == TME_ARRAY_ELS(bt458->tme_bt458_omap_primaries)) {
766 	  bt458_address++;
767 	  bt458_rgb = 0;
768 	}
769       } while (--map_count > 0);
770 
771       /* calling out a mode change on every overlap map register write
772 	 is expensive and unnecessary.  instead, arrange for the
773 	 update function to eventually cause a mode change: */
774       sunfb->tme_sunfb_callout_flags |= TME_SUNFB_CALLOUT_MODE_CHANGE;
775     }
776   }
777 
778   /* otherwise, this is a read: */
779   else {
780     assert (cycle_init->tme_bus_cycle_type == TME_BUS_CYCLE_READ);
781 
782     /* zero the value read: */
783     value_packed = 0;
784 
785     /* assume only one byte will be read: */
786     byte_count = sizeof(tme_uint8_t);
787 
788     /* if this is a read of the address register: */
789     if (reg == TME_SUNFB_S4_REG_BT458_ADDRESS) {
790 
791       /* read the Bt458 address register: */
792       value_packed = bt458_address;
793     }
794 
795     /* if this is a read to the colormap register: */
796     else if (reg == TME_SUNFB_S4_REG_BT458_CMAP) {
797 
798       /* read the colormap: */
799       byte_count = map_count;
800       do {
801 
802 	/* advance the packed value: */
803 	value_packed <<= 8;
804 
805 	/* read one colormap primary: */
806 	value_packed |= (bt458->tme_bt458_cmap_primaries[bt458_rgb])[bt458_address];
807 
808 	/* advance the Bt458 address registers: */
809 	bt458_rgb++;
810 	if (bt458_rgb == TME_ARRAY_ELS(bt458->tme_bt458_cmap_primaries)) {
811 	  bt458_address++;
812 	  bt458_rgb = 0;
813 	}
814       } while (--map_count > 0);
815     }
816 
817     /* if this is a read of the control register: */
818     else if (reg == TME_SUNFB_S4_REG_BT458_CONTROL) {
819 
820       /* the Bt458 datasheet says, "If an invalid address is loaded
821 	 into the address register, data written to the device will
822 	 be ignored and invalid data will be read by the MPU." */
823       if (bt458_address >= TME_BT458_REG_CONTROL_FIRST
824 	  && bt458_address <= TME_BT458_REG_CONTROL_LAST) {
825 
826 	/* read this register: */
827 	value_packed = bt458->tme_bt458_regs[bt458_address - TME_BT458_REG_CONTROL_FIRST];
828       }
829     }
830 
831     /* this must be a read of the overlay map register: */
832     else {
833       assert (reg == TME_SUNFB_S4_REG_BT458_OMAP);
834 
835       /* read the overlay map: */
836       byte_count = map_count;
837       do {
838 
839 	/* if the Bt458 address isn't in the overlay map: */
840 	if (bt458_address >= 4) {
841 	  abort();
842 	}
843 
844 	/* advance the packed value: */
845 	value_packed <<= 8;
846 
847 	/* read one overlay map primary: */
848 	value_packed |= bt458->tme_bt458_omap_primaries[bt458_rgb][bt458_address];
849 
850 	/* advance the Bt458 address registers: */
851 	bt458_rgb++;
852 	if (bt458_rgb == TME_ARRAY_ELS(bt458->tme_bt458_omap_primaries)) {
853 	  bt458_address++;
854 	  bt458_rgb = 0;
855 	}
856       } while (--map_count > 0);
857     }
858 
859     /* run the bus cycle: */
860     if (cycle_init->tme_bus_cycle_size == sizeof(tme_uint32_t)) {
861       if (byte_count == sizeof(tme_uint8_t)) {
862 	value_packed |= (value_packed << 8);
863 	value_packed |= (value_packed << 16);
864       }
865       tme_bus_cycle_xfer_reg(cycle_init,
866 			     &value_packed,
867 			     TME_BUS32_LOG2);
868     }
869     else {
870       value = value_packed;
871       tme_bus_cycle_xfer_reg(cycle_init,
872 			     &value,
873 			     TME_BUS8_LOG2);
874     }
875   }
876 
877   /* update the Bt458 address registers: */
878   bt458->tme_bt458_address = bt458_address;
879   bt458->tme_bt458_rgb = ((reg == TME_SUNFB_S4_REG_BT458_CMAP
880 			   || reg == TME_SUNFB_S4_REG_BT458_OMAP)
881 			  ? bt458_rgb
882 			  : 0);
883 
884   /* unlock the mutex: */
885   tme_mutex_unlock(&sunfb->tme_sunfb_mutex);
886 
887   /* no faults: */
888   return (TME_OK);
889 }
890 
891 /* the sunfb S4 bus cycle handler: */
892 int
tme_sunfb_bus_cycle_s4(void * _sunfb,struct tme_bus_cycle * cycle_init)893 tme_sunfb_bus_cycle_s4(void *_sunfb, struct tme_bus_cycle *cycle_init)
894 {
895   struct tme_sunfb *sunfb;
896   tme_bus_addr32_t undecoded;
897   tme_uint8_t sunfb_s4_status;
898 
899   /* if this bus cycle happened in the Bt458 registers: */
900   if ((cycle_init->tme_bus_cycle_address % TME_SUNFB_S4_SIZ_REGS)
901       < TME_SUNFB_S4_SIZ_BT458) {
902 
903     /* call the Bt458 cycle handler: */
904     return (tme_sunfb_bus_cycle_bt458(_sunfb, cycle_init));
905   }
906 
907   /* recover our data structure: */
908   sunfb = (struct tme_sunfb *) _sunfb;
909 
910   /* lock the mutex: */
911   tme_mutex_lock(&sunfb->tme_sunfb_mutex);
912 
913   /* the entire register bus subregion is all decoded (or, rather, not
914      decoded) as the S4 registers: */
915   undecoded
916     = (cycle_init->tme_bus_cycle_address
917        & (((tme_bus_addr32_t) 0)
918 	  - TME_SUNFB_S4_SIZ_REGS));
919 
920   /* save the status register: */
921   sunfb_s4_status = sunfb->tme_sunfb_s4_regs.tme_sunfb_s4_regs_status;
922 
923   /* if this is a write, and an interrupt is pending, and this write
924      covers the status register: */
925   if (cycle_init->tme_bus_cycle_type == TME_BUS_CYCLE_WRITE
926       && (sunfb_s4_status & TME_SUNFB_S4_STATUS_INT_PENDING)
927       && (cycle_init->tme_bus_cycle_address
928 	  <= (undecoded
929 	      + TME_SUNFB_S4_REG(tme_sunfb_s4_regs_status)))
930       && (cycle_init->tme_bus_cycle_size
931 	  > ((undecoded
932 	      + TME_SUNFB_S4_REG(tme_sunfb_s4_regs_status))
933 	     - cycle_init->tme_bus_cycle_address))) {
934 
935     /* clear the interrupt: */
936     sunfb_s4_status &= ~TME_SUNFB_S4_STATUS_INT_PENDING;
937   }
938 
939   /* run the cycle: */
940   assert (cycle_init->tme_bus_cycle_address
941 	  >= sunfb->tme_sunfb_bus_subregion_regs.tme_bus_subregion_address_first);
942   tme_bus_cycle_xfer_memory(cycle_init,
943 			    (((tme_uint8_t *) &sunfb->tme_sunfb_s4_regs)
944 			     - TME_SUNFB_S4_SIZ_BT458
945 			     - undecoded),
946 			    (undecoded
947 			     | (TME_SUNFB_S4_SIZ_REGS - 1)));
948 
949   /* restore the status register: */
950   sunfb->tme_sunfb_s4_regs.tme_sunfb_s4_regs_status = sunfb_s4_status;
951 
952   /* make any callouts: */
953   _tme_sunfb_callout(sunfb);
954 
955   /* unlock the mutex: */
956   tme_mutex_unlock(&sunfb->tme_sunfb_mutex);
957 
958   /* no faults: */
959   return (TME_OK);
960 }
961 
962 /* the sunfb TLB filler: */
963 static int
_tme_sunfb_tlb_fill(void * _sunfb,struct tme_bus_tlb * tlb,tme_bus_addr_t address_wider,unsigned int cycles)964 _tme_sunfb_tlb_fill(void *_sunfb,
965 		    struct tme_bus_tlb *tlb,
966 		    tme_bus_addr_t address_wider,
967 		    unsigned int cycles)
968 {
969   struct tme_sunfb *sunfb;
970   tme_bus_addr32_t address;
971   struct tme_token *tlb_token;
972   struct tme_token *tlb_token_other;
973   tme_uint32_t offset_updated_first;
974   tme_uint32_t offset_updated_last;
975   unsigned int subregion_i;
976 
977   /* recover our data structure: */
978   sunfb = (struct tme_sunfb *) _sunfb;
979 
980   /* initialize the TLB entry: */
981   tme_bus_tlb_initialize(tlb);
982 
983   /* get the normal-width address: */
984   address = address_wider;
985   assert (address == address_wider);
986 
987   /* if this address falls in the bus subregion for memory: */
988   if ((sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_first
989        <= address)
990       && (address
991 	  <= sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_last)) {
992 
993     /* if this address falls in the memory pad: */
994     if (address > sunfb->tme_sunfb_memory_address_last_displayed) {
995 
996       /* this TLB entry covers this range: */
997       tlb->tme_bus_tlb_addr_first = (sunfb->tme_sunfb_memory_address_last_displayed + 1);
998       tlb->tme_bus_tlb_addr_last = sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_last;
999 
1000       /* bus cycles to this range are to the memory pad and can be
1001          fast: */
1002       tlb->tme_bus_tlb_cycle = _tme_sunfb_bus_cycle_memory_pad;
1003       tlb->tme_bus_tlb_emulator_off_write
1004 	= (sunfb->tme_sunfb_memory_pad
1005 	   - tlb->tme_bus_tlb_addr_first);
1006     }
1007 
1008     /* otherwise, this address does not fall in the memory pad: */
1009     else {
1010 
1011       /* if this TLB entry is not for writing: */
1012       if ((cycles & TME_BUS_CYCLE_WRITE) == 0) {
1013 
1014 	/* this TLB entry covers this range: */
1015 	tlb->tme_bus_tlb_addr_first = sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_first;
1016 	tlb->tme_bus_tlb_addr_last = sunfb->tme_sunfb_memory_address_last_displayed;
1017 
1018 	/* this TLB entry allows only (fast) reading to the memory: */
1019 	tlb->tme_bus_tlb_emulator_off_read = sunfb->tme_sunfb_memory - tlb->tme_bus_tlb_addr_first;
1020 	tlb->tme_bus_tlb_rwlock = &sunfb->tme_sunfb_rwlock;
1021 	tlb->tme_bus_tlb_cycles_ok = TME_BUS_CYCLE_READ;
1022 	tlb->tme_bus_tlb_cycle = _tme_sunfb_bus_cycle_memory;
1023 	tlb->tme_bus_tlb_cycle_private = _sunfb;
1024 	return (TME_OK);
1025       }
1026 
1027       /* get the token for this writable TLB entry: */
1028       tlb_token = tlb->tme_bus_tlb_token;
1029 
1030       /* if a different writable TLB entry's token is outstanding: */
1031       tlb_token_other = sunfb->tme_sunfb_tlb_token;
1032       if (__tme_predict_true(tlb_token_other != NULL)) {
1033 	if (tlb_token_other != tlb_token) {
1034 
1035 	  /* invalidate this other TLB entry: */
1036 	  tme_token_invalidate(tlb_token_other);
1037 	}
1038       }
1039 
1040       /* save the token for this writable TLB entry: */
1041       sunfb->tme_sunfb_tlb_token = tlb_token;
1042 
1043       /* update the offsets of the first and last bytes updated in the
1044 	 real framebuffer memory: */
1045       offset_updated_first = address;
1046       offset_updated_first -= (tme_uint32_t) sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_first;
1047       offset_updated_last = offset_updated_first + TME_SUNFB_UPDATE_SIZE;
1048       offset_updated_first
1049 	= TME_MIN(offset_updated_first,
1050 		  sunfb->tme_sunfb_offset_updated_first);
1051       offset_updated_last
1052 	= TME_MAX(offset_updated_last,
1053 		  sunfb->tme_sunfb_offset_updated_last);
1054       offset_updated_last
1055 	= TME_MIN(offset_updated_last,
1056 		  (((tme_uint32_t)
1057 		    sunfb->tme_sunfb_memory_address_last_displayed)
1058 		   - ((tme_uint32_t)
1059 		      sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_first)));
1060       sunfb->tme_sunfb_offset_updated_first = offset_updated_first;
1061       sunfb->tme_sunfb_offset_updated_last = offset_updated_last;
1062 
1063       /* this TLB entry covers this range: */
1064       tlb->tme_bus_tlb_addr_first
1065 	= (sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_first
1066 	   + offset_updated_first);
1067       tlb->tme_bus_tlb_addr_last
1068 	= (sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_first
1069 	   + offset_updated_last);
1070 
1071       /* bus cycles to this range are to the memory and can be fast: */
1072       tlb->tme_bus_tlb_cycle = _tme_sunfb_bus_cycle_memory;
1073       tlb->tme_bus_tlb_emulator_off_write
1074 	= (sunfb->tme_sunfb_memory
1075 	   - sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_first);
1076     }
1077 
1078     /* this TLB entry allows fast reading and writing: */
1079     tlb->tme_bus_tlb_emulator_off_read = tlb->tme_bus_tlb_emulator_off_write;
1080   }
1081 
1082   /* otherwise, this address doesn't fall in the bus subregion for memory: */
1083   else {
1084 
1085     /* search the other bus subregions: */
1086     for (subregion_i = 0;; subregion_i++) {
1087 
1088       /* this address must be in some subregion: */
1089       assert (subregion_i < TME_SUNFB_BUS_SUBREGIONS_MAX);
1090 
1091       /* if this subregion is defined, and this address falls in it: */
1092       if (sunfb->tme_sunfb_bus_handlers[subregion_i] != NULL
1093 	  && (sunfb->tme_sunfb_bus_subregions[subregion_i].tme_bus_subregion_address_first
1094 	      <= address)
1095 	  && (address
1096 	      <= sunfb->tme_sunfb_bus_subregions[subregion_i].tme_bus_subregion_address_last)) {
1097 
1098 	/* this TLB entry covers this range: */
1099 	tlb->tme_bus_tlb_addr_first = sunfb->tme_sunfb_bus_subregions[subregion_i].tme_bus_subregion_address_first;
1100 	tlb->tme_bus_tlb_addr_last = sunfb->tme_sunfb_bus_subregions[subregion_i].tme_bus_subregion_address_last;
1101 
1102 	/* bus cycles to this range are handled by this handler: */
1103 	tlb->tme_bus_tlb_cycle = sunfb->tme_sunfb_bus_handlers[subregion_i];
1104 
1105 	break;
1106       }
1107     }
1108   }
1109 
1110   /* the fast reading and writing rwlock: */
1111   tlb->tme_bus_tlb_rwlock = &sunfb->tme_sunfb_rwlock;
1112 
1113   /* allow reading and writing: */
1114   tlb->tme_bus_tlb_cycles_ok = TME_BUS_CYCLE_READ | TME_BUS_CYCLE_WRITE;
1115 
1116   /* our bus cycle handler private data: */
1117   tlb->tme_bus_tlb_cycle_private = _sunfb;
1118 
1119   return (TME_OK);
1120 }
1121 
1122 #if TME_SUNFB_BUS_TRANSITION
1123 
1124 /* this is the bus cycle transition glue: */
1125 int
tme_sunfb_bus_cycle_transition(void * _sunfb,struct tme_bus_cycle * master_cycle,void (* handler)_TME_P ((struct tme_sunfb *,struct tme_bus_cycle *,tme_uint32_t *,struct tme_completion *)))1126 tme_sunfb_bus_cycle_transition(void *_sunfb,
1127 			       struct tme_bus_cycle *master_cycle,
1128 			       void (*handler) _TME_P((struct tme_sunfb *,
1129 						       struct tme_bus_cycle *,
1130 						       tme_uint32_t *,
1131 						       struct tme_completion *)))
1132 {
1133   struct tme_completion completion_buffer;
1134   struct tme_sunfb *sunfb;
1135   tme_uint32_t master_fast_cycle_types;
1136 
1137   /* initialize the completion buffer: */
1138   tme_completion_init(&completion_buffer);
1139 
1140 #ifndef NDEBUG
1141 
1142   /* initialize the completion: */
1143   completion_buffer.tme_completion_error = 0x71aa;
1144 
1145 #endif /* NDEBUG */
1146 
1147   /* recover our data structure: */
1148   sunfb = (struct tme_sunfb *) _sunfb;
1149 
1150   /* lock the mutex: */
1151   tme_mutex_lock(&sunfb->tme_sunfb_mutex);
1152 
1153   /* run the cycle handler: */
1154   (*handler)
1155     (sunfb,
1156      master_cycle,
1157      &master_fast_cycle_types,
1158      &completion_buffer);
1159 
1160   /* unlock the mutex: */
1161   tme_mutex_unlock(&sunfb->tme_sunfb_mutex);
1162 
1163   /* check the completion: */
1164   assert (completion_buffer.tme_completion_error != (int) 0x71aa);
1165 
1166   return (completion_buffer.tme_completion_error);
1167 }
1168 
1169 #endif /* TME_SUNFB_BUS_TRANSITION */
1170 
1171 /* this makes a new framebuffer connection: */
1172 static int
_tme_sunfb_connection_make(struct tme_connection * conn,unsigned int state)1173 _tme_sunfb_connection_make(struct tme_connection *conn, unsigned int state)
1174 {
1175   struct tme_sunfb *sunfb;
1176   struct tme_fb_connection *conn_fb;
1177   struct tme_fb_connection *conn_fb_other;
1178   int rc;
1179 
1180   /* recover our data structures: */
1181   sunfb = conn->tme_connection_element->tme_element_private;
1182   conn_fb = (struct tme_fb_connection *) conn;
1183   conn_fb_other = (struct tme_fb_connection *) conn->tme_connection_other;
1184 
1185   /* both sides must be framebuffer connections: */
1186   assert(conn->tme_connection_type == TME_CONNECTION_FRAMEBUFFER);
1187   assert(conn->tme_connection_other->tme_connection_type == TME_CONNECTION_FRAMEBUFFER);
1188 
1189   /* lock our mutex: */
1190   tme_mutex_lock(&sunfb->tme_sunfb_mutex);
1191 
1192   /* we're always set up to answer calls across the connection, so we
1193      only have to do work when the connection has gone full, namely
1194      taking the other side of the connection: */
1195   if (state == TME_CONNECTION_FULL) {
1196 
1197     /* if the other side of the connection is not supplying specific
1198        displayed memory that it wants us to use: */
1199     if (conn_fb->tme_fb_connection_buffer == NULL) {
1200 
1201       /* allocate displayed memory: */
1202       rc = tme_fb_xlat_alloc_src(conn_fb);
1203       assert (rc == TME_OK);
1204     }
1205 
1206     /* if this framebuffer just maps the displayed memory on the bus,
1207        do that: */
1208     if (sunfb->tme_sunfb_memory == NULL) {
1209       sunfb->tme_sunfb_memory = conn_fb->tme_fb_connection_buffer;
1210     }
1211 
1212     /* save our connection: */
1213     sunfb->tme_sunfb_fb_connection = conn_fb_other;
1214   }
1215 
1216   /* unlock our mutex: */
1217   tme_mutex_unlock(&sunfb->tme_sunfb_mutex);
1218 
1219   return (TME_OK);
1220 }
1221 
1222 /* this breaks a connection: */
1223 static int
_tme_sunfb_connection_break(struct tme_connection * conn,unsigned int state)1224 _tme_sunfb_connection_break(struct tme_connection *conn, unsigned int state)
1225 {
1226   abort();
1227 }
1228 
1229 /* this makes a new connection side for a sunfb: */
1230 static int
_tme_sunfb_connections_new(struct tme_element * element,const char * const * args,struct tme_connection ** _conns,char ** _output)1231 _tme_sunfb_connections_new(struct tme_element *element,
1232 			   const char * const *args,
1233 			   struct tme_connection **_conns,
1234 			   char **_output)
1235 {
1236   struct tme_sunfb *sunfb;
1237   struct tme_fb_connection *conn_fb;
1238   struct tme_connection *conn;
1239   int rc;
1240 
1241   /* recover our data structure: */
1242   sunfb = (struct tme_sunfb *) element->tme_element_private;
1243 
1244   /* make the generic bus device connection side: */
1245   rc = tme_bus_device_connections_new(element, args, _conns, _output);
1246   if (rc != TME_OK) {
1247     return (rc);
1248   }
1249 
1250   /* if we don't have a framebuffer connection, make one: */
1251   if (sunfb->tme_sunfb_fb_connection == NULL) {
1252 
1253     /* allocate the new framebuffer connection: */
1254     conn_fb = tme_new0(struct tme_fb_connection, 1);
1255     conn = &conn_fb->tme_fb_connection;
1256 
1257     /* fill in the generic connection: */
1258     conn->tme_connection_next = *_conns;
1259     conn->tme_connection_type = TME_CONNECTION_FRAMEBUFFER;
1260     conn->tme_connection_score = tme_fb_connection_score;
1261     conn->tme_connection_make = _tme_sunfb_connection_make;
1262     conn->tme_connection_break = _tme_sunfb_connection_break;
1263 
1264     /* fill in the framebuffer connection: */
1265     conn_fb->tme_fb_connection_mode_change = NULL;
1266     conn_fb->tme_fb_connection_update = NULL;
1267 
1268     /* class: */
1269     conn_fb->tme_fb_connection_class = sunfb->tme_sunfb_class;
1270 
1271     /* depth: */
1272     conn_fb->tme_fb_connection_depth = sunfb->tme_sunfb_depth;
1273 
1274     /* width and height: */
1275     conn_fb->tme_fb_connection_width = tme_sunfb_size_width(sunfb->tme_sunfb_size);
1276     conn_fb->tme_fb_connection_height = tme_sunfb_size_height(sunfb->tme_sunfb_size);
1277 
1278     /* we skip no pixels at the start of the scanline: */
1279     conn_fb->tme_fb_connection_skipx = 0;
1280 
1281     /* we pad to 32-bit boundaries: */
1282     conn_fb->tme_fb_connection_scanline_pad = 32;
1283 
1284     /* we are big-endian: */
1285     conn_fb->tme_fb_connection_order = TME_ENDIAN_BIG;
1286 
1287     /* we don't allocate memory until the connection is made, in case
1288        the other side of the connection wants to provide us with a
1289        specific memory region to use (maybe we're on a system with
1290        real matching hardware and we can write directly to its buffer): */
1291     conn_fb->tme_fb_connection_buffer = NULL;
1292 
1293     /* assume that bits per pixel is the same as depth: */
1294     conn_fb->tme_fb_connection_bits_per_pixel = sunfb->tme_sunfb_depth;
1295 
1296     /* assume that our pixels don't have subfields: */
1297     conn_fb->tme_fb_connection_mask_g = 0;
1298     conn_fb->tme_fb_connection_mask_r = 0;
1299     conn_fb->tme_fb_connection_mask_b = 0;
1300 
1301     /* set any update function: */
1302     conn_fb->tme_fb_connection_update = sunfb->tme_sunfb_memory_update;
1303 
1304     /* if this is a bwtwo: */
1305     if (_TME_SUNFB_IS_BWTWO(sunfb)) {
1306 
1307       /* intensities are a single bit, linearly mapped, but inverted: */
1308       conn_fb->tme_fb_connection_map_bits = 1;
1309       conn_fb->tme_fb_connection_map_g = NULL;
1310       conn_fb->tme_fb_connection_map_r = NULL;
1311       conn_fb->tme_fb_connection_map_b = NULL;
1312       conn_fb->tme_fb_connection_inverted = TRUE;
1313     }
1314 
1315     /* otherwise, this is one of the eight-bit color framebuffers: */
1316     else {
1317 
1318       /* intensities are eight bits and index mapped: */
1319       conn_fb->tme_fb_connection_map_bits = 8;
1320       conn_fb->tme_fb_connection_map_g = sunfb->tme_sunfb_cmap_g;
1321       conn_fb->tme_fb_connection_map_r = sunfb->tme_sunfb_cmap_r;
1322       conn_fb->tme_fb_connection_map_b = sunfb->tme_sunfb_cmap_b;
1323     }
1324 
1325     /* return the connection side possibility: */
1326     *_conns = conn;
1327   }
1328 
1329   /* done: */
1330   return (TME_OK);
1331 }
1332 
1333 /* the new Sun framebuffer function: */
1334 int
tme_sunfb_new(struct tme_sunfb * sunfb,const char * const * args,char ** _output)1335 tme_sunfb_new(struct tme_sunfb *sunfb,
1336 	      const char * const *args,
1337 	      char **_output)
1338 {
1339   struct tme_bus_subregion *subregion;
1340   const struct tme_bus_subregion **_subregion_prev;
1341   unsigned int subregion_i;
1342   const char *sunfb_type_string;
1343   const char *sunfb_size_string;
1344   tme_uint32_t sunfb_size;
1345   tme_bus_addr_t fb_size;
1346   tme_uint32_t sunfb_p4;
1347   tme_uint8_t sunfb_s4_status;
1348   int arg_i;
1349   int usage;
1350 
1351   /* check our arguments: */
1352   usage = 0;
1353   sunfb_type_string = NULL;
1354   sunfb_size_string = NULL;
1355   arg_i = 1;
1356   for (;;) {
1357 
1358     /* the framebuffer type: */
1359     if (TME_ARG_IS(args[arg_i + 0], "type")
1360 	&& sunfb_type_string == NULL
1361 	&& sunfb->tme_sunfb_type_set != NULL) {
1362       sunfb_type_string = args[arg_i + 1];
1363       if (sunfb_type_string == NULL
1364 	  || (*sunfb->tme_sunfb_type_set)(sunfb, sunfb_type_string) != NULL) {
1365 	usage = TRUE;
1366 	break;
1367       }
1368       arg_i += 2;
1369     }
1370 
1371     /* the framebuffer size: */
1372     else if (TME_ARG_IS(args[arg_i + 0], "size")
1373 	     && sunfb_size_string == NULL) {
1374       sunfb_size_string = args[arg_i + 1];
1375       if (sunfb_size_string == NULL) {
1376 	usage = TRUE;
1377 	break;
1378       }
1379       arg_i += 2;
1380     }
1381 
1382     /* if we ran out of arguments: */
1383     else if (args[arg_i] == NULL) {
1384 
1385       break;
1386     }
1387 
1388     /* otherwise this is a bad argument: */
1389     else {
1390       tme_output_append_error(_output,
1391 			      "%s %s, ",
1392 			      args[arg_i],
1393 			      _("unexpected"));
1394       usage = TRUE;
1395       break;
1396     }
1397   }
1398 
1399   /* set some common defaults based on framebuffer type: */
1400 
1401   /* if this is a P4 framebuffer: */
1402   if (_TME_SUNFB_IS_P4(sunfb)) {
1403 
1404     /* default possible P4 sizes: */
1405     if (sunfb->tme_sunfb_size == 0) {
1406       sunfb->tme_sunfb_size
1407 	= (TME_SUNFB_SIZE_1600_1280
1408 	   | TME_SUNFB_SIZE_1152_900
1409 	   | TME_SUNFB_SIZE_1024_1024
1410 	   | TME_SUNFB_SIZE_1280_1024
1411 	   | TME_SUNFB_SIZE_1440_1440);
1412     }
1413 
1414     /* the memory address can't be zero: */
1415     assert (sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_first != 0);
1416 
1417     /* the P4 register is always at the same offset: */
1418     sunfb->tme_sunfb_bus_subregion_regs.tme_bus_subregion_address_first = TME_SUNFB_P4_OFFSET_P4;
1419 
1420     /* the default size of the P4 register bus subregion: */
1421     if (sunfb->tme_sunfb_bus_subregion_regs.tme_bus_subregion_address_last == 0) {
1422       sunfb->tme_sunfb_bus_subregion_regs.tme_bus_subregion_address_last
1423 	= (sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_first
1424 	   - 1);
1425     }
1426   }
1427 
1428 
1429   /* if this is an S4 framebuffer: */
1430   if (_TME_SUNFB_IS_S4(sunfb)) {
1431 
1432     /* default possible S4 framebuffer sizes: */
1433     if (sunfb->tme_sunfb_size == 0) {
1434       sunfb->tme_sunfb_size
1435 	= (TME_SUNFB_SIZE_1024_768
1436 	   | TME_SUNFB_SIZE_1152_900
1437 	   | TME_SUNFB_SIZE_1280_1024
1438 	   | TME_SUNFB_SIZE_1600_1280);
1439     }
1440 
1441     /* the default memory address: */
1442     if (sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_first == 0) {
1443       sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_first = TME_SUNFB_S4_OFFSET_MEMORY;
1444     }
1445 
1446     /* the S4 registers are always at the same offset: */
1447     sunfb->tme_sunfb_bus_subregion_regs.tme_bus_subregion_address_first = TME_SUNFB_S4_OFFSET_REGS;
1448 
1449     /* the default size of the S4 register bus subregion: */
1450     if (sunfb->tme_sunfb_bus_subregion_regs.tme_bus_subregion_address_last == 0) {
1451       sunfb->tme_sunfb_bus_subregion_regs.tme_bus_subregion_address_last
1452 	= (sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_first
1453 	   - 1);
1454     }
1455   }
1456 
1457   /* we must have some possible sizes: */
1458   assert (sunfb->tme_sunfb_size != 0 || usage);
1459 
1460   /* if no specific size is given: */
1461   if (sunfb_size_string == NULL) {
1462 
1463     /* use the first size supported by this framebuffer, which will
1464        usually be 1152x900: */
1465     sunfb_size = sunfb->tme_sunfb_size;
1466     sunfb_size = (sunfb_size & ~(sunfb_size - 1));
1467   }
1468 
1469   /* otherwise, convert the specific size: */
1470   else {
1471     sunfb_size = tme_sunfb_size(sunfb_size_string);
1472   }
1473 
1474   /* if the size is not supported by this framebuffer: */
1475   if ((sunfb->tme_sunfb_size & sunfb_size) == 0) {
1476     usage = TRUE;
1477   }
1478 
1479   if (usage) {
1480 
1481     /* start the usage message: */
1482     tme_output_append_error(_output,
1483 			    "%s %s",
1484 			    _("usage"),
1485 			    args[0]);
1486 
1487     /* if this framebuffer has types, append a type argument to the
1488        usage message: */
1489     if (sunfb->tme_sunfb_type_set != NULL) {
1490       sunfb_type_string = (*sunfb->tme_sunfb_type_set)(sunfb, NULL);
1491       tme_output_append_error(_output, " type { %s }", sunfb_type_string);
1492     }
1493 
1494     /* append the supported types to the usage message: */
1495     tme_output_append_error(_output,
1496 			    " [ size {");
1497     for (sunfb_size = sunfb->tme_sunfb_size;
1498 	 sunfb_size != 0;
1499 	 sunfb_size &= (sunfb_size - 1)) {
1500       switch (sunfb_size & ~(sunfb_size - 1)) {
1501       default: assert(FALSE);
1502       case TME_SUNFB_SIZE_1152_900: sunfb_size_string = "1152x900"; break;
1503       case TME_SUNFB_SIZE_1024_1024: sunfb_size_string = "1024x1024"; break;
1504       case TME_SUNFB_SIZE_1280_1024: sunfb_size_string = "1280x1024"; break;
1505       case TME_SUNFB_SIZE_1600_1280: sunfb_size_string = "1600x1280"; break;
1506       case TME_SUNFB_SIZE_1440_1440: sunfb_size_string = "1440x1440"; break;
1507       case TME_SUNFB_SIZE_1024_768: sunfb_size_string = "1024x768"; break;
1508       case TME_SUNFB_SIZE_640_480: sunfb_size_string = "640x480"; break;
1509       }
1510       tme_output_append_error(_output, " %s", sunfb_size_string);
1511     }
1512     tme_output_append_error(_output, " } ]");
1513 
1514     /* return the error: */
1515     return (EINVAL);
1516   }
1517 
1518   /* finish initializing the sunfb structure: */
1519   tme_mutex_init(&sunfb->tme_sunfb_mutex);
1520   tme_rwlock_init(&sunfb->tme_sunfb_rwlock);
1521 
1522   /* set the size: */
1523   sunfb->tme_sunfb_size = sunfb_size;
1524 
1525   /* calculate the number of bytes of displayed framebuffer memory: */
1526   fb_size = tme_sunfb_size_width(sunfb->tme_sunfb_size);
1527   fb_size *= tme_sunfb_size_height(sunfb->tme_sunfb_size);
1528   if (_TME_SUNFB_IS_BWTWO(sunfb)) {
1529     fb_size /= 8;
1530   }
1531 
1532   /* set the (relative) bus address of the last byte of displayed
1533      memory: */
1534   sunfb->tme_sunfb_memory_address_last_displayed
1535     = (sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_first
1536        + fb_size
1537        - 1);
1538 
1539   /* assume that the real number of bytes of memory is the number of
1540      bytes displayed, rounded up to the nearest power of two: */
1541   if ((fb_size & (fb_size - 1)) != 0) {
1542     for (; (fb_size & (fb_size - 1)) != 0; fb_size &= (fb_size - 1));
1543     fb_size <<= 1;
1544   }
1545 
1546   /* set the (relative) bus address of the last byte of memory: */
1547   sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_last
1548     = (sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_first
1549        + fb_size
1550        - 1);
1551 
1552   /* if we need to, allocate pad (undisplayed) framebuffer memory: */
1553   if (sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_last
1554       > sunfb->tme_sunfb_memory_address_last_displayed) {
1555 
1556     /* allocate the pad memory: */
1557     sunfb->tme_sunfb_memory_pad
1558       = tme_new0(tme_uint8_t,
1559 		 (sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_last
1560 		  - sunfb->tme_sunfb_memory_address_last_displayed));
1561   }
1562 
1563   /* if this is a P4 framebuffer: */
1564   if (_TME_SUNFB_IS_P4(sunfb)) {
1565 
1566     /* get our initial P4 register: */
1567     sunfb_p4 = tme_betoh_u32(sunfb->tme_sunfb_p4);
1568 
1569     /* if the P4 register doesn't already have something in the size
1570        field, add it: */
1571     if ((sunfb_p4 & TME_SUNFB_P4_SIZE_MASK) == 0) {
1572       switch (sunfb_size) {
1573       default: assert(FALSE);
1574       case TME_SUNFB_SIZE_1152_900: sunfb_p4 |= TME_SUNFB_P4_SIZE_1152_900; break;
1575       case TME_SUNFB_SIZE_1024_1024: sunfb_p4 |= TME_SUNFB_P4_SIZE_1024_1024; break;
1576       case TME_SUNFB_SIZE_1280_1024: sunfb_p4 |= TME_SUNFB_P4_SIZE_1280_1024; break;
1577       case TME_SUNFB_SIZE_1600_1280: sunfb_p4 |= TME_SUNFB_P4_SIZE_1600_1280; break;
1578       case TME_SUNFB_SIZE_1440_1440: sunfb_p4 |= TME_SUNFB_P4_SIZE_1440_1440; break;
1579       case TME_SUNFB_SIZE_640_480: sunfb_p4 |= TME_SUNFB_P4_SIZE_640_480; break;
1580       }
1581     }
1582 
1583     /* set video as enabled: */
1584     sunfb_p4 |= TME_SUNFB_P4_REG_VIDEO_ENABLE;
1585 
1586     /* set the initial P4 register: */
1587     sunfb->tme_sunfb_p4 = tme_htobe_u32(sunfb_p4);
1588   }
1589 
1590   /* if this is an S4 framebuffer: */
1591   if (_TME_SUNFB_IS_S4(sunfb)) {
1592 
1593     /* set the initial S4 control register: */
1594     sunfb->tme_sunfb_s4_regs.tme_sunfb_s4_regs_control
1595       = (TME_SUNFB_S4_CONTROL_VIDEO_ENABLE);
1596 
1597     /* set the initial S4 status register: */
1598     switch (sunfb_size) {
1599     default: assert(FALSE);
1600     case TME_SUNFB_SIZE_1152_900: sunfb_s4_status = TME_SUNFB_S4_STATUS_SIZE_1152_900; break;
1601     case TME_SUNFB_SIZE_1024_768: sunfb_s4_status = TME_SUNFB_S4_STATUS_SIZE_1024_768; break;
1602     case TME_SUNFB_SIZE_1280_1024: sunfb_s4_status = TME_SUNFB_S4_STATUS_SIZE_1280_1024; break;
1603     case TME_SUNFB_SIZE_1600_1280: sunfb_s4_status = TME_SUNFB_S4_STATUS_SIZE_1600_1280; break;
1604     }
1605     sunfb->tme_sunfb_s4_regs.tme_sunfb_s4_regs_status
1606       = (sunfb_s4_status
1607 	 | (_TME_SUNFB_IS_BWTWO(sunfb)
1608 	    ? TME_SUNFB_S4_STATUS_ID_MONO
1609 	    : TME_SUNFB_S4_STATUS_ID_COLOR));
1610   }
1611 
1612   /* make sure that the interrupt signal has been defined.  no known
1613      framebuffer uses a priority zero interrupt: */
1614 #if TME_BUS_SIGNAL_INT(0) != 0
1615 #error "TME_BUS_SIGNAL_INT() changed"
1616 #endif
1617   assert (sunfb->tme_sunfb_bus_signal_int != TME_BUS_SIGNAL_INT(0));
1618 
1619   /* if this is a color framebuffer: */
1620   if (!_TME_SUNFB_IS_BWTWO(sunfb)) {
1621 
1622     /* if we don't have a specific memory update function, use the
1623        default: */
1624     if (sunfb->tme_sunfb_memory_update == NULL) {
1625       sunfb->tme_sunfb_memory_update = tme_sunfb_memory_update;
1626     }
1627   }
1628 
1629   /* make all of the defined subregions into a list.  the memory
1630      subregion is always in the list, and it is first: */
1631   _subregion_prev = &sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_next;
1632   for (subregion_i = 0;
1633        subregion_i < TME_SUNFB_BUS_SUBREGIONS_MAX;
1634        subregion_i++) {
1635     if (sunfb->tme_sunfb_bus_handlers[subregion_i] != NULL) {
1636       subregion = &sunfb->tme_sunfb_bus_subregions[subregion_i];
1637       *_subregion_prev = subregion;
1638       _subregion_prev = &subregion->tme_bus_subregion_next;
1639     }
1640   }
1641   *_subregion_prev = NULL;
1642 
1643   /* initialize our simple bus device descriptor: */
1644   sunfb->tme_sunfb_device.tme_bus_device_tlb_fill = _tme_sunfb_tlb_fill;
1645 
1646   /* fill the element: */
1647   sunfb->tme_sunfb_element->tme_element_private = sunfb;
1648   sunfb->tme_sunfb_element->tme_element_connections_new = _tme_sunfb_connections_new;
1649 
1650   /* initialize the timeout thread condition: */
1651   tme_cond_init(&sunfb->tme_sunfb_callout_cond);
1652 
1653   /* start the callout thread: */
1654   tme_thread_create((tme_thread_t) _tme_sunfb_callout_thread, sunfb);
1655 
1656   return (TME_OK);
1657 }
1658 
1659 /* the new sun cgthree function: */
1660 int
tme_sun_cgthree(struct tme_element * element,const char * const * args,char ** _output)1661 tme_sun_cgthree(struct tme_element *element, const char * const *args, char **_output)
1662 {
1663   struct tme_sunfb *sunfb;
1664   tme_uint8_t *cmap;
1665   int rc;
1666 
1667   /* start the sunfb structure: */
1668   sunfb = tme_new0(struct tme_sunfb, 1);
1669   sunfb->tme_sunfb_element = element;
1670 
1671   /* initialize the sunfb structure: */
1672   sunfb->tme_sunfb_class = TME_FB_XLAT_CLASS_COLOR;
1673   sunfb->tme_sunfb_depth = 8;
1674   sunfb->tme_sunfb_bus_handler_regs = tme_sunfb_bus_cycle_s4;
1675   sunfb->tme_sunfb_flags
1676     |= (TME_SUNFB_FLAG_BT458_CMAP_PACKED
1677 	| TME_SUNFB_FLAG_BT458_BYTE_D0_D7);
1678   sunfb->tme_sunfb_bus_signal_int = TME_BUS_SIGNAL_INT(5);
1679 
1680   /* if the generic initialization fails: */
1681   rc = tme_sunfb_new(sunfb, args, _output);
1682   if (rc) {
1683 
1684     /* free the sunfb structure and return the error: */
1685     tme_free(sunfb);
1686     return (rc);
1687   }
1688 
1689   /* allocate the colormap arrays: */
1690   cmap = tme_new0(tme_uint8_t, 256 * 3);
1691   sunfb->tme_sunfb_cmap_g = &cmap[256 * 0];
1692   sunfb->tme_sunfb_cmap_r = &cmap[256 * 1];
1693   sunfb->tme_sunfb_cmap_b = &cmap[256 * 2];
1694   sunfb->tme_sunfb_bt458.tme_bt458_cmap_g = sunfb->tme_sunfb_cmap_g;
1695   sunfb->tme_sunfb_bt458.tme_bt458_cmap_r = sunfb->tme_sunfb_cmap_r;
1696   sunfb->tme_sunfb_bt458.tme_bt458_cmap_b = sunfb->tme_sunfb_cmap_b;
1697 
1698   return (TME_OK);
1699 }
1700