1 /* $Id: sun-bwtwo.c,v 1.6 2009/11/08 17:03:58 fredette Exp $ */
2
3 /* machine/sun/sun-bwtwo.c - Sun bwtwo emulation: */
4
5 /*
6 * Copyright (c) 2003, 2004, 2006 Matt Fredette
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by Matt Fredette.
20 * 4. The name of the author may not be used to endorse or promote products
21 * derived from this software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
27 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
31 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
34 */
35
36 #include <tme/common.h>
37 _TME_RCSID("$Id: sun-bwtwo.c,v 1.6 2009/11/08 17:03:58 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 /* bwtwo types: */
48 #define TME_SUNBW2_TYPE_NULL (0)
49 #define TME_SUNBW2_TYPE_MULTIBUS (1)
50 #define TME_SUNBW2_TYPE_OLD_ONBOARD (2)
51 #define TME_SUNBW2_TYPE_ONBOARD (3)
52 #define TME_SUNBW2_TYPE_P4 (4)
53 #define TME_SUNBW2_TYPE_SBUS (5)
54
55 /* register offsets and sizes: */
56 #define TME_SUNBW2_REG_CSR_MULTIBUS (0x81800)
57 #define TME_SUNBW2_REG_CSR_OLD_ONBOARD (0x20000)
58 #define TME_SUNBW2_SIZ_CSR (0x00002)
59 #define TME_SUNBW2_SIZ_CSR_PAGE (0x00800)
60
61 /* the bits in the Multibus and old-onboard Control/Status register: */
62 #define TME_SUNBW2_CSR_ENABLE_VIDEO (0x8000) /* enable video */
63 #define TME_SUNBW2_CSR_ENABLE_COPY (0x4000) /* enable copy mode */
64 #define TME_SUNBW2_CSR_ENABLE_INT (0x2000) /* interrupt enable */
65 #define TME_SUNBW2_CSR_INT_ACTIVE (0x1000) /* interrupt is active */
66 #define TME_SUNBW2_CSR_JUMPER_B (0x0800) /* jumper B */
67 #define TME_SUNBW2_CSR_JUMPER_A (0x0400) /* jumper A */
68 #define TME_SUNBW2_CSR_JUMPER_COLOR (0x0200) /* jumper color */
69 #define TME_SUNBW2_CSR_JUMPER_HIRES (0x0100) /* jumper hires */
70 #define TME_SUNBW2_CSR_COPYBASE_MASK (0x007E) /* copybase mask */
71
72 #if 0
73 #define TME_SUNBW2_DEBUG
74 #endif
75
76 /* structures: */
77
78 /* the card: */
79 struct tme_sunbw2 {
80
81 /* our generic Sun framebuffer: */
82 struct tme_sunfb tme_sunbw2_sunfb;
83 #define tme_sunbw2_mutex tme_sunbw2_sunfb.tme_sunfb_mutex
84 #define tme_sunbw2_bus_subregion_memory tme_sunbw2_sunfb.tme_sunfb_bus_subregion_memory
85 #define tme_sunbw2_bus_subregion_regs tme_sunbw2_sunfb.tme_sunfb_bus_subregion_regs
86 #define tme_sunbw2_csr_address tme_sunbw2_bus_subregion_regs.tme_bus_subregion_address_first
87
88 /* the type of the bwtwo: */
89 tme_uint32_t tme_sunbw2_type;
90
91 /* our csr: */
92 tme_uint16_t tme_sunbw2_csr;
93 };
94
95 #ifdef TME_SUNBW2_DEBUG
96 #define TME_SUNBW2_LO_WIDTH (1152)
97 #define TME_SUNBW2_LO_HEIGHT (900)
98 static int
_tme_sunbw2_update_debug(struct tme_fb_connection * conn_fb)99 _tme_sunbw2_update_debug(struct tme_fb_connection *conn_fb)
100 {
101 struct tme_sunbw2 *sunbw2;
102 static int y = -1;
103 static int x;
104 unsigned long pixel;
105 unsigned int pixel_byte;
106 tme_uint8_t pixel_bit;
107 int box, box_y, box_x;
108
109 sunbw2 = conn_fb->tme_fb_connection.tme_connection_element->tme_element_private;
110
111 for (box = 0; box < 2; box++) {
112 if (y < 0) {
113 y = 16;
114 x = 0;
115 continue;
116 }
117 for (box_y = 0; box_y < 2; box_y++) {
118 for (box_x = 0; box_x < 2; box_x++) {
119 pixel = (((y + box_y)
120 * TME_SUNBW2_LO_WIDTH)
121 + x
122 + box_x);
123 pixel_byte = (pixel / 8);
124 pixel_bit = (0x80 >> (pixel % 8));
125 sunbw2->tme_sunbw2_fb_memory[pixel_byte] ^= pixel_bit;
126 }
127 }
128 if (box == 0) {
129 x += 2;
130 if (x == TME_SUNBW2_LO_WIDTH) {
131 x = 0;
132 y += 2;
133 if (y == TME_SUNBW2_LO_HEIGHT) {
134 y = 0;
135 }
136 }
137 }
138 }
139
140 return (TME_OK);
141 }
142 #undef TME_SUNBW2_LO_WIDTH
143 #undef TME_SUNBW2_LO_HEIGHT
144 #endif /* TME_SUNBW2_DEBUG */
145
146 /* the sunbw2 CSR bus cycle handler: */
147 static int
_tme_sunbw2_bus_cycle_csr(void * _sunbw2,struct tme_bus_cycle * cycle_init)148 _tme_sunbw2_bus_cycle_csr(void *_sunbw2, struct tme_bus_cycle *cycle_init)
149 {
150 struct tme_sunbw2 *sunbw2;
151 tme_uint16_t csr_old, csr_new;
152 tme_bus_addr32_t undecoded;
153
154 /* recover our data structure: */
155 sunbw2 = (struct tme_sunbw2 *) _sunbw2;
156
157 /* lock the mutex: */
158 tme_mutex_lock(&sunbw2->tme_sunbw2_mutex);
159
160 /* get the old CSR value: */
161 csr_old = tme_betoh_u16(sunbw2->tme_sunbw2_csr);
162
163 /* the entire 2KB (one page's) worth of addresses at
164 tme_sunbw2_csr_address are all decoded (or, rather, not decoded)
165 as the CSR: */
166 undecoded
167 = (cycle_init->tme_bus_cycle_address
168 & (TME_SUNBW2_SIZ_CSR_PAGE - sizeof(sunbw2->tme_sunbw2_csr)));
169 cycle_init->tme_bus_cycle_address
170 -= undecoded;
171
172 /* run the cycle: */
173 assert (cycle_init->tme_bus_cycle_address
174 >= sunbw2->tme_sunbw2_csr_address);
175 tme_bus_cycle_xfer_memory(cycle_init,
176 (((tme_uint8_t *) &sunbw2->tme_sunbw2_csr)
177 - sunbw2->tme_sunbw2_csr_address),
178 (sunbw2->tme_sunbw2_csr_address
179 + sizeof(sunbw2->tme_sunbw2_csr)
180 - 1));
181 cycle_init->tme_bus_cycle_address
182 += undecoded;
183
184 /* get the new CSR value: */
185 csr_new = tme_betoh_u16(sunbw2->tme_sunbw2_csr);
186
187 /* put back the unchanging bits: */
188 csr_new
189 = ((csr_new
190 & ~(TME_SUNBW2_CSR_INT_ACTIVE
191 | TME_SUNBW2_CSR_JUMPER_B
192 | TME_SUNBW2_CSR_JUMPER_A
193 | TME_SUNBW2_CSR_JUMPER_COLOR
194 | TME_SUNBW2_CSR_JUMPER_HIRES))
195 | (csr_old
196 & (TME_SUNBW2_CSR_INT_ACTIVE
197 | TME_SUNBW2_CSR_JUMPER_B
198 | TME_SUNBW2_CSR_JUMPER_A
199 | TME_SUNBW2_CSR_JUMPER_COLOR
200 | TME_SUNBW2_CSR_JUMPER_HIRES)));
201
202 /* we do not support these bits: */
203 if (csr_new
204 & (TME_SUNBW2_CSR_ENABLE_COPY
205 | TME_SUNBW2_CSR_ENABLE_INT)) {
206 abort();
207 }
208
209 /* set the new CSR value: */
210 sunbw2->tme_sunbw2_csr = tme_htobe_u16(csr_new);
211
212 /* unlock the mutex: */
213 tme_mutex_unlock(&sunbw2->tme_sunbw2_mutex);
214
215 /* no faults: */
216 return (TME_OK);
217 }
218
219 /* this sets the bwtwo type: */
220 static const char *
_tme_sunbw2_type_set(struct tme_sunfb * sunfb,const char * bw2_type_string)221 _tme_sunbw2_type_set(struct tme_sunfb *sunfb, const char *bw2_type_string)
222 {
223 struct tme_sunbw2 *sunbw2;
224 tme_uint32_t bw2_type;
225
226 /* recover our data structure: */
227 sunbw2 = (struct tme_sunbw2 *) sunfb;
228
229 /* see if this is a good type: */
230 bw2_type = TME_SUNBW2_TYPE_NULL;
231 if (TME_ARG_IS(bw2_type_string, "multibus")) {
232 bw2_type = TME_SUNBW2_TYPE_MULTIBUS;
233 }
234 else if (TME_ARG_IS(bw2_type_string, "old-onboard")) {
235 bw2_type = TME_SUNBW2_TYPE_OLD_ONBOARD;
236 }
237 else if (TME_ARG_IS(bw2_type_string, "onboard")) {
238 bw2_type = TME_SUNBW2_TYPE_ONBOARD;
239 }
240 else if (TME_ARG_IS(bw2_type_string, "P4")) {
241 bw2_type = TME_SUNBW2_TYPE_P4;
242 }
243 else if (TME_ARG_IS(bw2_type_string, "sbus")) {
244 bw2_type = TME_SUNBW2_TYPE_SBUS;
245 }
246
247 /* set the new type: */
248 sunbw2->tme_sunbw2_type = bw2_type;
249
250 /* assume the (relative) bus address of the first byte of displayed
251 framebuffer memory is zero: */
252 sunbw2->tme_sunbw2_bus_subregion_memory.tme_bus_subregion_address_first = 0;
253
254 /* assume that we can use the unspecified interrupt: */
255 sunfb->tme_sunfb_bus_signal_int = TME_BUS_SIGNAL_INT_UNSPEC;
256
257 /* dispatch on the new type: */
258 switch (bw2_type) {
259
260 /* if this was a bad type, return a string of types: */
261 default: assert(FALSE);
262 case TME_SUNBW2_TYPE_NULL:
263 return ("multibus | old-onboard | onboard | P4 | sbus");
264
265 case TME_SUNBW2_TYPE_MULTIBUS:
266 case TME_SUNBW2_TYPE_OLD_ONBOARD:
267
268 /* set the addresses of the CSR bus subregion: */
269 sunbw2->tme_sunbw2_csr_address
270 = (bw2_type == TME_SUNBW2_TYPE_MULTIBUS
271 ? TME_SUNBW2_REG_CSR_MULTIBUS
272 : TME_SUNBW2_REG_CSR_OLD_ONBOARD);
273 sunbw2->tme_sunbw2_bus_subregion_regs.tme_bus_subregion_address_last
274 = (sunbw2->tme_sunbw2_csr_address
275 + TME_SUNBW2_SIZ_CSR_PAGE
276 - 1);
277
278 /* set the CSR bus cycle handler: */
279 sunfb->tme_sunfb_bus_handler_regs = _tme_sunbw2_bus_cycle_csr;
280
281 /* the original Multibus bwtwo and onboard bwtwo only support
282 1152x900 and 1024x1024: */
283 sunfb->tme_sunfb_size
284 = (TME_SUNFB_SIZE_1152_900
285 | TME_SUNFB_SIZE_1024_1024);
286 break;
287
288 case TME_SUNBW2_TYPE_ONBOARD:
289
290 /* the onboard bwtwo doesn't have any CSR: */
291 sunfb->tme_sunfb_bus_handler_regs = NULL;
292
293 /* the sizes supported by a CSR-less bwtwo appear to depend on the
294 actual model; we assume the user knows what he is doing: */
295 sunfb->tme_sunfb_size = (TME_SUNFB_SIZE_NULL - 1);
296 break;
297
298 case TME_SUNBW2_TYPE_P4:
299
300 /* set our initial P4 register: */
301 sunfb->tme_sunfb_p4 = tme_htobe_u32(TME_SUNFB_P4_ID_BWTWO);
302
303 /* set the P4 register bus cycle handler: */
304 sunfb->tme_sunfb_bus_handler_regs = tme_sunfb_bus_cycle_p4;
305
306 /* we support the default P4 framebuffer sizes: */
307 sunfb->tme_sunfb_size = 0;
308
309 /* the framebuffer memory begins at a fixed offset after the P4 register: */
310 sunbw2->tme_sunbw2_bus_subregion_memory.tme_bus_subregion_address_first
311 = TME_SUNFB_P4_OFFSET_BITMAP;
312
313 break;
314
315 case TME_SUNBW2_TYPE_SBUS:
316
317 /* set the S4 register bus cycle handler: */
318 sunfb->tme_sunfb_bus_handler_regs = tme_sunfb_bus_cycle_s4;
319
320 /* we support the default S4 framebuffer sizes: */
321 sunfb->tme_sunfb_size = 0;
322
323 /* we use the default S4 memory address: */
324 sunbw2->tme_sunbw2_bus_subregion_memory.tme_bus_subregion_address_first = 0;
325
326 /* the SBus bwtwo uses priority seven interrupts: */
327 sunfb->tme_sunfb_bus_signal_int = TME_BUS_SIGNAL_INT(7);
328
329 break;
330 }
331
332 /* success: */
333 return (NULL);
334 }
335
336 /* the new sun bwtwo function: */
337 int
tme_sun_bwtwo(struct tme_element * element,const char * const * args,char ** _output)338 tme_sun_bwtwo(struct tme_element *element, const char * const *args, char **_output)
339 {
340 struct tme_sunbw2 *sunbw2;
341 int rc;
342 tme_uint16_t v;
343
344 /* start the sunbw2 structure: */
345 sunbw2 = tme_new0(struct tme_sunbw2, 1);
346 sunbw2->tme_sunbw2_sunfb.tme_sunfb_element = element;
347
348 /* initialize the sunfb structure: */
349 sunbw2->tme_sunbw2_sunfb.tme_sunfb_class = TME_FB_XLAT_CLASS_MONOCHROME;
350 sunbw2->tme_sunbw2_sunfb.tme_sunfb_depth = 1;
351 sunbw2->tme_sunbw2_sunfb.tme_sunfb_type_set = _tme_sunbw2_type_set;
352
353 /* if the generic initialization fails: */
354 rc = tme_sunfb_new(&sunbw2->tme_sunbw2_sunfb, args, _output);
355 if (rc) {
356
357 /* free the sunfb structure and return the error: */
358 tme_free(sunbw2);
359 return (rc);
360 }
361
362 /* dispatch on the bwtwo type: */
363 switch (sunbw2->tme_sunbw2_type) {
364 default: break;
365 case TME_SUNBW2_TYPE_MULTIBUS:
366 case TME_SUNBW2_TYPE_OLD_ONBOARD:
367
368 /* set our initial CSR: */
369 v = TME_SUNBW2_CSR_ENABLE_VIDEO | (sunbw2->tme_sunbw2_sunfb.tme_sunfb_size
370 == TME_SUNFB_SIZE_1024_1024
371 ? TME_SUNBW2_CSR_JUMPER_HIRES : 0);
372 sunbw2->tme_sunbw2_csr = tme_htobe_u16(v);
373 break;
374 }
375
376 return (TME_OK);
377 }
378
379