xref: /openbsd-src/sys/arch/sparc64/dev/fb.c (revision 9593dc34da13a12012033a17061c846c208061c2)
1*9593dc34Smglocker /*	$OpenBSD: fb.c,v 1.31 2024/09/04 07:54:52 mglocker Exp $	*/
270d3ea64Smiod /*	$NetBSD: fb.c,v 1.23 1997/07/07 23:30:22 pk Exp $ */
370d3ea64Smiod 
470d3ea64Smiod /*
5607827a8Smiod  * Copyright (c) 2002, 2004, 2008  Miodrag Vallat.
670d3ea64Smiod  * All rights reserved.
770d3ea64Smiod  *
870d3ea64Smiod  * Redistribution and use in source and binary forms, with or without
970d3ea64Smiod  * modification, are permitted provided that the following conditions
1070d3ea64Smiod  * are met:
1170d3ea64Smiod  * 1. Redistributions of source code must retain the above copyright
1270d3ea64Smiod  *    notice, this list of conditions and the following disclaimer.
1370d3ea64Smiod  * 2. Redistributions in binary form must reproduce the above copyright
1470d3ea64Smiod  *    notice, this list of conditions and the following disclaimer in the
1570d3ea64Smiod  *    documentation and/or other materials provided with the distribution.
1670d3ea64Smiod  *
1770d3ea64Smiod  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1870d3ea64Smiod  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
1970d3ea64Smiod  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
2070d3ea64Smiod  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
2170d3ea64Smiod  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
2270d3ea64Smiod  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
2370d3ea64Smiod  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2470d3ea64Smiod  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
2570d3ea64Smiod  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
2670d3ea64Smiod  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2770d3ea64Smiod  * POSSIBILITY OF SUCH DAMAGE.
2870d3ea64Smiod  *
2970d3ea64Smiod  *
3070d3ea64Smiod  * Copyright (c) 1992, 1993
3170d3ea64Smiod  *	The Regents of the University of California.  All rights reserved.
3270d3ea64Smiod  *
3370d3ea64Smiod  * This software was developed by the Computer Systems Engineering group
3470d3ea64Smiod  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
3570d3ea64Smiod  * contributed to Berkeley.
3670d3ea64Smiod  *
3770d3ea64Smiod  * All advertising materials mentioning features or use of this software
3870d3ea64Smiod  * must display the following acknowledgement:
3970d3ea64Smiod  *	This product includes software developed by the University of
4070d3ea64Smiod  *	California, Lawrence Berkeley Laboratory.
4170d3ea64Smiod  *
4270d3ea64Smiod  * Redistribution and use in source and binary forms, with or without
4370d3ea64Smiod  * modification, are permitted provided that the following conditions
4470d3ea64Smiod  * are met:
4570d3ea64Smiod  * 1. Redistributions of source code must retain the above copyright
4670d3ea64Smiod  *    notice, this list of conditions and the following disclaimer.
4770d3ea64Smiod  * 2. Redistributions in binary form must reproduce the above copyright
4870d3ea64Smiod  *    notice, this list of conditions and the following disclaimer in the
4970d3ea64Smiod  *    documentation and/or other materials provided with the distribution.
5070d3ea64Smiod  * 3. Neither the name of the University nor the names of its contributors
5170d3ea64Smiod  *    may be used to endorse or promote products derived from this software
5270d3ea64Smiod  *    without specific prior written permission.
5370d3ea64Smiod  *
5470d3ea64Smiod  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
5570d3ea64Smiod  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
5670d3ea64Smiod  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
5770d3ea64Smiod  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
5870d3ea64Smiod  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
5970d3ea64Smiod  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
6070d3ea64Smiod  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
6170d3ea64Smiod  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
6270d3ea64Smiod  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
6370d3ea64Smiod  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
6470d3ea64Smiod  * SUCH DAMAGE.
6570d3ea64Smiod  *
6670d3ea64Smiod  *	@(#)fb.c	8.1 (Berkeley) 6/11/93
6770d3ea64Smiod  */
6870d3ea64Smiod 
6970d3ea64Smiod /*
7070d3ea64Smiod  * Common wsdisplay framebuffer drivers helpers.
7170d3ea64Smiod  */
7270d3ea64Smiod 
7370d3ea64Smiod #include <sys/param.h>
7470d3ea64Smiod #include <sys/systm.h>
7570d3ea64Smiod #include <sys/device.h>
7670d3ea64Smiod #include <sys/proc.h>
7770d3ea64Smiod #include <sys/conf.h>
7870d3ea64Smiod 
7970d3ea64Smiod #include <machine/autoconf.h>
8070d3ea64Smiod #include <machine/conf.h>
81607827a8Smiod #include <machine/openfirm.h>
8270d3ea64Smiod 
8370d3ea64Smiod #include <dev/wscons/wsdisplayvar.h>
8470d3ea64Smiod #include <dev/rasops/rasops.h>
8570d3ea64Smiod #include <machine/fbvar.h>
8670d3ea64Smiod 
8770d3ea64Smiod #include "wsdisplay.h"
8870d3ea64Smiod 
8970d3ea64Smiod /*
903238630cSmiod  * Sun specific color indexes.
913238630cSmiod  * Black is not really 7, but rather ~0; to fit within the 8 ANSI color
923238630cSmiod  * palette we are using on console, we pick (~0) & 0x07 instead.
933238630cSmiod  * This essentially swaps WSCOL_BLACK and WSCOL_WHITE.
943238630cSmiod  */
953238630cSmiod #define	WSCOL_SUN_WHITE		0
963238630cSmiod #define	WSCOL_SUN_BLACK		7
973238630cSmiod 
983238630cSmiod /*
9970d3ea64Smiod  * emergency unblank code
10070d3ea64Smiod  * XXX should be somewhat moved to wscons MI code
10170d3ea64Smiod  */
10270d3ea64Smiod 
10370d3ea64Smiod void (*fb_burner)(void *, u_int, u_int);
10470d3ea64Smiod void *fb_cookie;
10570d3ea64Smiod 
10670d3ea64Smiod void
1070aac5001Snaddy fb_unblank(void)
10870d3ea64Smiod {
10970d3ea64Smiod 	if (fb_burner != NULL)
11070d3ea64Smiod 		(*fb_burner)(fb_cookie, 1, 0);
11170d3ea64Smiod }
11270d3ea64Smiod 
11370d3ea64Smiod #if NWSDISPLAY > 0
11470d3ea64Smiod 
1152f3b6a47Smiod static int a2int(char *, int);
116607827a8Smiod int	fb_get_console_metrics(int *, int *, int *, int *);
117607827a8Smiod void	fb_initwsd(struct sunfb *);
118607827a8Smiod void	fb_updatecursor(struct rasops_info *);
119607827a8Smiod 
120607827a8Smiod int	fb_alloc_screen(void *, const struct wsscreen_descr *, void **,
121e0c3e559Sjsg 	    int *, int *, uint32_t *);
122607827a8Smiod void	fb_free_screen(void *, void *);
123607827a8Smiod int	fb_show_screen(void *, void *, int, void (*)(void *, int, int),
124607827a8Smiod 	    void *);
12583275742Smiod int	fb_load_font(void *, void *, struct wsdisplay_font *);
12683275742Smiod int	fb_list_font(void *, struct wsdisplay_font *);
1272f3b6a47Smiod 
12870d3ea64Smiod void
12970d3ea64Smiod fb_setsize(struct sunfb *sf, int def_depth, int def_width, int def_height,
13070d3ea64Smiod     int node, int unused)
13170d3ea64Smiod {
13270d3ea64Smiod 	int def_linebytes;
13370d3ea64Smiod 
1349f777a6aSkettenis 	/*
1359f777a6aSkettenis 	 * Some PCI devices lack the `depth' property, but have a `depth '
1369f777a6aSkettenis 	 * property (with a trailing space) instead.
1379f777a6aSkettenis 	 */
1389f777a6aSkettenis 	sf->sf_depth = getpropint(node, "depth",
1399f777a6aSkettenis 	    getpropint(node, "depth ", def_depth));
14070d3ea64Smiod 	sf->sf_width = getpropint(node, "width", def_width);
14170d3ea64Smiod 	sf->sf_height = getpropint(node, "height", def_height);
14270d3ea64Smiod 
14370d3ea64Smiod 	def_linebytes =
14470d3ea64Smiod 	    roundup(sf->sf_width, sf->sf_depth) * sf->sf_depth / 8;
14570d3ea64Smiod 	sf->sf_linebytes = getpropint(node, "linebytes", def_linebytes);
146607827a8Smiod 
14770d3ea64Smiod 	/*
14870d3ea64Smiod 	 * XXX If we are configuring a board in a wider depth level
14970d3ea64Smiod 	 * than the mode it is currently operating in, the PROM will
15070d3ea64Smiod 	 * return a linebytes property tied to the current depth value,
15170d3ea64Smiod 	 * which is NOT what we are relying upon!
15270d3ea64Smiod 	 */
153607827a8Smiod 	if (sf->sf_linebytes < (sf->sf_width * sf->sf_depth) / 8)
15470d3ea64Smiod 		sf->sf_linebytes = def_linebytes;
15570d3ea64Smiod 
15670d3ea64Smiod 	sf->sf_fbsize = sf->sf_height * sf->sf_linebytes;
15770d3ea64Smiod }
15870d3ea64Smiod 
159de9ae89dSmiod static int
16070d3ea64Smiod a2int(char *cp, int deflt)
16170d3ea64Smiod {
16270d3ea64Smiod 	int i = 0;
16370d3ea64Smiod 
16470d3ea64Smiod 	if (*cp == '\0')
16570d3ea64Smiod 		return (deflt);
16670d3ea64Smiod 	while (*cp != '\0')
16770d3ea64Smiod 		i = i * 10 + *cp++ - '0';
16870d3ea64Smiod 	return (i);
16970d3ea64Smiod }
17070d3ea64Smiod 
171de9ae89dSmiod /* setup the embedded wsscreen_descr structure from rasops settings */
172607827a8Smiod void
173de9ae89dSmiod fb_initwsd(struct sunfb *sf)
174de9ae89dSmiod {
175de9ae89dSmiod 	strlcpy(sf->sf_wsd.name, "std", sizeof(sf->sf_wsd.name));
176de9ae89dSmiod 	sf->sf_wsd.capabilities = sf->sf_ro.ri_caps;
177de9ae89dSmiod 	sf->sf_wsd.nrows = sf->sf_ro.ri_rows;
178de9ae89dSmiod 	sf->sf_wsd.ncols = sf->sf_ro.ri_cols;
179de9ae89dSmiod 	sf->sf_wsd.textops = &sf->sf_ro.ri_ops;
180de9ae89dSmiod }
181de9ae89dSmiod 
182607827a8Smiod void
1832f3b6a47Smiod fb_updatecursor(struct rasops_info *ri)
1842f3b6a47Smiod {
1852f3b6a47Smiod 	struct sunfb *sf = (struct sunfb *)ri->ri_hw;
1862f3b6a47Smiod 
1872f3b6a47Smiod 	if (sf->sf_crowp != NULL)
1882f3b6a47Smiod 		*sf->sf_crowp = ri->ri_crow;
1892f3b6a47Smiod 	if (sf->sf_ccolp != NULL)
1902f3b6a47Smiod 		*sf->sf_ccolp = ri->ri_ccol;
1912f3b6a47Smiod }
1922f3b6a47Smiod 
19370d3ea64Smiod void
194607827a8Smiod fbwscons_init(struct sunfb *sf, int flags, int isconsole)
19570d3ea64Smiod {
1960c14c0f0Smiod 	struct rasops_info *ri = &sf->sf_ro;
197607827a8Smiod 	int cols, rows, fw, fh, wt, wl;
19870d3ea64Smiod 
19970d3ea64Smiod 	/* ri_hw and ri_bits must have already been setup by caller */
200607827a8Smiod 	ri->ri_flg = RI_FULLCLEAR | flags;
2010c14c0f0Smiod 	ri->ri_depth = sf->sf_depth;
2020c14c0f0Smiod 	ri->ri_stride = sf->sf_linebytes;
2030c14c0f0Smiod 	ri->ri_width = sf->sf_width;
2040c14c0f0Smiod 	ri->ri_height = sf->sf_height;
20570d3ea64Smiod 
20670d3ea64Smiod 	rows = a2int(getpropstring(optionsnode, "screen-#rows"), 34);
20770d3ea64Smiod 	cols = a2int(getpropstring(optionsnode, "screen-#columns"), 80);
20870d3ea64Smiod 
209607827a8Smiod 	/*
210607827a8Smiod 	 * If the framebuffer width is under 960 pixels, rasops will
211607827a8Smiod 	 * switch from the 12x22 font to the more adequate 8x16 font
212607827a8Smiod 	 * here.
213607827a8Smiod 	 * If we are the console device, we need to adjust two things:
214*9593dc34Smglocker 	 * - the display row should be overridden from the current PROM
215607827a8Smiod 	 *   metrics, since it will not match the PROM reality anymore.
216607827a8Smiod 	 * - the screen needs to be cleared.
217607827a8Smiod 	 *
21834a62e53Skrw 	 * However, to accommodate laptops with specific small fonts,
219607827a8Smiod 	 * it is necessary to compare the resolution with the actual
220607827a8Smiod 	 * font metrics.
221607827a8Smiod 	 */
222607827a8Smiod 
223607827a8Smiod 	if (isconsole) {
224607827a8Smiod 		if (fb_get_console_metrics(&fw, &fh, &wt, &wl) != 0) {
225607827a8Smiod 			/*
226607827a8Smiod 			 * Assume a 12x22 prom font and a centered
227607827a8Smiod 			 * 80x34 console window.
228607827a8Smiod 			 */
229607827a8Smiod 			fw = 12; fh = 22;
230095b369dSmiod 			wt = wl = 0;
231095b369dSmiod 		} else {
232095b369dSmiod 			/*
233095b369dSmiod 			 * Make sure window-top and window-left
234095b369dSmiod 			 * values are consistent with the font metrics.
235095b369dSmiod 			 */
2362dd06ba7Skettenis 			if (wt <= 0 || wt > sf->sf_height - rows * fh ||
2372dd06ba7Skettenis 			    wl <= 0 || wl > sf->sf_width - cols * fw)
238095b369dSmiod 				wt = wl = 0;
23930afeea5Smiod 		}
240095b369dSmiod 		if (wt == 0 /* || wl == 0 */) {
241607827a8Smiod 			ri->ri_flg |= RI_CENTER;
242607827a8Smiod 
243607827a8Smiod 			/*
244607827a8Smiod 			 * Since the console window might not be
245607827a8Smiod 			 * centered (e.g. on a 1280x1024 vigra
246607827a8Smiod 			 * VS-12 frame buffer), have rasops
247607827a8Smiod 			 * clear the margins even if the screen is
248607827a8Smiod 			 * not cleared.
249607827a8Smiod 			 */
250607827a8Smiod 			ri->ri_flg |= RI_CLEARMARGINS;
251607827a8Smiod 		}
252607827a8Smiod 
253607827a8Smiod 		if (ri->ri_wsfcookie != 0) {
254607827a8Smiod 			/* driver handles font issues. do nothing. */
255607827a8Smiod 		} else {
256607827a8Smiod 			/*
257607827a8Smiod 			 * If the PROM uses a different font than the
258607827a8Smiod 			 * one we are expecting it to use, or if the
259607827a8Smiod 			 * display is shorter than 960 pixels wide,
260607827a8Smiod 			 * we'll force a screen clear.
261607827a8Smiod 			 */
262607827a8Smiod 			if (fw != 12 || sf->sf_width < 12 * 80)
263607827a8Smiod 				ri->ri_flg |= RI_CLEAR | RI_CENTER;
264607827a8Smiod 		}
265607827a8Smiod 	} else {
266607827a8Smiod 		ri->ri_flg |= RI_CLEAR | RI_CENTER;
267607827a8Smiod 	}
268607827a8Smiod 
269607827a8Smiod 	/* ifb(4) doesn't set ri_bits at the moment */
270607827a8Smiod 	if (ri->ri_bits == NULL)
2719c2c4db2Smiod 		ri->ri_flg &= ~(RI_CLEAR | RI_CLEARMARGINS);
272607827a8Smiod 
2730c14c0f0Smiod 	rasops_init(ri, rows, cols);
2743049e847Smiod 
275607827a8Smiod 	/*
276607827a8Smiod 	 * If this is the console display and there is no font change,
277607827a8Smiod 	 * adjust our terminal window to the position of the PROM
278607827a8Smiod 	 * window - in case it is not exactly centered.
279607827a8Smiod 	 */
280607827a8Smiod 	if ((ri->ri_flg & RI_CENTER) == 0) {
281607827a8Smiod 		/* code above made sure wt and wl are initialized */
282607827a8Smiod 		ri->ri_bits += wt * ri->ri_stride;
283607827a8Smiod 		if (ri->ri_depth >= 8)	/* for 15bpp to compute ok */
284607827a8Smiod 			ri->ri_bits += wl * ri->ri_pelbytes;
285607827a8Smiod 		else
286607827a8Smiod 			ri->ri_bits += (wl * ri->ri_depth) >> 3;
287607827a8Smiod 
288607827a8Smiod 		ri->ri_xorigin = wl;
289607827a8Smiod 		ri->ri_yorigin = wt;
290607827a8Smiod 	}
291607827a8Smiod 
2923049e847Smiod 	if (sf->sf_depth == 8) {
2933049e847Smiod 		/*
2943049e847Smiod 		 * If we are running with an indexed palette, compensate
2953049e847Smiod 		 * the swap of black and white through ri_devcmap.
2963049e847Smiod 		 */
2973049e847Smiod 		ri->ri_devcmap[WSCOL_SUN_BLACK] = 0;
2983049e847Smiod 		ri->ri_devcmap[WSCOL_SUN_WHITE] = 0xffffffff;
2993049e847Smiod 	} else if (sf->sf_depth > 8) {
3003049e847Smiod 		/*
3013049e847Smiod 		 * If we are running on a direct color frame buffer,
3023049e847Smiod 		 * make the ``normal'' white the same as the highlighted
3033049e847Smiod 		 * white.
3043049e847Smiod 		 */
3053049e847Smiod 		ri->ri_devcmap[WSCOL_WHITE] = ri->ri_devcmap[WSCOL_WHITE + 8];
3063049e847Smiod 	}
30770d3ea64Smiod }
30870d3ea64Smiod 
30970d3ea64Smiod void
310aca70fa6Smiod fbwscons_console_init(struct sunfb *sf, int row)
31170d3ea64Smiod {
3122008d283Smiod 	struct rasops_info *ri = &sf->sf_ro;
3133df54b20Skettenis 	void *cookie;
314e0c3e559Sjsg 	uint32_t defattr;
31570d3ea64Smiod 
3162628683eSmiod 	if (romgetcursoraddr(&sf->sf_crowp, &sf->sf_ccolp))
3172628683eSmiod 		sf->sf_ccolp = sf->sf_crowp = NULL;
3182628683eSmiod 	if (sf->sf_ccolp != NULL)
3192008d283Smiod 		ri->ri_ccol = *sf->sf_ccolp;
32070d3ea64Smiod 
321607827a8Smiod 	if (ri->ri_flg & RI_CLEAR) {
322607827a8Smiod 		/*
323607827a8Smiod 		 * If we have cleared the screen, this is because either
324607827a8Smiod 		 * we are not the console display, or the font has been
325607827a8Smiod 		 * changed.
326607827a8Smiod 		 * In this case, choose not to keep pointers to the PROM
327607827a8Smiod 		 * cursor position, as the values are likely to be inaccurate
328607827a8Smiod 		 * upon shutdown...
329607827a8Smiod 		 */
330607827a8Smiod 		sf->sf_crowp = sf->sf_ccolp = NULL;
331607827a8Smiod 		row = 0;
332607827a8Smiod 	}
333607827a8Smiod 
334607827a8Smiod 	if (row < 0) /* no override */ {
3352628683eSmiod 		if (sf->sf_crowp != NULL)
3362008d283Smiod 			ri->ri_crow = *sf->sf_crowp;
33770d3ea64Smiod 		else
33870d3ea64Smiod 			/* assume last row */
3392008d283Smiod 			ri->ri_crow = ri->ri_rows - 1;
3402628683eSmiod 	} else {
3412008d283Smiod 		ri->ri_crow = row;
3422628683eSmiod 	}
34370d3ea64Smiod 
34470d3ea64Smiod 	/*
34570d3ea64Smiod 	 * Scale back rows and columns if the font would not otherwise
34670d3ea64Smiod 	 * fit on this display. Without this we would panic later.
34770d3ea64Smiod 	 */
3482008d283Smiod 	if (ri->ri_crow >= ri->ri_rows)
3492008d283Smiod 		ri->ri_crow = ri->ri_rows - 1;
3502008d283Smiod 	if (ri->ri_ccol >= ri->ri_cols)
3512008d283Smiod 		ri->ri_ccol = ri->ri_cols - 1;
35270d3ea64Smiod 
35370d3ea64Smiod 	/*
354a0c83eadSjsing 	 * Take care of updating the PROM cursor position as well if we can.
3552f3b6a47Smiod 	 */
3562008d283Smiod 	if (ri->ri_updatecursor != NULL &&
3572f3b6a47Smiod 	    (sf->sf_ccolp != NULL || sf->sf_crowp != NULL))
3582008d283Smiod 		ri->ri_updatecursor = fb_updatecursor;
3592f3b6a47Smiod 
3603df54b20Skettenis 	if (ri->ri_flg & RI_VCONS)
3613df54b20Skettenis 		cookie = ri->ri_active;
3623df54b20Skettenis 	else
3633df54b20Skettenis 		cookie = ri;
3643df54b20Skettenis 
3652008d283Smiod 	if (ISSET(ri->ri_caps, WSSCREEN_WSCOLORS))
366fc223b23Sjsg 		ri->ri_ops.pack_attr(cookie,
36770d3ea64Smiod 		    WSCOL_BLACK, WSCOL_WHITE, WSATTR_WSCOLORS, &defattr);
3682008d283Smiod 	else
369fc223b23Sjsg 		ri->ri_ops.pack_attr(cookie, 0, 0, 0, &defattr);
37070d3ea64Smiod 
371de9ae89dSmiod 	fb_initwsd(sf);
3723df54b20Skettenis 	wsdisplay_cnattach(&sf->sf_wsd, cookie,
3733df54b20Skettenis 	    ri->ri_ccol, ri->ri_crow, defattr);
37470d3ea64Smiod }
37570d3ea64Smiod 
37670d3ea64Smiod void
37770d3ea64Smiod fbwscons_setcolormap(struct sunfb *sf,
37870d3ea64Smiod     void (*setcolor)(void *, u_int, u_int8_t, u_int8_t, u_int8_t))
37970d3ea64Smiod {
38070d3ea64Smiod 	int i;
3813238630cSmiod 	const u_char *color;
38270d3ea64Smiod 
38370d3ea64Smiod 	if (sf->sf_depth <= 8 && setcolor != NULL) {
38470d3ea64Smiod 		for (i = 0; i < 16; i++) {
3853238630cSmiod 			color = &rasops_cmap[i * 3];
38670d3ea64Smiod 			setcolor(sf, i, color[0], color[1], color[2]);
38770d3ea64Smiod 		}
388ce0365c9Smiod 		for (i = 240; i < 256; i++) {
3893238630cSmiod 			color = &rasops_cmap[i * 3];
390ce0365c9Smiod 			setcolor(sf, i, color[0], color[1], color[2]);
391ce0365c9Smiod 		}
3923238630cSmiod 		/*
3933238630cSmiod 		 * Compensate for BoW default hardware palette: existing
3943238630cSmiod 		 * output (which we do not want to affect) is black on
3953238630cSmiod 		 * white with color index 0 being white and 0xff being
3963238630cSmiod 		 * black.
3973238630cSmiod 		 */
3983238630cSmiod 		setcolor(sf, WSCOL_SUN_WHITE, 0xff, 0xff, 0xff);
3993238630cSmiod 		setcolor(sf, 0xff ^ WSCOL_SUN_WHITE, 0, 0, 0);
4003238630cSmiod 		setcolor(sf, WSCOL_SUN_BLACK, 0, 0, 0);
4013238630cSmiod 		setcolor(sf, 0xff ^ (WSCOL_SUN_BLACK), 0xff, 0xff, 0xff);
40270d3ea64Smiod 	}
40370d3ea64Smiod }
40470d3ea64Smiod 
405de9ae89dSmiod void
406de9ae89dSmiod fbwscons_attach(struct sunfb *sf, struct wsdisplay_accessops *op, int isconsole)
407de9ae89dSmiod {
408de9ae89dSmiod 	struct wsemuldisplaydev_attach_args waa;
409de9ae89dSmiod 
410de9ae89dSmiod 	if (isconsole == 0) {
411de9ae89dSmiod 		/* done in wsdisplay_cnattach() earlier if console */
412de9ae89dSmiod 		fb_initwsd(sf);
413aca70fa6Smiod 	} else {
414aca70fa6Smiod 		/* remember screen burner routine */
415aca70fa6Smiod 		fb_burner = op->burn_screen;
416aca70fa6Smiod 		fb_cookie = sf;
417de9ae89dSmiod 	}
418de9ae89dSmiod 
419607827a8Smiod 	/* plug common wsdisplay_accessops if necessary */
420607827a8Smiod 	if (op->alloc_screen == NULL) {
421607827a8Smiod 		op->alloc_screen = fb_alloc_screen;
422607827a8Smiod 		op->free_screen = fb_free_screen;
423607827a8Smiod 		op->show_screen = fb_show_screen;
424607827a8Smiod 	}
42583275742Smiod 	if (op->load_font == NULL) {
42683275742Smiod 		op->load_font = fb_load_font;
42783275742Smiod 		op->list_font = fb_list_font;
42883275742Smiod 	}
429607827a8Smiod 
430ece7a61fSmiod 	sf->sf_scrlist[0] = &sf->sf_wsd;
431cffcb173Smiod 	sf->sf_wsl.nscreens = 1;
432ece7a61fSmiod 	sf->sf_wsl.screens = (const struct wsscreen_descr **)sf->sf_scrlist;
433de9ae89dSmiod 
434de9ae89dSmiod 	waa.console = isconsole;
435cffcb173Smiod 	waa.scrdata = &sf->sf_wsl;
436de9ae89dSmiod 	waa.accessops = op;
437de9ae89dSmiod 	waa.accesscookie = sf;
4382281f83fSmiod 	waa.defaultscreens = 0;
439de9ae89dSmiod 	config_found(&sf->sf_dev, &waa, wsemuldisplaydevprint);
440de9ae89dSmiod }
441de9ae89dSmiod 
442607827a8Smiod /*
443607827a8Smiod  * Common wsdisplay_accessops routines.
444607827a8Smiod  */
445607827a8Smiod int
446607827a8Smiod fb_alloc_screen(void *v, const struct wsscreen_descr *type,
447e0c3e559Sjsg     void **cookiep, int *curxp, int *curyp, uint32_t *attrp)
448607827a8Smiod {
449607827a8Smiod 	struct sunfb *sf = v;
450607827a8Smiod 	struct rasops_info *ri = &sf->sf_ro;
4513df54b20Skettenis 	void *cookie;
452607827a8Smiod 
453607827a8Smiod 	if (sf->sf_nscreens > 0)
454607827a8Smiod 		return (ENOMEM);
455607827a8Smiod 
4563df54b20Skettenis 	if (ri->ri_flg & RI_VCONS)
4573df54b20Skettenis 		cookie = ri->ri_active;
4583df54b20Skettenis 	else
4593df54b20Skettenis 		cookie = ri;
4603df54b20Skettenis 
4613df54b20Skettenis 	*cookiep = cookie;
462607827a8Smiod 	*curyp = 0;
463607827a8Smiod 	*curxp = 0;
464607827a8Smiod 	if (ISSET(ri->ri_caps, WSSCREEN_WSCOLORS))
465fc223b23Sjsg 		ri->ri_ops.pack_attr(cookie,
466607827a8Smiod 		    WSCOL_BLACK, WSCOL_WHITE, WSATTR_WSCOLORS, attrp);
467607827a8Smiod 	else
468fc223b23Sjsg 		ri->ri_ops.pack_attr(cookie, 0, 0, 0, attrp);
469607827a8Smiod 	sf->sf_nscreens++;
470607827a8Smiod 	return (0);
471607827a8Smiod }
472607827a8Smiod 
473607827a8Smiod void
474607827a8Smiod fb_free_screen(void *v, void *cookie)
475607827a8Smiod {
476607827a8Smiod 	struct sunfb *sf = v;
477607827a8Smiod 
478607827a8Smiod 	sf->sf_nscreens--;
479607827a8Smiod }
480607827a8Smiod 
481607827a8Smiod int
482607827a8Smiod fb_show_screen(void *v, void *cookie, int waitok, void (*cb)(void *, int, int),
483607827a8Smiod     void *cbarg)
484607827a8Smiod {
485607827a8Smiod 	return (0);
486607827a8Smiod }
487607827a8Smiod 
488607827a8Smiod int
48983275742Smiod fb_load_font(void *v, void *emulcookie, struct wsdisplay_font *font)
49083275742Smiod {
49183275742Smiod 	struct sunfb *sf = v;
49283275742Smiod 	struct rasops_info *ri = &sf->sf_ro;
49383275742Smiod 
49483275742Smiod 	return rasops_load_font(ri, emulcookie, font);
49583275742Smiod }
49683275742Smiod 
49783275742Smiod int
49883275742Smiod fb_list_font(void *v, struct wsdisplay_font *font)
49983275742Smiod {
50083275742Smiod 	struct sunfb *sf = v;
50183275742Smiod 	struct rasops_info *ri = &sf->sf_ro;
50283275742Smiod 
50383275742Smiod 	return rasops_list_font(ri, font);
50483275742Smiod }
50583275742Smiod 
50683275742Smiod int
507607827a8Smiod fb_get_console_metrics(int *fontwidth, int *fontheight, int *wtop, int *wleft)
508607827a8Smiod {
509607827a8Smiod 	cell_t romheight, romwidth, windowtop, windowleft;
510607827a8Smiod 
511607827a8Smiod 	/*
512607827a8Smiod 	 * Get the PROM font metrics and address
513607827a8Smiod 	 */
514607827a8Smiod 	OF_interpret("stdout @ is my-self "
515607827a8Smiod 	    "addr char-height addr char-width "
516607827a8Smiod 	    "addr window-top addr window-left",
517607827a8Smiod 	    4, &windowleft, &windowtop, &romwidth, &romheight);
518607827a8Smiod 
51988ee6abdSmiod 	if (romheight == 0 || romwidth == 0 ||
52088ee6abdSmiod 	    windowtop == 0 || windowleft == 0)
521607827a8Smiod 		return (1);
522607827a8Smiod 
523607827a8Smiod 	*fontwidth = (int)*(uint64_t *)romwidth;
524607827a8Smiod 	*fontheight = (int)*(uint64_t *)romheight;
525607827a8Smiod 	*wtop = (int)*(uint64_t *)windowtop;
526607827a8Smiod 	*wleft = (int)*(uint64_t *)windowleft;
527607827a8Smiod 
528607827a8Smiod 	return (0);
529607827a8Smiod }
530607827a8Smiod 
53170d3ea64Smiod #endif	/* NWSDISPLAY */
532