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