1 /* $Id: sun-cgsix.c,v 1.3 2010/06/05 19:16:12 fredette Exp $ */
2
3 /* machine/sun/sun-cgsix.c - Sun cgsix emulation: */
4
5 /*
6 * Copyright (c) 2009 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-cgsix.c,v 1.3 2010/06/05 19:16:12 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 /* cgsix types: */
48 #define TME_SUNCG6_TYPE_NULL (0)
49 #define TME_SUNCG6_TYPE_501_2325 (1)
50
51 /* register subregions: */
52 #define tme_suncg6_bus_subregion_p4 tme_suncg6_sunfb.tme_sunfb_bus_subregion_regs
53 #define tme_suncg6_bus_handler_p4 tme_suncg6_sunfb.tme_sunfb_bus_handler_regs
54 #define tme_suncg6_bus_subregion_fbc tme_suncg6_sunfb.tme_sunfb_bus_subregions[1]
55 #define tme_suncg6_bus_handler_fbc tme_suncg6_sunfb.tme_sunfb_bus_handlers[1]
56 #define tme_suncg6_bus_subregion_dac tme_suncg6_sunfb.tme_sunfb_bus_subregions[2]
57 #define tme_suncg6_bus_handler_dac tme_suncg6_sunfb.tme_sunfb_bus_handlers[2]
58 #define tme_suncg6_bus_subregion_fhc_thc tme_suncg6_sunfb.tme_sunfb_bus_subregions[4]
59 #define tme_suncg6_bus_handler_fhc_thc tme_suncg6_sunfb.tme_sunfb_bus_handlers[4]
60 #define tme_suncg6_bus_subregion_tec tme_suncg6_sunfb.tme_sunfb_bus_subregions[3]
61 #define tme_suncg6_bus_handler_tec tme_suncg6_sunfb.tme_sunfb_bus_handlers[3]
62 #define tme_suncg6_bus_subregion_alt tme_suncg6_sunfb.tme_sunfb_bus_subregions[6]
63 #define tme_suncg6_bus_handler_alt tme_suncg6_sunfb.tme_sunfb_bus_handlers[6]
64
65 /* this converts a group member to a register offset: */
66 #define _TME_SUNCG6_REG_X(module_cap, module, n, x) \
67 (_TME_CONCAT4(TME_SUNCG6_REG_,module_cap,_GROUP,n) \
68 + ((tme_uint8_t *) &((struct tme_suncg6 *) 0) \
69 ->_TME_CONCAT4(tme_suncg6_,module,_group,n) \
70 ._TME_CONCAT4(tme_suncg6_,module,_,x)) \
71 - ((tme_uint8_t *) &((struct tme_suncg6 *) 0) \
72 ->_TME_CONCAT4(tme_suncg6_,module,_group,n)))
73
74 /* this expands part of a large ternary expression that converts a
75 register address into pointer to a register: */
76 #define TME_SUNCG6_REG_POINTER(suncg6, reg, module_cap, module, n)\
77 (((reg) \
78 >= _TME_CONCAT4(TME_SUNCG6_REG_,module_cap,_GROUP,n)) \
79 && ((reg) \
80 < (_TME_CONCAT4(TME_SUNCG6_REG_,module_cap,_GROUP,n) \
81 + sizeof((suncg6) \
82 ->_TME_CONCAT4(tme_suncg6_,module,_group,n)))))\
83 ? (((tme_suncg6_reg_t *) \
84 &((suncg6) \
85 ->_TME_CONCAT4(tme_suncg6_,module,_group,n))) \
86 + (((reg) \
87 - _TME_CONCAT4(TME_SUNCG6_REG_,module_cap,_GROUP,n)) \
88 / sizeof(tme_suncg6_reg_t)))
89
90 /* some register offsets and sizes: */
91 #define TME_SUNCG6_REG_DAC (0x200000)
92 #define TME_SUNCG6_REG_ALT (0x280000)
93 #define TME_SUNCG6_SIZ_ALT (0x1000)
94 #define TME_SUNCG6_REG_THC(n,x) _TME_SUNCG6_REG_X(THC,thc,n,x)
95 #define TME_SUNCG6_SIZ_THC (0x1000)
96 #define TME_SUNCG6_REG_FBC(n,x) _TME_SUNCG6_REG_X(FBC,fbc,n,x)
97 #define TME_SUNCG6_REG_TEC(n,x) _TME_SUNCG6_REG_X(TEC,tec,n,x)
98 #define TME_SUNCG6_TEC_SIZE (0x1000)
99
100 /* the FHC register: */
101 #define TME_SUNCG6_FHC_ID_MASK (0xff000000)
102 #define TME_SUNCG6_FHC_REVISION_MASK (0x00f00000)
103 #define TME_SUNCG6_FHC_DISABLE_FROP (0x00080000)
104 #define TME_SUNCG6_FHC_DISABLE_ROW (0x00040000)
105 #define TME_SUNCG6_FHC_DISABLE_SRC (0x00020000)
106 #define TME_SUNCG6_FHC_DISABLE_DST (0x00010000)
107 #define TME_SUNCG6_FHC_RESET (0x00008000)
108 #define TME_SUNCG6_FHC_ENDIAN_LITTLE (0x00002000)
109 #define TME_SUNCG6_FHC_SIZE_MASK (0x00001800)
110 #define TME_SUNCG6_FHC_SIZE_1024_768 (0x00000000)
111 #define TME_SUNCG6_FHC_SIZE_1152_900 (0x00000800)
112 #define TME_SUNCG6_FHC_SIZE_1280_1024 (0x00001000)
113 #define TME_SUNCG6_FHC_SIZE_1600_1280 (0x00001800)
114 #define TME_SUNCG6_FHC_CPU_MASK (0x00000600)
115 #define TME_SUNCG6_FHC_CPU_SPARC (0x00000000)
116 #define TME_SUNCG6_FHC_CPU_68K (0x00000200)
117 #define TME_SUNCG6_FHC_CPU_IA32 (0x00000400)
118 #define TME_SUNCG6_FHC_TEST (0x00000100)
119 #define TME_SUNCG6_FHC_TESTX_MASK (0x000000f0)
120 #define TME_SUNCG6_FHC_TESTY_MASK (0x0000000f)
121
122 /* the THC miscellaneous register: */
123 #define TME_SUNCG6_THC_MISC_UNKNOWN_20 (0xfff00000)
124 #define TME_SUNCG6_THC_MISC_REVISION_MASK (0x000f0000)
125 #define TME_SUNCG6_THC_MISC_UNKNOWN_13 (0x0000e000)
126 #define TME_SUNCG6_THC_MISC_RESET (0x00001000)
127 #define TME_SUNCG6_THC_MISC_UNKNOWN_11 (0x00000800)
128 #define TME_SUNCG6_THC_MISC_ENABLE_VIDEO (0x00000400)
129 #define TME_SUNCG6_THC_MISC_SYNC (0x00000200)
130 #define TME_SUNCG6_THC_MISC_VSYNC (0x00000100)
131 #define TME_SUNCG6_THC_MISC_ENABLE_SYNC (0x00000080)
132 #define TME_SUNCG6_THC_MISC_CURSOR_RESOLUTION (0x00000040)
133 #define TME_SUNCG6_THC_MISC_INT_ENABLE (0x00000020)
134 #define TME_SUNCG6_THC_MISC_INT_ACTIVE (0x00000010)
135 #define TME_SUNCG6_THC_MISC_UNKNOWN_0 (0x0000000f)
136
137 /* the FBC rasterop register: */
138 #define TME_SUNCG6_FBC_RASTEROP_PLANE_ONES (0x80000000)
139 #define TME_SUNCG6_FBC_RASTEROP_PLANE_ZEROES (0x40000000)
140 #define TME_SUNCG6_FBC_RASTEROP_PIXEL_ONES (0x20000000)
141 #define TME_SUNCG6_FBC_RASTEROP_PIXEL_ZEROES (0x10000000)
142 #define TME_SUNCG6_FBC_RASTEROP_PATTERN_ONES (0x08000000)
143 #define TME_SUNCG6_FBC_RASTEROP_PATTERN_ZEROES (0x04000000)
144 #define TME_SUNCG6_FBC_RASTEROP_POLYG_NONOVERLAP (0x02000000)
145 #define TME_SUNCG6_FBC_RASTEROP_POLYG_OVERLAP (0x01000000)
146 #define TME_SUNCG6_FBC_RASTEROP_ATTR_SUPP (0x00800000)
147 #define TME_SUNCG6_FBC_RASTEROP_ATTR_UNSUPP (0x00400000)
148 #define TME_SUNCG6_FBC_RASTEROP_RAST_BOOL (0x00000000)
149 #define TME_SUNCG6_FBC_RASTEROP_RAST_LINEAR (0x00020000)
150 #define TME_SUNCG6_FBC_RASTEROP_PLOT_PLOT (0x00000000)
151 #define TME_SUNCG6_FBC_RASTEROP_PLOT_UNPLOT (0x00010000)
152 #define TME_SUNCG6_FBC_RASTEROP_ROP_11_1(x) ((x) << 14)
153 #define TME_SUNCG6_FBC_RASTEROP_ROP_11_0(x) ((x) << 12)
154 #define TME_SUNCG6_FBC_RASTEROP_ROP_10_1(x) ((x) << 10)
155 #define TME_SUNCG6_FBC_RASTEROP_ROP_10_0(x) ((x) << 8)
156 #define TME_SUNCG6_FBC_RASTEROP_ROP_01_1(x) ((x) << 6)
157 #define TME_SUNCG6_FBC_RASTEROP_ROP_01_0(x) ((x) << 4)
158 #define TME_SUNCG6_FBC_RASTEROP_ROP_00_1(x) ((x) << 2)
159 #define TME_SUNCG6_FBC_RASTEROP_ROP_00_0(x) ((x) << 0)
160 #define TME_SUNCG6_FBC_RASTEROP_ROP_CLEAR (0x0)
161 #define TME_SUNCG6_FBC_RASTEROP_ROP_INVERT (0x1)
162 #define TME_SUNCG6_FBC_RASTEROP_ROP_NOP (0x2)
163 #define TME_SUNCG6_FBC_RASTEROP_ROP_SET (0x3)
164
165 /* common FBC rasterop functions: */
166
167 /* copy: */
168 #define TME_SUNCG6_FBC_RASTEROP_FUNC_COPY \
169 (TME_SUNCG6_FBC_RASTEROP_PLANE_ONES \
170 | TME_SUNCG6_FBC_RASTEROP_PIXEL_ONES \
171 | TME_SUNCG6_FBC_RASTEROP_PATTERN_ONES \
172 | TME_SUNCG6_FBC_RASTEROP_POLYG_OVERLAP \
173 | TME_SUNCG6_FBC_RASTEROP_ATTR_SUPP \
174 | TME_SUNCG6_FBC_RASTEROP_ROP_11_1(TME_SUNCG6_FBC_RASTEROP_ROP_SET) \
175 | TME_SUNCG6_FBC_RASTEROP_ROP_11_0(TME_SUNCG6_FBC_RASTEROP_ROP_CLEAR) \
176 | TME_SUNCG6_FBC_RASTEROP_ROP_10_1(TME_SUNCG6_FBC_RASTEROP_ROP_SET) \
177 | TME_SUNCG6_FBC_RASTEROP_ROP_10_0(TME_SUNCG6_FBC_RASTEROP_ROP_CLEAR) \
178 | TME_SUNCG6_FBC_RASTEROP_ROP_01_1(TME_SUNCG6_FBC_RASTEROP_ROP_SET) \
179 | TME_SUNCG6_FBC_RASTEROP_ROP_01_0(TME_SUNCG6_FBC_RASTEROP_ROP_CLEAR) \
180 | TME_SUNCG6_FBC_RASTEROP_ROP_00_1(TME_SUNCG6_FBC_RASTEROP_ROP_SET) \
181 | TME_SUNCG6_FBC_RASTEROP_ROP_00_0(TME_SUNCG6_FBC_RASTEROP_ROP_CLEAR))
182
183 /* fill: */
184 #define TME_SUNCG6_FBC_RASTEROP_FUNC_FILL \
185 (TME_SUNCG6_FBC_RASTEROP_PLANE_ONES \
186 | TME_SUNCG6_FBC_RASTEROP_PIXEL_ONES \
187 | TME_SUNCG6_FBC_RASTEROP_PATTERN_ONES \
188 | TME_SUNCG6_FBC_RASTEROP_POLYG_OVERLAP \
189 | TME_SUNCG6_FBC_RASTEROP_ATTR_SUPP \
190 | TME_SUNCG6_FBC_RASTEROP_ROP_11_1(TME_SUNCG6_FBC_RASTEROP_ROP_SET) \
191 | TME_SUNCG6_FBC_RASTEROP_ROP_11_0(TME_SUNCG6_FBC_RASTEROP_ROP_SET) \
192 | TME_SUNCG6_FBC_RASTEROP_ROP_10_1(TME_SUNCG6_FBC_RASTEROP_ROP_SET) \
193 | TME_SUNCG6_FBC_RASTEROP_ROP_10_0(TME_SUNCG6_FBC_RASTEROP_ROP_SET) \
194 | TME_SUNCG6_FBC_RASTEROP_ROP_01_1(TME_SUNCG6_FBC_RASTEROP_ROP_CLEAR) \
195 | TME_SUNCG6_FBC_RASTEROP_ROP_01_0(TME_SUNCG6_FBC_RASTEROP_ROP_CLEAR) \
196 | TME_SUNCG6_FBC_RASTEROP_ROP_00_1(TME_SUNCG6_FBC_RASTEROP_ROP_CLEAR) \
197 | TME_SUNCG6_FBC_RASTEROP_ROP_00_0(TME_SUNCG6_FBC_RASTEROP_ROP_CLEAR))
198
199 /* flip: */
200 #define TME_SUNCG6_FBC_RASTEROP_FUNC_FLIP \
201 (TME_SUNCG6_FBC_RASTEROP_PLANE_ONES \
202 | TME_SUNCG6_FBC_RASTEROP_PIXEL_ONES \
203 | TME_SUNCG6_FBC_RASTEROP_PATTERN_ONES \
204 | TME_SUNCG6_FBC_RASTEROP_POLYG_OVERLAP \
205 | TME_SUNCG6_FBC_RASTEROP_ATTR_SUPP \
206 | TME_SUNCG6_FBC_RASTEROP_ROP_11_1(TME_SUNCG6_FBC_RASTEROP_ROP_INVERT) \
207 | TME_SUNCG6_FBC_RASTEROP_ROP_11_0(TME_SUNCG6_FBC_RASTEROP_ROP_INVERT) \
208 | TME_SUNCG6_FBC_RASTEROP_ROP_10_1(TME_SUNCG6_FBC_RASTEROP_ROP_INVERT) \
209 | TME_SUNCG6_FBC_RASTEROP_ROP_10_0(TME_SUNCG6_FBC_RASTEROP_ROP_INVERT) \
210 | TME_SUNCG6_FBC_RASTEROP_ROP_01_1(TME_SUNCG6_FBC_RASTEROP_ROP_INVERT) \
211 | TME_SUNCG6_FBC_RASTEROP_ROP_01_0(TME_SUNCG6_FBC_RASTEROP_ROP_INVERT) \
212 | TME_SUNCG6_FBC_RASTEROP_ROP_00_1(TME_SUNCG6_FBC_RASTEROP_ROP_INVERT) \
213 | TME_SUNCG6_FBC_RASTEROP_ROP_00_0(TME_SUNCG6_FBC_RASTEROP_ROP_INVERT))
214
215 /* NB: I couldn't reason out how the rop?? values work. the values
216 used by X11 and the NetBSD cgsix driver make some sense, but the
217 0x6c60 used by the SUNW,501-2325 PROM for all of its blits and
218 draws is confusing: */
219 #define TME_SUNCG6_FBC_RASTEROP_FUNC_PROM \
220 (TME_SUNCG6_FBC_RASTEROP_PLANE_ONES \
221 | TME_SUNCG6_FBC_RASTEROP_PIXEL_ONES \
222 | TME_SUNCG6_FBC_RASTEROP_PATTERN_ONES \
223 | TME_SUNCG6_FBC_RASTEROP_POLYG_OVERLAP \
224 | TME_SUNCG6_FBC_RASTEROP_ATTR_SUPP \
225 | TME_SUNCG6_FBC_RASTEROP_ROP_11_1(TME_SUNCG6_FBC_RASTEROP_ROP_INVERT) \
226 | TME_SUNCG6_FBC_RASTEROP_ROP_11_0(TME_SUNCG6_FBC_RASTEROP_ROP_NOP) \
227 | TME_SUNCG6_FBC_RASTEROP_ROP_10_1(TME_SUNCG6_FBC_RASTEROP_ROP_SET) \
228 | TME_SUNCG6_FBC_RASTEROP_ROP_10_0(TME_SUNCG6_FBC_RASTEROP_ROP_CLEAR) \
229 | TME_SUNCG6_FBC_RASTEROP_ROP_01_1(TME_SUNCG6_FBC_RASTEROP_ROP_INVERT) \
230 | TME_SUNCG6_FBC_RASTEROP_ROP_01_0(TME_SUNCG6_FBC_RASTEROP_ROP_NOP) \
231 | TME_SUNCG6_FBC_RASTEROP_ROP_00_1(TME_SUNCG6_FBC_RASTEROP_ROP_CLEAR) \
232 | TME_SUNCG6_FBC_RASTEROP_ROP_00_0(TME_SUNCG6_FBC_RASTEROP_ROP_CLEAR))
233
234 /* types: */
235
236 /* the cgsix pixel is eight bits: */
237 typedef tme_uint8_t tme_suncg6_pixel_t;
238
239 /* all cgsix registers are at least 32-bit aligned: */
240 typedef tme_uint32_t tme_suncg6_reg_t;
241
242 /* the card: */
243 struct tme_suncg6 {
244
245 /* our generic Sun framebuffer: */
246 struct tme_sunfb tme_suncg6_sunfb;
247 #define tme_suncg6_mutex tme_suncg6_sunfb.tme_sunfb_mutex
248 #define tme_suncg6_bus_subregion_memory tme_suncg6_sunfb.tme_sunfb_bus_subregion_memory
249 #define tme_suncg6_bus_subregion_regs tme_suncg6_sunfb.tme_sunfb_bus_subregion_regs
250
251 /* the type of the cgsix: */
252 tme_uint32_t tme_suncg6_type;
253
254 /* the current framebuffer width and height: */
255 tme_uint32_t tme_suncg6_width;
256 tme_uint32_t tme_suncg6_height;
257
258 /* the FHC: */
259 #define TME_SUNCG6_REG_FHC (0x300000)
260 tme_suncg6_reg_t tme_suncg6_fhc;
261
262 /* the THC: */
263 #define TME_SUNCG6_REG_THC_UNKNOWN_0x0 (0x301000)
264 struct {
265 #define TME_SUNCG6_REG_THC_GROUP0 (0x301090)
266 tme_suncg6_reg_t tme_suncg6_thc_unknown_0x90;
267 tme_suncg6_reg_t tme_suncg6_thc_unknown_0x94;
268 } tme_suncg6_thc_group0;
269 struct {
270 #define TME_SUNCG6_REG_THC_GROUP1 (0x301800)
271 tme_suncg6_reg_t tme_suncg6_thc_hsync1;
272 tme_suncg6_reg_t tme_suncg6_thc_hsync2;
273 tme_suncg6_reg_t tme_suncg6_thc_hsync3;
274 tme_suncg6_reg_t tme_suncg6_thc_vsync1;
275 tme_suncg6_reg_t tme_suncg6_thc_vsync2;
276 tme_suncg6_reg_t tme_suncg6_thc_refresh;
277 tme_suncg6_reg_t tme_suncg6_thc_misc;
278 tme_suncg6_reg_t tme_suncg6_thc_unknown_0x81c[56];
279 tme_suncg6_reg_t tme_suncg6_thc_cursor_xy;
280 tme_suncg6_reg_t tme_suncg6_thc_cursor_mask[32];
281 tme_suncg6_reg_t tme_suncg6_thc_cursor_bits[32];
282 } tme_suncg6_thc_group1;
283
284 /* the FBC: */
285 struct {
286 #define TME_SUNCG6_REG_FBC_GROUP0 (0x700000)
287 tme_suncg6_reg_t tme_suncg6_fbc_unknown_0x0;
288 tme_suncg6_reg_t tme_suncg6_fbc_misc;
289 tme_suncg6_reg_t tme_suncg6_fbc_clip_check;
290 tme_suncg6_reg_t tme_suncg6_fbc_unknown_0xc;
291 tme_suncg6_reg_t tme_suncg6_fbc_status;
292 tme_suncg6_reg_t tme_suncg6_fbc_status_draw;
293 tme_suncg6_reg_t tme_suncg6_fbc_status_blit;
294 tme_suncg6_reg_t tme_suncg6_fbc_font;
295 tme_suncg6_reg_t tme_suncg6_fbc_unknown_0x20[24];
296 tme_suncg6_reg_t tme_suncg6_fbc_x0;
297 tme_suncg6_reg_t tme_suncg6_fbc_y0;
298 tme_suncg6_reg_t tme_suncg6_fbc_z0;
299 tme_suncg6_reg_t tme_suncg6_fbc_color0;
300 tme_suncg6_reg_t tme_suncg6_fbc_x1;
301 tme_suncg6_reg_t tme_suncg6_fbc_y1;
302 tme_suncg6_reg_t tme_suncg6_fbc_z1;
303 tme_suncg6_reg_t tme_suncg6_fbc_color1;
304 tme_suncg6_reg_t tme_suncg6_fbc_x2;
305 tme_suncg6_reg_t tme_suncg6_fbc_y2;
306 tme_suncg6_reg_t tme_suncg6_fbc_z2;
307 tme_suncg6_reg_t tme_suncg6_fbc_color2;
308 tme_suncg6_reg_t tme_suncg6_fbc_x3;
309 tme_suncg6_reg_t tme_suncg6_fbc_y3;
310 tme_suncg6_reg_t tme_suncg6_fbc_z3;
311 tme_suncg6_reg_t tme_suncg6_fbc_color3;
312 tme_suncg6_reg_t tme_suncg6_fbc_offx;
313 tme_suncg6_reg_t tme_suncg6_fbc_offy;
314 tme_suncg6_reg_t tme_suncg6_fbc_unknown_0xc8[2];
315 tme_suncg6_reg_t tme_suncg6_fbc_inc_x;
316 tme_suncg6_reg_t tme_suncg6_fbc_inc_y;
317 tme_suncg6_reg_t tme_suncg6_fbc_unknown_0xd8[2];
318 tme_suncg6_reg_t tme_suncg6_fbc_clip_min_x;
319 tme_suncg6_reg_t tme_suncg6_fbc_clip_min_y;
320 tme_suncg6_reg_t tme_suncg6_fbc_unknown_0xe8[2];
321 tme_suncg6_reg_t tme_suncg6_fbc_clip_max_x;
322 tme_suncg6_reg_t tme_suncg6_fbc_clip_max_y;
323 tme_suncg6_reg_t tme_suncg6_fbc_unknown_0xf8[2];
324 tme_suncg6_reg_t tme_suncg6_fbc_fg;
325 tme_suncg6_reg_t tme_suncg6_fbc_bg;
326 tme_suncg6_reg_t tme_suncg6_fbc_rasterop;
327 tme_suncg6_reg_t tme_suncg6_fbc_pm;
328 tme_suncg6_reg_t tme_suncg6_fbc_pixelm;
329 tme_suncg6_reg_t tme_suncg6_fbc_unknown_0x114[2];
330 tme_suncg6_reg_t tme_suncg6_fbc_patalign;
331 tme_suncg6_reg_t tme_suncg6_fbc_pattern[8];
332 } tme_suncg6_fbc_group0;
333 struct {
334 #define TME_SUNCG6_REG_FBC_GROUP1 (0x700900)
335 tme_suncg6_reg_t tme_suncg6_fbc_rect_abs_x;
336 tme_suncg6_reg_t tme_suncg6_fbc_rect_abs_y;
337 } tme_suncg6_fbc_group1;
338
339 /* in the FBC, the rectangle absolute coordinate registers seem to
340 be indexed: */
341 #define TME_SUNCG6_RECT_ABS_COUNT (2)
342 unsigned int tme_suncg6_fbc_rect_abs_x_i;
343 unsigned int tme_suncg6_fbc_rect_abs_y_i;
344 tme_suncg6_reg_t tme_suncg6_fbc_rect_abs_x[TME_SUNCG6_RECT_ABS_COUNT];
345 tme_suncg6_reg_t tme_suncg6_fbc_rect_abs_y[TME_SUNCG6_RECT_ABS_COUNT];
346
347 /* the TEC: */
348 struct {
349 #define TME_SUNCG6_REG_TEC_GROUP0 (0x701000)
350 tme_suncg6_reg_t tme_suncg6_tec_mv;
351 tme_suncg6_reg_t tme_suncg6_tec_clip;
352 tme_suncg6_reg_t tme_suncg6_tec_vdc;
353 } tme_suncg6_tec_group0;
354 };
355
356 /* this does a blit: */
357 static void
_tme_suncg6_blit(struct tme_suncg6 * suncg6)358 _tme_suncg6_blit(struct tme_suncg6 *suncg6)
359 {
360 tme_uint32_t fb_width;
361 tme_uint32_t fb_height;
362 tme_int32_t src_x;
363 tme_int32_t src_y;
364 tme_int32_t dst_x;
365 tme_int32_t dst_y;
366 tme_int32_t blit_width;
367 tme_int32_t blit_height;
368 int unsupported;
369 tme_uint32_t offset_updated_first;
370 tme_uint32_t offset_updated_last;
371 const tme_suncg6_pixel_t *src;
372 tme_suncg6_pixel_t *dst;
373
374 /* get the framebuffer width and height: */
375 fb_width = suncg6->tme_suncg6_width;
376 fb_height = suncg6->tme_suncg6_height;
377
378 /* get the blit source: */
379 src_x = suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_x0;
380 src_y = suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_y0;
381
382 /* get the blit destination: */
383 dst_x = suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_x2;
384 dst_y = suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_y2;
385
386 /* get the blit width and height: */
387 blit_width = suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_x1;
388 blit_width
389 = (blit_width < src_x
390 ? 0
391 : (blit_width + 1 - src_x));
392 blit_height = suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_y1;
393 blit_height
394 = (blit_height < src_y
395 ? 0
396 : (blit_height + 1 - src_y));
397
398 /* check that this blit is supported: */
399 unsupported = FALSE;
400 unsupported |= (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_clip_check != 0);
401 unsupported |= (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_status != 0);
402 unsupported |= (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_offx != 0);
403 unsupported |= (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_offy != 0);
404 unsupported |= (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_clip_min_x != 0);
405 unsupported |= (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_clip_min_y != 0);
406 unsupported |= (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_clip_max_x != (fb_width - 1));
407 unsupported |= (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_clip_max_y != (fb_height - 1));
408 unsupported
409 |= (blit_width
410 != (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_x3 < dst_x
411 ? 0
412 : (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_x3 + 1 - dst_x)));
413 unsupported
414 |= (blit_height
415 != (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_y3 < dst_y
416 ? 0
417 : (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_y3 + 1 - dst_y)));
418 if (__tme_predict_false(unsupported)) {
419 tme_log(TME_SUNFB_LOG_HANDLE(&suncg6->tme_suncg6_sunfb), 0, EINVAL,
420 (TME_SUNFB_LOG_HANDLE(&suncg6->tme_suncg6_sunfb),
421 _("unsupported blit parameters")));
422 return;
423 }
424
425 /* if any of the least coordinates aren't in the framebuffer: */
426 if (src_x >= fb_width
427 || dst_x >= fb_width
428 || src_y >= fb_height
429 || dst_y >= fb_height) {
430 return;
431 }
432
433 /* make sure the blit height and width stay in the framebuffer: */
434 blit_width = TME_MIN(blit_width,
435 TME_MIN(fb_width - src_x,
436 fb_width - dst_x));
437 blit_height = TME_MIN(blit_height,
438 TME_MIN(fb_height - src_y,
439 fb_height - dst_y));
440
441 /* if the blit height or width are zero: */
442 if (blit_width == 0
443 || blit_height == 0) {
444 return;
445 }
446
447 /* get the offsets of the first and last bytes of the
448 destination: */
449 offset_updated_first = ((fb_width * dst_y) + dst_x);
450 offset_updated_last
451 = (offset_updated_first
452 + (blit_width - 1)
453 + (fb_width * (blit_height - 1)));
454
455 /* get the first source and destination rows: */
456 dst = (tme_suncg6_pixel_t *) suncg6->tme_suncg6_sunfb.tme_sunfb_memory;
457 src = dst + ((fb_width * src_y) + src_x);
458 dst += offset_updated_first;
459
460 /* if this is a copy: */
461 if (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_rasterop
462 == TME_SUNCG6_FBC_RASTEROP_FUNC_COPY
463 /* XXX FIXME - the rasterop function that the SUNW,501-2325 PROM
464 uses for all of its blits and draws doesn't do a copy blit,
465 but for now we treat it like it does: */
466 || (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_rasterop
467 == TME_SUNCG6_FBC_RASTEROP_FUNC_PROM)
468 ) {
469
470 /* if the copy is full-width: */
471 if (blit_width == fb_width) {
472
473 /* copy the source to the destination: */
474 memmove(dst,
475 src,
476 sizeof(tme_suncg6_pixel_t) * blit_width * blit_height);
477 }
478
479 /* otherwise, the copy is not full-width: */
480 else {
481
482 /* copy the source to the destination: */
483 do {
484 memmove(dst,
485 src,
486 sizeof(tme_suncg6_pixel_t) * blit_width);
487 dst += sizeof(tme_suncg6_pixel_t) * fb_width;
488 src += sizeof(tme_suncg6_pixel_t) * fb_width;
489 } while (--blit_height);
490 }
491 }
492
493 /* otherwise, this is an unsupported blit: */
494 else {
495 tme_log(TME_SUNFB_LOG_HANDLE(&suncg6->tme_suncg6_sunfb), 0, EINVAL,
496 (TME_SUNFB_LOG_HANDLE(&suncg6->tme_suncg6_sunfb),
497 _("unsupported blit function")));
498 }
499
500 /* update the offsets of the first and last bytes updated in the
501 real framebuffer memory: */
502 offset_updated_first
503 = TME_MIN(offset_updated_first,
504 suncg6->tme_suncg6_sunfb.tme_sunfb_offset_updated_first);
505 offset_updated_last
506 = TME_MAX(offset_updated_last,
507 suncg6->tme_suncg6_sunfb.tme_sunfb_offset_updated_last);
508 suncg6->tme_suncg6_sunfb.tme_sunfb_offset_updated_first = offset_updated_first;
509 suncg6->tme_suncg6_sunfb.tme_sunfb_offset_updated_last = offset_updated_last;
510 }
511
512 /* this does a draw: */
513 static void
_tme_suncg6_draw(struct tme_suncg6 * suncg6)514 _tme_suncg6_draw(struct tme_suncg6 *suncg6)
515 {
516 tme_uint32_t fb_width;
517 tme_uint32_t fb_height;
518 unsigned int rect_abs_i;
519 tme_int32_t draw_width;
520 tme_int32_t dst_x;
521 tme_int32_t draw_height;
522 tme_int32_t dst_y;
523 int unsupported;
524 tme_uint32_t offset_updated_first;
525 tme_uint32_t offset_updated_last;
526 tme_suncg6_pixel_t *dst;
527 tme_int32_t resid_width;
528
529 /* get the framebuffer width and height: */
530 fb_width = suncg6->tme_suncg6_width;
531 fb_height = suncg6->tme_suncg6_height;
532
533 /* get the draw width and destination x: */
534 rect_abs_i = suncg6->tme_suncg6_fbc_rect_abs_x_i;
535 draw_width = suncg6->tme_suncg6_fbc_rect_abs_x[rect_abs_i % TME_SUNCG6_RECT_ABS_COUNT];
536 rect_abs_i = rect_abs_i - 1;
537 dst_x = suncg6->tme_suncg6_fbc_rect_abs_x[rect_abs_i % TME_SUNCG6_RECT_ABS_COUNT];
538 draw_width
539 = (draw_width < dst_x
540 ? 0
541 : (draw_width + 1 - dst_x));
542
543 /* get the draw height and destination y: */
544 rect_abs_i = suncg6->tme_suncg6_fbc_rect_abs_y_i;
545 draw_height = suncg6->tme_suncg6_fbc_rect_abs_y[rect_abs_i % TME_SUNCG6_RECT_ABS_COUNT];
546 rect_abs_i = rect_abs_i - 1;
547 dst_y = suncg6->tme_suncg6_fbc_rect_abs_y[rect_abs_i % TME_SUNCG6_RECT_ABS_COUNT];
548 draw_height
549 = (draw_height < dst_y
550 ? 0
551 : (draw_height + 1 - dst_y));
552
553 /* check that this draw is supported: */
554 unsupported = FALSE;
555 unsupported |= (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_clip_check != 0);
556 unsupported |= (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_status != 0);
557 unsupported |= (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_offx != 0);
558 unsupported |= (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_offy != 0);
559 unsupported |= (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_clip_min_x != 0);
560 unsupported |= (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_clip_min_y != 0);
561 unsupported |= (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_clip_max_x != (fb_width - 1));
562 unsupported |= (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_clip_max_y != (fb_height - 1));
563 if (__tme_predict_false(unsupported)) {
564 tme_log(TME_SUNFB_LOG_HANDLE(&suncg6->tme_suncg6_sunfb), 0, EINVAL,
565 (TME_SUNFB_LOG_HANDLE(&suncg6->tme_suncg6_sunfb),
566 _("unsupported draw parameters")));
567 return;
568 }
569
570 /* if the draw coordinate isn't in the framebuffer: */
571 if (dst_x >= fb_width
572 || dst_y >= fb_height) {
573 return;
574 }
575
576 /* make sure the draw height and width stay in the framebuffer: */
577 draw_width = TME_MIN(draw_width,
578 fb_width - dst_x);
579 draw_height = TME_MIN(draw_height,
580 fb_height - dst_y);
581
582 /* if the draw height or width are zero: */
583 if (draw_width == 0
584 || draw_height == 0) {
585 return;
586 }
587
588 /* get the offsets of the first and last bytes of the
589 destination: */
590 offset_updated_first = ((fb_width * dst_y) + dst_x);
591 offset_updated_last
592 = (offset_updated_first
593 + (draw_width - 1)
594 + (fb_width * (draw_height - 1)));
595
596 /* get the first destination row: */
597 dst = (tme_suncg6_pixel_t *) suncg6->tme_suncg6_sunfb.tme_sunfb_memory;
598 dst += offset_updated_first;
599
600 /* if this is a fill: */
601 if (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_rasterop
602 == TME_SUNCG6_FBC_RASTEROP_FUNC_FILL
603 /* XXX FIXME - the rasterop function that the SUNW,501-2325 PROM
604 uses for all of its blits and draws doesn't do a fill draw,
605 but for now we treat it like it does: */
606 || (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_rasterop
607 == TME_SUNCG6_FBC_RASTEROP_FUNC_PROM)
608 ) {
609
610 /* if the fill is full-width: */
611 if (draw_width == fb_width) {
612
613 /* fill the destination: */
614 memset(dst,
615 (tme_uint8_t) suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_fg,
616 sizeof(tme_suncg6_pixel_t) * draw_width * draw_height);
617 }
618
619 /* otherwise, the fill is not full-width: */
620 else {
621
622 /* fill the destination: */
623 do {
624 memset(dst,
625 (tme_uint8_t) suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_fg,
626 sizeof(tme_suncg6_pixel_t) * draw_width);
627 dst += sizeof(tme_suncg6_pixel_t) * fb_width;
628 } while (--draw_height);
629 }
630 }
631
632 /* otherwise, if this is an invert: */
633 else if (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_rasterop
634 == TME_SUNCG6_FBC_RASTEROP_FUNC_FLIP) {
635
636 /* do the inversion: */
637 /* XXX FIXME - the inversion almost certainly isn't this
638 simple: */
639 do {
640 resid_width = draw_width;
641 do {
642 *(dst++) ^= 0xff;
643 } while (--resid_width);
644 dst = (dst - draw_width) + fb_width;
645 } while (--draw_height);
646 }
647
648 /* otherwise, this is an unsupported draw: */
649 else {
650 tme_log(TME_SUNFB_LOG_HANDLE(&suncg6->tme_suncg6_sunfb), 0, EINVAL,
651 (TME_SUNFB_LOG_HANDLE(&suncg6->tme_suncg6_sunfb),
652 _("unsupported draw function")));
653 }
654
655 /* update the offsets of the first and last bytes updated in the
656 real framebuffer memory: */
657 offset_updated_first
658 = TME_MIN(offset_updated_first,
659 suncg6->tme_suncg6_sunfb.tme_sunfb_offset_updated_first);
660 offset_updated_last
661 = TME_MAX(offset_updated_last,
662 suncg6->tme_suncg6_sunfb.tme_sunfb_offset_updated_last);
663 suncg6->tme_suncg6_sunfb.tme_sunfb_offset_updated_first = offset_updated_first;
664 suncg6->tme_suncg6_sunfb.tme_sunfb_offset_updated_last = offset_updated_last;
665 }
666
667 /* this does a font draw: */
668 static void
_tme_suncg6_font(struct tme_suncg6 * suncg6,tme_suncg6_reg_t font)669 _tme_suncg6_font(struct tme_suncg6 *suncg6,
670 tme_suncg6_reg_t font)
671 {
672 tme_uint32_t fb_width;
673 tme_uint32_t fb_height;
674 tme_int32_t dst_x;
675 tme_int32_t dst_y;
676 tme_int32_t draw_width;
677 int unsupported;
678 tme_uint32_t offset_updated_first;
679 tme_uint32_t offset_updated_last;
680 tme_suncg6_pixel_t *dst;
681 tme_uint16_t pixels;
682
683 /* get the framebuffer width and height: */
684 fb_width = suncg6->tme_suncg6_width;
685 fb_height = suncg6->tme_suncg6_height;
686
687 /* get the font draw destination: */
688 dst_x = suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_x0;
689 dst_y = suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_y0;
690
691 /* get the font draw width: */
692 draw_width = suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_x1;
693 draw_width
694 = (draw_width < dst_x
695 ? 0
696 : (draw_width + 1 - dst_x));
697
698 /* check that this font draw is supported: */
699 unsupported = FALSE;
700 unsupported |= (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_clip_check != 0);
701 unsupported |= (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_status != 0);
702 unsupported |= (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_offx != 0);
703 unsupported |= (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_offy != 0);
704 unsupported |= (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_clip_min_x != 0);
705 unsupported |= (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_clip_min_y != 0);
706 unsupported |= (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_clip_max_x != (fb_width - 1));
707 unsupported |= (suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_clip_max_y != (fb_height - 1));
708 if (__tme_predict_false(unsupported)) {
709 tme_log(TME_SUNFB_LOG_HANDLE(&suncg6->tme_suncg6_sunfb), 0, EINVAL,
710 (TME_SUNFB_LOG_HANDLE(&suncg6->tme_suncg6_sunfb),
711 _("unsupported font draw parameters")));
712 return;
713 }
714
715 /* if the font draw coordinate isn't in the framebuffer: */
716 if (dst_x >= fb_width
717 || dst_y >= fb_height) {
718 return;
719 }
720
721 /* make sure the font draw width stays in the framebuffer: */
722 draw_width = TME_MIN(draw_width,
723 fb_width - dst_x);
724
725 /* if the draw width is zero: */
726 if (draw_width == 0) {
727 return;
728 }
729
730 /* get the offsets of the first and last bytes of the
731 destination: */
732 offset_updated_first = ((fb_width * dst_y) + dst_x);
733 offset_updated_last
734 = (offset_updated_first
735 + (draw_width - 1));
736
737 /* get the first destination row: */
738 dst = (tme_suncg6_pixel_t *) suncg6->tme_suncg6_sunfb.tme_sunfb_memory;
739 dst += offset_updated_first;
740
741 /* get the foreground and background pixels: */
742 pixels = (tme_suncg6_pixel_t) suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_fg;
743 pixels <<= (8 * sizeof(tme_suncg6_pixel_t));
744 pixels += (tme_suncg6_pixel_t) suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_bg;
745
746 /* do the font draw: */
747 do {
748 *(dst++)
749 = ((tme_suncg6_pixel_t)
750 (pixels
751 >> ((0 - (((tme_int32_t) font) < 0))
752 & (8 * sizeof(tme_suncg6_pixel_t)))));
753 font <<= 1;
754 } while (--draw_width);
755
756 /* advance after the font draw: */
757 suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_x0 += suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_inc_x;
758 suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_x1 += suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_inc_x;
759 suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_y0 += suncg6->tme_suncg6_fbc_group0.tme_suncg6_fbc_inc_y;
760
761 /* update the offsets of the first and last bytes updated in the
762 real framebuffer memory: */
763 offset_updated_first
764 = TME_MIN(offset_updated_first,
765 suncg6->tme_suncg6_sunfb.tme_sunfb_offset_updated_first);
766 offset_updated_last
767 = TME_MAX(offset_updated_last,
768 suncg6->tme_suncg6_sunfb.tme_sunfb_offset_updated_last);
769 suncg6->tme_suncg6_sunfb.tme_sunfb_offset_updated_first = offset_updated_first;
770 suncg6->tme_suncg6_sunfb.tme_sunfb_offset_updated_last = offset_updated_last;
771 }
772
773 /* the ALT bus cycle handler: */
774 static void
_tme_suncg6_bus_cycle_alt(struct tme_sunfb * sunfb,struct tme_bus_cycle * master_cycle,tme_uint32_t * _master_fast_cycle_types,struct tme_completion * master_completion)775 _tme_suncg6_bus_cycle_alt(struct tme_sunfb *sunfb,
776 struct tme_bus_cycle *master_cycle,
777 tme_uint32_t *_master_fast_cycle_types,
778 struct tme_completion *master_completion)
779 {
780 struct tme_suncg6 *suncg6;
781 tme_bus_addr32_t reg;
782 tme_suncg6_reg_t *_reg;
783 tme_suncg6_reg_t value32_buffer;
784 tme_suncg6_reg_t value32;
785
786 /* recover our data structure: */
787 suncg6 = (struct tme_suncg6 *) sunfb;
788
789 /* get the register: */
790 reg = master_cycle->tme_bus_cycle_address;
791
792 /* convert the register into a pointer: */
793 _reg = NULL;
794
795 /* if this is a write: */
796 if (master_cycle->tme_bus_cycle_type == TME_BUS_CYCLE_WRITE) {
797
798 /* run the bus cycle: */
799 tme_bus_cycle_xfer_reg(master_cycle,
800 &value32_buffer,
801 TME_BUS32_LOG2);
802 value32 = value32_buffer;
803 }
804
805 /* otherwise, this must be a read: */
806 else {
807 assert (master_cycle->tme_bus_cycle_type == TME_BUS_CYCLE_READ);
808
809 /* this must be a maintained register: */
810 if (_reg == NULL) {
811 abort();
812 }
813 value32 = *_reg;
814
815 /* run the bus cycle: */
816 value32_buffer = value32;
817 tme_bus_cycle_xfer_reg(master_cycle,
818 &value32_buffer,
819 TME_BUS32_LOG2);
820 }
821
822 /* complete the cycle: */
823 master_completion->tme_completion_error = TME_OK;
824 tme_memory_barrier(master_completion, sizeof(*master_completion), TME_MEMORY_BARRIER_WRITE_BEFORE_WRITE);
825 tme_completion_validate(master_completion);
826 *_master_fast_cycle_types = 0;
827
828 tme_log(TME_SUNFB_LOG_HANDLE(sunfb), 2000, TME_OK,
829 (TME_SUNFB_LOG_HANDLE(sunfb),
830 _("ALT 0x%06" TME_PRIx32 " %s%s 0x%08" TME_PRIx32),
831 reg,
832 (_reg == NULL
833 ? "UNKNOWN "
834 : ""),
835 (master_cycle->tme_bus_cycle_type == TME_BUS_CYCLE_WRITE
836 ? "<-"
837 : "->"),
838 value32));
839 }
840
841 /* the FHC and THC bus cycle handler: */
842 static void
_tme_suncg6_bus_cycle_fhc_thc(struct tme_sunfb * sunfb,struct tme_bus_cycle * master_cycle,tme_uint32_t * _master_fast_cycle_types,struct tme_completion * master_completion)843 _tme_suncg6_bus_cycle_fhc_thc(struct tme_sunfb *sunfb,
844 struct tme_bus_cycle *master_cycle,
845 tme_uint32_t *_master_fast_cycle_types,
846 struct tme_completion *master_completion)
847 {
848 struct tme_suncg6 *suncg6;
849 tme_bus_addr32_t reg;
850 tme_suncg6_reg_t *_reg;
851 tme_suncg6_reg_t value32_buffer;
852 tme_suncg6_reg_t value32;
853 tme_suncg6_reg_t reg_mask_ro;
854
855 /* recover our data structure: */
856 suncg6 = (struct tme_suncg6 *) sunfb;
857
858 /* get the register: */
859 reg = master_cycle->tme_bus_cycle_address;
860
861 /* convert the register into a pointer: */
862 if (reg >= TME_SUNCG6_REG_THC_UNKNOWN_0x0) {
863 _reg = (TME_SUNCG6_REG_POINTER(suncg6, reg,THC,thc,0)
864 : TME_SUNCG6_REG_POINTER(suncg6, reg,THC,thc,1)
865 : NULL);
866 }
867 else {
868 reg = TME_SUNCG6_REG_FHC;
869 _reg = &suncg6->tme_suncg6_fhc;
870 }
871
872 /* if this is a write: */
873 if (master_cycle->tme_bus_cycle_type == TME_BUS_CYCLE_WRITE) {
874
875 /* run the bus cycle: */
876 tme_bus_cycle_xfer_reg(master_cycle,
877 &value32_buffer,
878 TME_BUS32_LOG2);
879 value32 = value32_buffer;
880
881 /* assume that none of the register is read-only: */
882 reg_mask_ro = 0;
883
884 /* dispatch on the register: */
885 switch (reg) {
886
887 /* the FHC: */
888 case TME_SUNCG6_REG_FHC:
889 reg_mask_ro
890 = (TME_SUNCG6_FHC_ID_MASK
891 + TME_SUNCG6_FHC_REVISION_MASK
892 + TME_SUNCG6_FHC_SIZE_MASK);
893 break;
894
895 /* the THC miscellaneous register: */
896 case TME_SUNCG6_REG_THC(1,misc):
897 reg_mask_ro
898 = (TME_SUNCG6_THC_MISC_REVISION_MASK
899 );
900 break;
901
902 default:
903 break;
904 }
905
906 /* if this is a maintained register: */
907 if (_reg != NULL) {
908 *_reg
909 = ((*_reg
910 & reg_mask_ro)
911 + (value32
912 & ~reg_mask_ro));
913 }
914 }
915
916 /* otherwise, this is a read: */
917 else {
918 assert (master_cycle->tme_bus_cycle_type == TME_BUS_CYCLE_READ);
919
920 /* dispatch on the register: */
921 switch (reg) {
922
923 default:
924 break;
925 }
926
927 /* this must be a maintained register: */
928 if (_reg == NULL) {
929 abort();
930 }
931 value32 = *_reg;
932
933 /* run the bus cycle: */
934 value32_buffer = value32;
935 tme_bus_cycle_xfer_reg(master_cycle,
936 &value32_buffer,
937 TME_BUS32_LOG2);
938 }
939
940 /* complete the cycle: */
941 master_completion->tme_completion_error = TME_OK;
942 tme_memory_barrier(master_completion, sizeof(*master_completion), TME_MEMORY_BARRIER_WRITE_BEFORE_WRITE);
943 tme_completion_validate(master_completion);
944 *_master_fast_cycle_types = 0;
945
946 tme_log(TME_SUNFB_LOG_HANDLE(sunfb), 2000, TME_OK,
947 (TME_SUNFB_LOG_HANDLE(sunfb),
948 _("%s 0x%06" TME_PRIx32 " %s%s 0x%08" TME_PRIx32),
949 (reg >= TME_SUNCG6_REG_THC_UNKNOWN_0x0
950 ? "THC"
951 : "FHC"),
952 reg,
953 (_reg == NULL
954 ? "UNKNOWN "
955 : ""),
956 (master_cycle->tme_bus_cycle_type == TME_BUS_CYCLE_WRITE
957 ? "<-"
958 : "->"),
959 value32));
960 }
961
962 /* the FBC bus cycle handler: */
963 static void
_tme_suncg6_bus_cycle_fbc(struct tme_sunfb * sunfb,struct tme_bus_cycle * master_cycle,tme_uint32_t * _master_fast_cycle_types,struct tme_completion * master_completion)964 _tme_suncg6_bus_cycle_fbc(struct tme_sunfb *sunfb,
965 struct tme_bus_cycle *master_cycle,
966 tme_uint32_t *_master_fast_cycle_types,
967 struct tme_completion *master_completion)
968 {
969 struct tme_suncg6 *suncg6;
970 tme_bus_addr32_t reg;
971 tme_suncg6_reg_t *_reg;
972 tme_suncg6_reg_t value32_buffer;
973 tme_suncg6_reg_t value32;
974 tme_suncg6_reg_t reg_mask_ro;
975
976 /* recover our data structure: */
977 suncg6 = (struct tme_suncg6 *) sunfb;
978
979 /* get the register: */
980 reg = master_cycle->tme_bus_cycle_address;
981
982 /* convert the register into a pointer: */
983 _reg
984 = (TME_SUNCG6_REG_POINTER(suncg6, reg,FBC,fbc,0)
985 : TME_SUNCG6_REG_POINTER(suncg6, reg,FBC,fbc,1)
986 : NULL);
987
988 /* if this is a write: */
989 if (master_cycle->tme_bus_cycle_type == TME_BUS_CYCLE_WRITE) {
990
991 /* run the bus cycle: */
992 tme_bus_cycle_xfer_reg(master_cycle,
993 &value32_buffer,
994 TME_BUS32_LOG2);
995 value32 = value32_buffer;
996
997 /* assume that none of the register is read-only: */
998 reg_mask_ro = 0;
999
1000 /* dispatch on the register: */
1001 switch (reg) {
1002
1003 /* a write of the font register: */
1004 case TME_SUNCG6_REG_FBC(0,font):
1005 _tme_suncg6_font(suncg6, value32);
1006 break;
1007
1008 /* a write of the rectangle absolute coordinate registers: */
1009 case TME_SUNCG6_REG_FBC(1,rect_abs_x):
1010 suncg6->tme_suncg6_fbc_rect_abs_x_i
1011 = ((suncg6->tme_suncg6_fbc_rect_abs_x_i + 1)
1012 % TME_SUNCG6_RECT_ABS_COUNT);
1013 _reg = &suncg6->tme_suncg6_fbc_rect_abs_x[suncg6->tme_suncg6_fbc_rect_abs_x_i];
1014 break;
1015 case TME_SUNCG6_REG_FBC(1,rect_abs_y):
1016 suncg6->tme_suncg6_fbc_rect_abs_y_i
1017 = ((suncg6->tme_suncg6_fbc_rect_abs_y_i + 1)
1018 % TME_SUNCG6_RECT_ABS_COUNT);
1019 _reg = &suncg6->tme_suncg6_fbc_rect_abs_y[suncg6->tme_suncg6_fbc_rect_abs_y_i];
1020 break;
1021
1022 default:
1023 break;
1024 }
1025
1026 /* if this is a maintained register: */
1027 if (_reg != NULL) {
1028 *_reg
1029 = ((*_reg
1030 & reg_mask_ro)
1031 + (value32
1032 & ~reg_mask_ro));
1033 }
1034 }
1035
1036 /* otherwise, this is a read: */
1037 else {
1038 assert (master_cycle->tme_bus_cycle_type == TME_BUS_CYCLE_READ);
1039
1040 /* dispatch on the register: */
1041 switch (reg) {
1042
1043 /* a read of the status register: */
1044 case TME_SUNCG6_REG_FBC(0,status):
1045 *_reg = 0;
1046 break;
1047
1048 /* a read of the blit status register: */
1049 case TME_SUNCG6_REG_FBC(0,status_blit):
1050
1051 /* trigger a blit: */
1052 _tme_suncg6_blit(suncg6);
1053
1054 *_reg = 0;
1055 break;
1056
1057 /* a read of the drawing status register: */
1058 case TME_SUNCG6_REG_FBC(0,status_draw):
1059
1060 /* trigger a draw: */
1061 _tme_suncg6_draw(suncg6);
1062
1063 *_reg = 0;
1064 break;
1065
1066 default:
1067 break;
1068 }
1069
1070 /* this must be a maintained register: */
1071 if (_reg == NULL) {
1072 abort();
1073 }
1074 value32 = *_reg;
1075
1076 /* run the bus cycle: */
1077 value32_buffer = value32;
1078 tme_bus_cycle_xfer_reg(master_cycle,
1079 &value32_buffer,
1080 TME_BUS32_LOG2);
1081 }
1082
1083 /* complete the cycle: */
1084 master_completion->tme_completion_error = TME_OK;
1085 tme_memory_barrier(master_completion, sizeof(*master_completion), TME_MEMORY_BARRIER_WRITE_BEFORE_WRITE);
1086 tme_completion_validate(master_completion);
1087 *_master_fast_cycle_types = 0;
1088
1089 tme_log(TME_SUNFB_LOG_HANDLE(sunfb), 2000, TME_OK,
1090 (TME_SUNFB_LOG_HANDLE(sunfb),
1091 _("FBC 0x%06" TME_PRIx32 " %s%s 0x%08" TME_PRIx32),
1092 reg,
1093 (_reg == NULL
1094 ? "UNKNOWN "
1095 : ""),
1096 (master_cycle->tme_bus_cycle_type == TME_BUS_CYCLE_WRITE
1097 ? "<-"
1098 : "->"),
1099 value32));
1100 }
1101
1102 /* the TEC bus cycle handler: */
1103 static void
_tme_suncg6_bus_cycle_tec(struct tme_sunfb * sunfb,struct tme_bus_cycle * master_cycle,tme_uint32_t * _master_fast_cycle_types,struct tme_completion * master_completion)1104 _tme_suncg6_bus_cycle_tec(struct tme_sunfb *sunfb,
1105 struct tme_bus_cycle *master_cycle,
1106 tme_uint32_t *_master_fast_cycle_types,
1107 struct tme_completion *master_completion)
1108 {
1109 struct tme_suncg6 *suncg6;
1110 tme_bus_addr32_t reg;
1111 tme_suncg6_reg_t *_reg;
1112 tme_suncg6_reg_t value32_buffer;
1113 tme_suncg6_reg_t value32;
1114 tme_suncg6_reg_t reg_mask_ro;
1115
1116 /* recover our data structure: */
1117 suncg6 = (struct tme_suncg6 *) sunfb;
1118
1119 /* get the register: */
1120 reg = master_cycle->tme_bus_cycle_address;
1121
1122 /* convert the register into a pointer: */
1123 _reg
1124 = (TME_SUNCG6_REG_POINTER(suncg6, reg,TEC,tec,0)
1125 : NULL);
1126
1127 /* if this is a write: */
1128 if (master_cycle->tme_bus_cycle_type == TME_BUS_CYCLE_WRITE) {
1129
1130 /* run the bus cycle: */
1131 tme_bus_cycle_xfer_reg(master_cycle,
1132 &value32_buffer,
1133 TME_BUS32_LOG2);
1134 value32 = value32_buffer;
1135
1136 /* assume that none of the register is read-only: */
1137 reg_mask_ro = 0;
1138
1139 /* dispatch on the register: */
1140 switch (reg) {
1141
1142 default:
1143 break;
1144 }
1145
1146 /* if this is a maintained register: */
1147 if (_reg != NULL) {
1148 *_reg
1149 = ((*_reg
1150 & reg_mask_ro)
1151 + (value32
1152 & ~reg_mask_ro));
1153 }
1154 }
1155
1156 /* otherwise, this is a read: */
1157 else {
1158 assert (master_cycle->tme_bus_cycle_type == TME_BUS_CYCLE_READ);
1159
1160 /* dispatch on the register: */
1161 switch (reg) {
1162
1163 default:
1164 break;
1165 }
1166
1167 /* this must be a maintained register: */
1168 if (_reg == NULL) {
1169 abort();
1170 }
1171 value32 = *_reg;
1172
1173 /* run the bus cycle: */
1174 value32_buffer = value32;
1175 tme_bus_cycle_xfer_reg(master_cycle,
1176 &value32_buffer,
1177 TME_BUS32_LOG2);
1178 }
1179
1180 /* complete the cycle: */
1181 master_completion->tme_completion_error = TME_OK;
1182 tme_memory_barrier(master_completion, sizeof(*master_completion), TME_MEMORY_BARRIER_WRITE_BEFORE_WRITE);
1183 tme_completion_validate(master_completion);
1184 *_master_fast_cycle_types = 0;
1185
1186 tme_log(TME_SUNFB_LOG_HANDLE(sunfb), 2000, TME_OK,
1187 (TME_SUNFB_LOG_HANDLE(sunfb),
1188 _("TEC 0x%06" TME_PRIx32 " %s%s 0x%08" TME_PRIx32),
1189 reg,
1190 (_reg == NULL
1191 ? "UNKNOWN "
1192 : ""),
1193 (master_cycle->tme_bus_cycle_type == TME_BUS_CYCLE_WRITE
1194 ? "<-"
1195 : "->"),
1196 value32));
1197 }
1198
1199 #if TME_SUNFB_BUS_TRANSITION
1200
1201 /* this is the bus cycle transition glue: */
1202 #define _tme_suncg6_bus_cycle_transition(regs) \
1203 static int \
1204 _TME_CONCAT(_tme_suncg6_bus_cycle_transition_,regs)(void *_sunfb, \
1205 struct tme_bus_cycle *master_cycle) \
1206 { \
1207 return (tme_sunfb_bus_cycle_transition(_sunfb, \
1208 master_cycle, \
1209 _TME_CONCAT(_tme_suncg6_bus_cycle_,regs))); \
1210 } \
1211 struct _tme_suncg6_bus_cycle_transition
1212 _tme_suncg6_bus_cycle_transition(alt);
1213 _tme_suncg6_bus_cycle_transition(fhc_thc);
1214 _tme_suncg6_bus_cycle_transition(fbc);
1215 _tme_suncg6_bus_cycle_transition(tec);
1216 #define _tme_suncg6_bus_cycle_alt _tme_suncg6_bus_cycle_transition_alt
1217 #define _tme_suncg6_bus_cycle_fhc_thc _tme_suncg6_bus_cycle_transition_fhc_thc
1218 #define _tme_suncg6_bus_cycle_fbc _tme_suncg6_bus_cycle_transition_fbc
1219 #define _tme_suncg6_bus_cycle_tec _tme_suncg6_bus_cycle_transition_tec
1220 #undef _tme_suncg6_bus_cycle_transition
1221
1222 #endif /* TME_SUNFB_BUS_TRANSITION */
1223
1224 /* this sets the cgsix type: */
1225 static const char *
_tme_suncg6_type_set(struct tme_sunfb * sunfb,const char * cg6_type_string)1226 _tme_suncg6_type_set(struct tme_sunfb *sunfb, const char *cg6_type_string)
1227 {
1228 struct tme_suncg6 *suncg6;
1229 tme_uint32_t cg6_type;
1230 tme_suncg6_reg_t fhc;
1231 tme_suncg6_reg_t thc_misc;
1232
1233 /* recover our data structure: */
1234 suncg6 = (struct tme_suncg6 *) sunfb;
1235
1236 /* see if this is a good type: */
1237 cg6_type = TME_SUNCG6_TYPE_NULL;
1238 if (TME_ARG_IS(cg6_type_string, "501-2325")) {
1239 cg6_type = TME_SUNCG6_TYPE_501_2325;
1240 }
1241
1242 /* set the new type: */
1243 suncg6->tme_suncg6_type = cg6_type;
1244
1245 /* zero various registers: */
1246 fhc = 0;
1247 thc_misc = 0;
1248
1249 /* dispatch on the new type: */
1250 switch (cg6_type) {
1251
1252 /* if this was a bad type, return a string of types: */
1253 default: assert(FALSE);
1254 case TME_SUNCG6_TYPE_NULL:
1255 return ("501-2325");
1256
1257 case TME_SUNCG6_TYPE_501_2325:
1258 TME_FIELD_MASK_DEPOSITU(fhc, TME_SUNCG6_FHC_ID_MASK, 0x63);
1259 TME_FIELD_MASK_DEPOSITU(fhc, TME_SUNCG6_FHC_REVISION_MASK, 0xb);
1260 TME_FIELD_MASK_DEPOSITU(thc_misc, TME_SUNCG6_THC_MISC_REVISION_MASK, 0x4);
1261 sunfb->tme_sunfb_bus_signal_int = TME_BUS_SIGNAL_INT(5);
1262 break;
1263 }
1264
1265 /* set various initial registers: */
1266 suncg6->tme_suncg6_fhc = fhc;
1267 suncg6->tme_suncg6_thc_group1.tme_suncg6_thc_misc = thc_misc;
1268
1269 /* success: */
1270 return (NULL);
1271 }
1272
1273 /* the new sun cgsix function: */
1274 int
tme_sun_cgsix(struct tme_element * element,const char * const * args,char ** _output)1275 tme_sun_cgsix(struct tme_element *element, const char * const *args, char **_output)
1276 {
1277 struct tme_suncg6 *suncg6;
1278 struct tme_sunfb *sunfb;
1279 tme_uint8_t *cmap;
1280 int rc;
1281 tme_suncg6_reg_t fhc;
1282
1283 /* start the suncg6 structure: */
1284 suncg6 = tme_new0(struct tme_suncg6, 1);
1285 suncg6->tme_suncg6_sunfb.tme_sunfb_element = element;
1286
1287 /* initialize the sunfb structure: */
1288 sunfb = &suncg6->tme_suncg6_sunfb;
1289 sunfb->tme_sunfb_class = TME_FB_XLAT_CLASS_COLOR;
1290 sunfb->tme_sunfb_depth = 8;
1291 sunfb->tme_sunfb_type_set = _tme_suncg6_type_set;
1292 sunfb->tme_sunfb_flags
1293 |= ((!TME_SUNFB_FLAG_BT458_CMAP_PACKED)
1294 | TME_SUNFB_FLAG_BT458_BYTE_D24_D31);
1295
1296 /* possible cgsix framebuffer sizes: */
1297 suncg6->tme_suncg6_sunfb.tme_sunfb_size
1298 = (TME_SUNFB_SIZE_1024_768
1299 | TME_SUNFB_SIZE_1152_900
1300 | TME_SUNFB_SIZE_1280_1024
1301 | TME_SUNFB_SIZE_1600_1280);
1302
1303 /* assume that this is not a P4 cgsix: */
1304 suncg6->tme_suncg6_bus_subregion_p4.tme_bus_subregion_address_first = 1;
1305 suncg6->tme_suncg6_bus_subregion_p4.tme_bus_subregion_address_last = 0;
1306 suncg6->tme_suncg6_bus_handler_p4 = NULL;
1307
1308 /* the DAC registers: */
1309 suncg6->tme_suncg6_bus_subregion_dac.tme_bus_subregion_address_first = TME_SUNCG6_REG_DAC;
1310 suncg6->tme_suncg6_bus_subregion_dac.tme_bus_subregion_address_last = TME_SUNCG6_REG_ALT - 1;
1311 suncg6->tme_suncg6_bus_handler_dac = tme_sunfb_bus_cycle_bt458;
1312
1313 /* the ALT registers: */
1314 suncg6->tme_suncg6_bus_subregion_alt.tme_bus_subregion_address_first = TME_SUNCG6_REG_ALT;
1315 suncg6->tme_suncg6_bus_subregion_alt.tme_bus_subregion_address_last = TME_SUNCG6_REG_ALT + TME_SUNCG6_SIZ_ALT - 1;
1316 suncg6->tme_suncg6_bus_handler_alt = _tme_suncg6_bus_cycle_alt;
1317
1318 /* the FHC and THC registers: */
1319 suncg6->tme_suncg6_bus_subregion_fhc_thc.tme_bus_subregion_address_first = TME_SUNCG6_REG_FHC;
1320 suncg6->tme_suncg6_bus_subregion_fhc_thc.tme_bus_subregion_address_last
1321 = (TME_SUNCG6_REG_THC_UNKNOWN_0x0
1322 + TME_SUNCG6_SIZ_THC
1323 - 1);
1324 suncg6->tme_suncg6_bus_handler_fhc_thc = _tme_suncg6_bus_cycle_fhc_thc;
1325
1326 /* the FBC registers: */
1327 suncg6->tme_suncg6_bus_subregion_fbc.tme_bus_subregion_address_first
1328 = TME_SUNCG6_REG_FBC_GROUP0;
1329 suncg6->tme_suncg6_bus_subregion_fbc.tme_bus_subregion_address_last
1330 = TME_SUNCG6_REG_TEC_GROUP0 - 1;
1331 suncg6->tme_suncg6_bus_handler_fbc = _tme_suncg6_bus_cycle_fbc;
1332
1333 /* the TEC registers: */
1334 suncg6->tme_suncg6_bus_subregion_tec.tme_bus_subregion_address_first
1335 = TME_SUNCG6_REG_TEC_GROUP0;
1336 suncg6->tme_suncg6_bus_subregion_tec.tme_bus_subregion_address_last
1337 = (TME_SUNCG6_REG_TEC_GROUP0
1338 + TME_SUNCG6_TEC_SIZE
1339 - 1);
1340 suncg6->tme_suncg6_bus_handler_tec = _tme_suncg6_bus_cycle_tec;
1341
1342 /* the memory address: */
1343 sunfb->tme_sunfb_bus_subregion_memory.tme_bus_subregion_address_first = TME_SUNFB_S4_OFFSET_MEMORY;
1344
1345 /* if the generic initialization fails: */
1346 rc = tme_sunfb_new(sunfb, args, _output);
1347 if (rc) {
1348
1349 /* free the sunfb structure and return the error: */
1350 tme_free(sunfb);
1351 return (rc);
1352 }
1353
1354 /* set the size in the initial FHC: */
1355 fhc = suncg6->tme_suncg6_fhc;
1356 fhc &= (TME_SUNCG6_FHC_ID_MASK
1357 + TME_SUNCG6_FHC_REVISION_MASK);
1358 switch (sunfb->tme_sunfb_size) {
1359 default: assert(FALSE);
1360 case TME_SUNFB_SIZE_1152_900: fhc += TME_SUNCG6_FHC_SIZE_1152_900; break;
1361 case TME_SUNFB_SIZE_1024_768: fhc += TME_SUNCG6_FHC_SIZE_1024_768; break;
1362 case TME_SUNFB_SIZE_1280_1024: fhc += TME_SUNCG6_FHC_SIZE_1280_1024; break;
1363 case TME_SUNFB_SIZE_1600_1280: fhc += TME_SUNCG6_FHC_SIZE_1600_1280; break;
1364 }
1365 suncg6->tme_suncg6_fhc = fhc;
1366
1367 /* save the size: */
1368 suncg6->tme_suncg6_width = tme_sunfb_size_width(suncg6->tme_suncg6_sunfb.tme_sunfb_size);
1369 suncg6->tme_suncg6_height = tme_sunfb_size_height(suncg6->tme_suncg6_sunfb.tme_sunfb_size);
1370
1371 /* allocate the colormap arrays: */
1372 cmap = tme_new0(tme_uint8_t, 256 * 3);
1373 sunfb->tme_sunfb_cmap_g = &cmap[256 * 0];
1374 sunfb->tme_sunfb_cmap_r = &cmap[256 * 1];
1375 sunfb->tme_sunfb_cmap_b = &cmap[256 * 2];
1376 sunfb->tme_sunfb_bt458.tme_bt458_cmap_g = sunfb->tme_sunfb_cmap_g;
1377 sunfb->tme_sunfb_bt458.tme_bt458_cmap_r = sunfb->tme_sunfb_cmap_r;
1378 sunfb->tme_sunfb_bt458.tme_bt458_cmap_b = sunfb->tme_sunfb_cmap_b;
1379
1380 return (TME_OK);
1381 }
1382