|
|
1.1 root 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
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
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
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
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
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
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
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 *
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
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.