xref: /netbsd-src/sys/arch/hp300/dev/diofb.c (revision f4485e648f613c608ba18410921936960a52c1a8)
1*f4485e64Stsutsui /*	$NetBSD: diofb.c,v 1.10 2024/05/01 19:28:33 tsutsui Exp $	*/
2b04b7da8Stsutsui /*	$OpenBSD: diofb.c,v 1.18 2010/12/26 15:40:59 miod Exp $	*/
3b04b7da8Stsutsui 
4b04b7da8Stsutsui /*
5b04b7da8Stsutsui  * Copyright (c) 2005, Miodrag Vallat
6b04b7da8Stsutsui  *
7b04b7da8Stsutsui  * Redistribution and use in source and binary forms, with or without
8b04b7da8Stsutsui  * modification, are permitted provided that the following conditions
9b04b7da8Stsutsui  * are met:
10b04b7da8Stsutsui  * 1. Redistributions of source code must retain the above copyright
11b04b7da8Stsutsui  *    notice, this list of conditions and the following disclaimer.
12b04b7da8Stsutsui  * 2. Redistributions in binary form must reproduce the above copyright
13b04b7da8Stsutsui  *    notice, this list of conditions and the following disclaimer in the
14b04b7da8Stsutsui  *    documentation and/or other materials provided with the distribution.
15b04b7da8Stsutsui  *
16b04b7da8Stsutsui  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17b04b7da8Stsutsui  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18b04b7da8Stsutsui  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19b04b7da8Stsutsui  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
20b04b7da8Stsutsui  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21b04b7da8Stsutsui  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22b04b7da8Stsutsui  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23b04b7da8Stsutsui  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24b04b7da8Stsutsui  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
25b04b7da8Stsutsui  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26b04b7da8Stsutsui  * POSSIBILITY OF SUCH DAMAGE.
27b04b7da8Stsutsui  */
28b04b7da8Stsutsui /*
29b04b7da8Stsutsui  * Copyright (c) 1988 University of Utah.
30b04b7da8Stsutsui  * Copyright (c) 1990, 1993
31b04b7da8Stsutsui  *	The Regents of the University of California.  All rights reserved.
32b04b7da8Stsutsui  *
33b04b7da8Stsutsui  * This code is derived from software contributed to Berkeley by
34b04b7da8Stsutsui  * the Systems Programming Group of the University of Utah Computer
35b04b7da8Stsutsui  * Science Department.
36b04b7da8Stsutsui  *
37b04b7da8Stsutsui  * Redistribution and use in source and binary forms, with or without
38b04b7da8Stsutsui  * modification, are permitted provided that the following conditions
39b04b7da8Stsutsui  * are met:
40b04b7da8Stsutsui  * 1. Redistributions of source code must retain the above copyright
41b04b7da8Stsutsui  *    notice, this list of conditions and the following disclaimer.
42b04b7da8Stsutsui  * 2. Redistributions in binary form must reproduce the above copyright
43b04b7da8Stsutsui  *    notice, this list of conditions and the following disclaimer in the
44b04b7da8Stsutsui  *    documentation and/or other materials provided with the distribution.
45b04b7da8Stsutsui  * 3. Neither the name of the University nor the names of its contributors
46b04b7da8Stsutsui  *    may be used to endorse or promote products derived from this software
47b04b7da8Stsutsui  *    without specific prior written permission.
48b04b7da8Stsutsui  *
49b04b7da8Stsutsui  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50b04b7da8Stsutsui  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51b04b7da8Stsutsui  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52b04b7da8Stsutsui  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53b04b7da8Stsutsui  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54b04b7da8Stsutsui  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55b04b7da8Stsutsui  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56b04b7da8Stsutsui  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57b04b7da8Stsutsui  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58b04b7da8Stsutsui  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59b04b7da8Stsutsui  * SUCH DAMAGE.
60b04b7da8Stsutsui  */
61b04b7da8Stsutsui 
62b04b7da8Stsutsui #include <sys/param.h>
63b04b7da8Stsutsui #include <sys/conf.h>
64b04b7da8Stsutsui #include <sys/proc.h>
65b04b7da8Stsutsui #include <sys/ioctl.h>
66b04b7da8Stsutsui #include <sys/tty.h>
67b04b7da8Stsutsui #include <sys/systm.h>
68b04b7da8Stsutsui #include <sys/device.h>
69b04b7da8Stsutsui #include <sys/bus.h>
70b04b7da8Stsutsui #include <sys/cpu.h>
71b04b7da8Stsutsui 
72b04b7da8Stsutsui #include <machine/autoconf.h>
73b04b7da8Stsutsui 
74b04b7da8Stsutsui #include <dev/wscons/wsconsio.h>
75b04b7da8Stsutsui #include <dev/wscons/wsdisplayvar.h>
76b04b7da8Stsutsui #include <dev/rasops/rasops.h>
77b04b7da8Stsutsui 
78b04b7da8Stsutsui #include <hp300/dev/dioreg.h>
79b04b7da8Stsutsui #include <hp300/dev/diovar.h>
80b04b7da8Stsutsui #include <hp300/dev/diofbreg.h>
81b04b7da8Stsutsui #include <hp300/dev/diofbvar.h>
82b04b7da8Stsutsui 
835d7f465dStsutsui static void	diofb_do_cursor(struct rasops_info *);
845d7f465dStsutsui static void	diofb_copycols(void *, int, int, int, int);
855d7f465dStsutsui static void	diofb_erasecols(void *, int, int, int, long);
865d7f465dStsutsui static void	diofb_copyrows(void *, int, int, int);
875d7f465dStsutsui static void	diofb_eraserows(void *, int, int, long);
885d7f465dStsutsui static int	diofb_allocattr(void *, int, int, int, long *);
89b04b7da8Stsutsui 
90b04b7da8Stsutsui struct diofb diofb_cn;
91b04b7da8Stsutsui 
92b04b7da8Stsutsui /*
93b04b7da8Stsutsui  * Frame buffer geometry initialization
94b04b7da8Stsutsui  */
95b04b7da8Stsutsui 
96b04b7da8Stsutsui int
diofb_fbinquire(struct diofb * fb,int scode,struct diofbreg * fbr)97b04b7da8Stsutsui diofb_fbinquire(struct diofb *fb, int scode, struct diofbreg *fbr)
98b04b7da8Stsutsui {
99b04b7da8Stsutsui 	int fboff, regsize;
100b04b7da8Stsutsui 
101b04b7da8Stsutsui 	if (ISIIOVA(fbr))
102b04b7da8Stsutsui 		fb->regaddr = (uint8_t *)IIOP(fbr);
103b04b7da8Stsutsui 	else
104b04b7da8Stsutsui 		fb->regaddr = dio_scodetopa(scode);
105b04b7da8Stsutsui 
106b04b7da8Stsutsui 	if (fb->fbwidth == 0 || fb->fbheight == 0) {
107b04b7da8Stsutsui 		fb->fbwidth = (fbr->fbwmsb << 8) | fbr->fbwlsb;
108b04b7da8Stsutsui 		fb->fbheight = (fbr->fbhmsb << 8) | fbr->fbhlsb;
109b04b7da8Stsutsui 	}
110b04b7da8Stsutsui 	fb->fbsize = fb->fbwidth * fb->fbheight;
111b04b7da8Stsutsui 
112b04b7da8Stsutsui 	fb->regkva = (uint8_t *)fbr;
113b04b7da8Stsutsui 	fboff = (fbr->fbomsb << 8) | fbr->fbolsb;
114b04b7da8Stsutsui 	fb->fbaddr = (uint8_t *) (*((uint8_t *)fbr + fboff) << 16);
115b04b7da8Stsutsui 
116b04b7da8Stsutsui 	if (fb->regaddr >= (uint8_t *)DIOII_BASE) {
117b04b7da8Stsutsui 		/*
118b04b7da8Stsutsui 		 * For DIO-II space the fbaddr just computed is
119b04b7da8Stsutsui 		 * the offset from the select code base (regaddr)
120b04b7da8Stsutsui 		 * of the framebuffer.  Hence it is also implicitly
121b04b7da8Stsutsui 		 * the size of the set.
122b04b7da8Stsutsui 		 */
123b04b7da8Stsutsui 		regsize = (uintptr_t)fb->fbaddr;
124b04b7da8Stsutsui 		fb->fbaddr = fb->regaddr + (uintptr_t)fb->fbaddr;
125b04b7da8Stsutsui 		fb->fbkva = (uint8_t *)fbr + regsize;
126b04b7da8Stsutsui 	} else {
127b04b7da8Stsutsui 		/*
128b04b7da8Stsutsui 		 * For internal or DIO-I space we need to map the separate
129b04b7da8Stsutsui 		 * framebuffer.
130b04b7da8Stsutsui 		 */
131b04b7da8Stsutsui 		fb->fbkva = iomap(fb->fbaddr, fb->fbsize);
132b04b7da8Stsutsui 		if (fb->fbkva == NULL)
1335d7f465dStsutsui 			return ENOMEM;
134b04b7da8Stsutsui 	}
135b04b7da8Stsutsui 	if (fb->dwidth == 0 || fb->dheight == 0) {
136b04b7da8Stsutsui 		fb->dwidth = (fbr->dwmsb << 8) | fbr->dwlsb;
137b04b7da8Stsutsui 		fb->dheight = (fbr->dhmsb << 8) | fbr->dhlsb;
138b04b7da8Stsutsui 	}
139b04b7da8Stsutsui 
140b04b7da8Stsutsui 	/*
141b04b7da8Stsutsui 	 * Some displays, such as the DaVinci, appear to return a display
142b04b7da8Stsutsui 	 * height larger than the frame buffer height.
143b04b7da8Stsutsui 	 */
144b04b7da8Stsutsui 	if (fb->dwidth > fb->fbwidth)
145b04b7da8Stsutsui 		fb->dwidth = fb->fbwidth;
146b04b7da8Stsutsui 	if (fb->dheight > fb->fbheight)
147b04b7da8Stsutsui 		fb->dheight = fb->fbheight;
148b04b7da8Stsutsui 
149b04b7da8Stsutsui 	fb->planes = fbr->num_planes;
150b04b7da8Stsutsui 	if (fb->planes > 8)
151b04b7da8Stsutsui 		fb->planes = 8;
152b04b7da8Stsutsui 	fb->planemask = (1 << fb->planes) - 1;
153b04b7da8Stsutsui 
154b04b7da8Stsutsui 	fb->mapmode = WSDISPLAYIO_MODE_DUMBFB;
155b04b7da8Stsutsui 
1565d7f465dStsutsui 	return 0;
157b04b7da8Stsutsui }
158b04b7da8Stsutsui 
159b04b7da8Stsutsui /*
160b04b7da8Stsutsui  * Frame buffer rasops and colormap setup
161b04b7da8Stsutsui  */
162b04b7da8Stsutsui 
163b04b7da8Stsutsui void
diofb_fbsetup(struct diofb * fb)164b04b7da8Stsutsui diofb_fbsetup(struct diofb *fb)
165b04b7da8Stsutsui {
166b04b7da8Stsutsui 	struct rasops_info *ri = &fb->ri;
167b04b7da8Stsutsui 
168b04b7da8Stsutsui 	/*
169b04b7da8Stsutsui 	 * Pretend we are an 8bpp frame buffer, unless ri_depth is already
170b04b7da8Stsutsui 	 * initialized, since this is how it is supposed to be addressed.
171b04b7da8Stsutsui 	 * (Hyperion forces 1bpp because it is really 1bpp addressed).
172b04b7da8Stsutsui 	 */
173b04b7da8Stsutsui 	if (ri->ri_depth == 0)
174b04b7da8Stsutsui 		ri->ri_depth = 8;
175b04b7da8Stsutsui 	ri->ri_stride = (fb->fbwidth * ri->ri_depth) / 8;
176b04b7da8Stsutsui 
177b04b7da8Stsutsui 	ri->ri_flg = RI_CENTER | RI_FULLCLEAR;
178b04b7da8Stsutsui 	/* We don't really support colors on less than 4bpp frame buffers */
179b04b7da8Stsutsui 	if (fb->planes < 4)
180b04b7da8Stsutsui 		ri->ri_flg |= RI_FORCEMONO;
181b04b7da8Stsutsui 	if (fb == &diofb_cn)
182b04b7da8Stsutsui 		ri->ri_flg |= RI_NO_AUTO;
183b04b7da8Stsutsui 	ri->ri_bits = fb->fbkva;
184b04b7da8Stsutsui 	ri->ri_width = fb->dwidth;
185b04b7da8Stsutsui 	ri->ri_height = fb->dheight;
186b04b7da8Stsutsui 	ri->ri_hw = fb;
187b04b7da8Stsutsui 
188b04b7da8Stsutsui 	/*
189b04b7da8Stsutsui 	 * Ask for an unholy big display, rasops will trim this to more
190b04b7da8Stsutsui 	 * reasonable values.
191b04b7da8Stsutsui 	 */
192b04b7da8Stsutsui 	rasops_init(ri, 160, 160);
193b04b7da8Stsutsui 
194b04b7da8Stsutsui 	diofb_resetcmap(fb);
195b04b7da8Stsutsui 
196b04b7da8Stsutsui 	/*
197b04b7da8Stsutsui 	 * For low depth frame buffers, since we have faked a 8bpp frame buffer
198b04b7da8Stsutsui 	 * to rasops, we actually have to remove capabilities.
199b04b7da8Stsutsui 	 */
200b04b7da8Stsutsui 	if (fb->planes == 4) {
201b04b7da8Stsutsui 		ri->ri_ops.allocattr = diofb_allocattr;
202b04b7da8Stsutsui 		ri->ri_caps &= ~WSSCREEN_HILIT;
203b04b7da8Stsutsui 	}
204b04b7da8Stsutsui 
205b04b7da8Stsutsui 	ri->ri_ops.copycols = diofb_copycols;
206b04b7da8Stsutsui 	ri->ri_ops.erasecols = diofb_erasecols;
207b04b7da8Stsutsui 	if (ri->ri_depth != 1) {
208b04b7da8Stsutsui 		ri->ri_ops.copyrows = diofb_copyrows;
209b04b7da8Stsutsui 		ri->ri_ops.eraserows = diofb_eraserows;
210b04b7da8Stsutsui 		ri->ri_do_cursor = diofb_do_cursor;
211b04b7da8Stsutsui 	}
212b04b7da8Stsutsui 
213b04b7da8Stsutsui 	/* Clear entire display, including non visible areas */
214b04b7da8Stsutsui 	(*fb->bmv)(fb, 0, 0, 0, 0, fb->fbwidth, fb->fbheight, RR_CLEAR, 0xff);
215b04b7da8Stsutsui 
216b04b7da8Stsutsui 	fb->wsd.name = fb->wsdname;
217b04b7da8Stsutsui 	fb->wsd.ncols = ri->ri_cols;
218b04b7da8Stsutsui 	fb->wsd.nrows = ri->ri_rows;
219b04b7da8Stsutsui 	fb->wsd.textops = &ri->ri_ops;
220b04b7da8Stsutsui 	fb->wsd.fontwidth = ri->ri_font->fontwidth;
221b04b7da8Stsutsui 	fb->wsd.fontheight = ri->ri_font->fontheight;
222b04b7da8Stsutsui 	fb->wsd.capabilities = ri->ri_caps;
223b04b7da8Stsutsui 	strlcpy(fb->wsdname, "std", sizeof(fb->wsdname));
224b04b7da8Stsutsui }
225b04b7da8Stsutsui 
226b04b7da8Stsutsui /*
227b04b7da8Stsutsui  * Setup default emulation mode colormap
228b04b7da8Stsutsui  */
229b04b7da8Stsutsui void
diofb_resetcmap(struct diofb * fb)230b04b7da8Stsutsui diofb_resetcmap(struct diofb *fb)
231b04b7da8Stsutsui {
232b04b7da8Stsutsui 	const u_char *color;
233b04b7da8Stsutsui 	u_int i;
234b04b7da8Stsutsui 
235b04b7da8Stsutsui 	/* start with the rasops colormap */
236b04b7da8Stsutsui 	color = (const u_char *)rasops_cmap;
237b04b7da8Stsutsui 	for (i = 0; i < 256; i++) {
238b04b7da8Stsutsui 		fb->cmap.r[i] = *color++;
239b04b7da8Stsutsui 		fb->cmap.g[i] = *color++;
240b04b7da8Stsutsui 		fb->cmap.b[i] = *color++;
241b04b7da8Stsutsui 	}
242b04b7da8Stsutsui 
243b04b7da8Stsutsui 	/*
244b04b7da8Stsutsui 	 * Tweak colormap
245b04b7da8Stsutsui 	 *
246b04b7da8Stsutsui 	 * Due to the way rasops cursor work, we need to provide
247b04b7da8Stsutsui 	 * copies of the 8 or 16 basic colors at extra locations
248b04b7da8Stsutsui 	 * in 4bpp and 6bpp mode. This is because missing planes
249b04b7da8Stsutsui 	 * accept writes but read back as zero.
250b04b7da8Stsutsui 	 *
251b04b7da8Stsutsui 	 * So, in 6bpp mode:
252b04b7da8Stsutsui 	 *   00 gets inverted to ff, read back as 3f
253b04b7da8Stsutsui 	 *   3f gets inverted to c0, read back as 00
254b04b7da8Stsutsui 	 * and in 4bpp mode:
255b04b7da8Stsutsui 	 *   00 gets inverted to ff, read back as 0f
256b04b7da8Stsutsui 	 *   0f gets inverted to f0, read back as 00
257b04b7da8Stsutsui 	 */
258b04b7da8Stsutsui 
259b04b7da8Stsutsui 	switch (fb->planes) {
260b04b7da8Stsutsui 	case 6:
261b04b7da8Stsutsui 		/*
262b04b7da8Stsutsui 		 * 00-0f normal colors
263b04b7da8Stsutsui 		 * 30-3f inverted colors
264b04b7da8Stsutsui 		 * c0-cf normal colors
265b04b7da8Stsutsui 		 * f0-ff inverted colors
266b04b7da8Stsutsui 		 */
267b04b7da8Stsutsui 		memcpy(fb->cmap.r + 0xc0, fb->cmap.r + 0x00, 0x10);
268b04b7da8Stsutsui 		memcpy(fb->cmap.g + 0xc0, fb->cmap.g + 0x00, 0x10);
269b04b7da8Stsutsui 		memcpy(fb->cmap.b + 0xc0, fb->cmap.b + 0x00, 0x10);
270b04b7da8Stsutsui 		memcpy(fb->cmap.r + 0x30, fb->cmap.r + 0xf0, 0x10);
271b04b7da8Stsutsui 		memcpy(fb->cmap.g + 0x30, fb->cmap.g + 0xf0, 0x10);
272b04b7da8Stsutsui 		memcpy(fb->cmap.b + 0x30, fb->cmap.b + 0xf0, 0x10);
273b04b7da8Stsutsui 		break;
274b04b7da8Stsutsui 	case 4:
275b04b7da8Stsutsui 		/*
276b04b7da8Stsutsui 		 * 00-07 normal colors
277b04b7da8Stsutsui 		 * 08-0f inverted colors
278b04b7da8Stsutsui 		 * highlighted colors are not available.
279b04b7da8Stsutsui 		 */
280b04b7da8Stsutsui 		memcpy(fb->cmap.r + 0x08, fb->cmap.r + 0xf8, 0x08);
281b04b7da8Stsutsui 		memcpy(fb->cmap.g + 0x08, fb->cmap.g + 0xf8, 0x08);
282b04b7da8Stsutsui 		memcpy(fb->cmap.b + 0x08, fb->cmap.b + 0xf8, 0x08);
283b04b7da8Stsutsui 		break;
284b04b7da8Stsutsui 	}
285b04b7da8Stsutsui }
286b04b7da8Stsutsui 
287b04b7da8Stsutsui /*
288b04b7da8Stsutsui  * Attachment helpers
289b04b7da8Stsutsui  */
290b04b7da8Stsutsui 
291b04b7da8Stsutsui void
diofb_cnattach(struct diofb * fb)292b04b7da8Stsutsui diofb_cnattach(struct diofb *fb)
293b04b7da8Stsutsui {
294b04b7da8Stsutsui 	long defattr;
295b04b7da8Stsutsui 	struct rasops_info *ri;
296b04b7da8Stsutsui 
297b04b7da8Stsutsui 	ri = &fb->ri;
298b04b7da8Stsutsui 	ri->ri_ops.allocattr(ri, 0, 0, 0, &defattr);
299b04b7da8Stsutsui 	wsdisplay_cnattach(&fb->wsd, ri, 0, 0, defattr);
300b04b7da8Stsutsui }
301b04b7da8Stsutsui 
302b04b7da8Stsutsui void
diofb_end_attach(device_t self,struct wsdisplay_accessops * accessops,struct diofb * fb,int console,const char * descr)303b04b7da8Stsutsui diofb_end_attach(device_t self, struct wsdisplay_accessops *accessops,
304b04b7da8Stsutsui     struct diofb *fb, int console, const char *descr)
305b04b7da8Stsutsui {
306b04b7da8Stsutsui 	struct wsemuldisplaydev_attach_args waa;
307b04b7da8Stsutsui 
3082ba8a55cStsutsui 	aprint_normal(": %dx%d", fb->dwidth, fb->dheight);
309b04b7da8Stsutsui 
310b04b7da8Stsutsui 	if (fb->planes == 1)
3112ba8a55cStsutsui 		aprint_normal(" monochrome");
312b04b7da8Stsutsui 	else
3132ba8a55cStsutsui 		aprint_normal("x%d", fb->planes);
314b04b7da8Stsutsui 
315b04b7da8Stsutsui 	if (descr != NULL)
3162ba8a55cStsutsui 		aprint_normal(" %s", descr);
3172ba8a55cStsutsui 	aprint_normal(" frame buffer\n");
318b04b7da8Stsutsui 
319b04b7da8Stsutsui 	fb->scrlist[0] = &fb->wsd;
320b04b7da8Stsutsui 	fb->wsl.nscreens = 1;
321bde065f0Schristos 	fb->wsl.screens = (void *)fb->scrlist;
322b04b7da8Stsutsui 
323b04b7da8Stsutsui 	waa.console = console;
324b04b7da8Stsutsui 	waa.scrdata = &fb->wsl;
325b04b7da8Stsutsui 	waa.accessops = accessops;
326b04b7da8Stsutsui 	waa.accesscookie = fb;
327b04b7da8Stsutsui 
328c7fb772bSthorpej 	config_found(self, &waa, wsemuldisplaydevprint, CFARGS_NONE);
329b04b7da8Stsutsui }
330b04b7da8Stsutsui 
331b04b7da8Stsutsui /*
332b04b7da8Stsutsui  * Common wsdisplay emulops for DIO frame buffers
333b04b7da8Stsutsui  */
334b04b7da8Stsutsui 
335b04b7da8Stsutsui int
diofb_allocattr(void * cookie,int fg,int bg,int flg,long * attr)336b04b7da8Stsutsui diofb_allocattr(void *cookie, int fg, int bg, int flg, long *attr)
337b04b7da8Stsutsui {
3385d7f465dStsutsui 
339b04b7da8Stsutsui 	if ((flg & (WSATTR_BLINK | WSATTR_HILIT)) != 0)
3405d7f465dStsutsui 		return EINVAL;
341b04b7da8Stsutsui 
342b04b7da8Stsutsui 	if ((flg & WSATTR_WSCOLORS) == 0) {
343b04b7da8Stsutsui 		fg = WSCOL_WHITE;
344b04b7da8Stsutsui 		bg = WSCOL_BLACK;
345b04b7da8Stsutsui 	}
346b04b7da8Stsutsui 
347b04b7da8Stsutsui 	if ((flg & WSATTR_REVERSE) != 0) {
348b04b7da8Stsutsui 		int swap;
349b04b7da8Stsutsui 		swap = fg;
350b04b7da8Stsutsui 		fg = bg;
351b04b7da8Stsutsui 		bg = swap;
352b04b7da8Stsutsui 	}
353b04b7da8Stsutsui 
35464b0a54cStsutsui 	*attr = (bg << 16) | (fg << 24) | (flg & WSATTR_UNDERLINE);
355b04b7da8Stsutsui 
356b04b7da8Stsutsui 	return 0;
357b04b7da8Stsutsui }
358b04b7da8Stsutsui 
359b04b7da8Stsutsui void
diofb_copycols(void * cookie,int row,int src,int dst,int n)360b04b7da8Stsutsui diofb_copycols(void *cookie, int row, int src, int dst, int n)
361b04b7da8Stsutsui {
362b04b7da8Stsutsui 	struct rasops_info *ri = cookie;
363b04b7da8Stsutsui 	struct diofb *fb = ri->ri_hw;
364*f4485e64Stsutsui 	int fontwidth = fb->wsd.fontwidth;
365b04b7da8Stsutsui 
366*f4485e64Stsutsui 	n *= fontwidth;
367*f4485e64Stsutsui 	src *= fontwidth;
368*f4485e64Stsutsui 	dst *= fontwidth;
369b04b7da8Stsutsui 	row *= ri->ri_font->fontheight;
370b04b7da8Stsutsui 
371b04b7da8Stsutsui 	(*fb->bmv)(fb, ri->ri_xorigin + src, ri->ri_yorigin + row,
372b04b7da8Stsutsui 	    ri->ri_xorigin + dst, ri->ri_yorigin + row,
373b04b7da8Stsutsui 	    n, ri->ri_font->fontheight, RR_COPY, 0xff);
374b04b7da8Stsutsui }
375b04b7da8Stsutsui 
376b04b7da8Stsutsui void
diofb_copyrows(void * cookie,int src,int dst,int n)377b04b7da8Stsutsui diofb_copyrows(void *cookie, int src, int dst, int n)
378b04b7da8Stsutsui {
379b04b7da8Stsutsui 	struct rasops_info *ri = cookie;
380b04b7da8Stsutsui 	struct diofb *fb = ri->ri_hw;
381b04b7da8Stsutsui 
382b04b7da8Stsutsui 	n *= ri->ri_font->fontheight;
383b04b7da8Stsutsui 	src *= ri->ri_font->fontheight;
384b04b7da8Stsutsui 	dst *= ri->ri_font->fontheight;
385b04b7da8Stsutsui 
386b04b7da8Stsutsui 	(*fb->bmv)(fb, ri->ri_xorigin, ri->ri_yorigin + src,
387b04b7da8Stsutsui 	    ri->ri_xorigin, ri->ri_yorigin + dst,
388b04b7da8Stsutsui 	    ri->ri_emuwidth, n, RR_COPY, 0xff);
389b04b7da8Stsutsui }
390b04b7da8Stsutsui 
391b04b7da8Stsutsui void
diofb_erasecols(void * cookie,int row,int col,int num,long attr)392b04b7da8Stsutsui diofb_erasecols(void *cookie, int row, int col, int num, long attr)
393b04b7da8Stsutsui {
394b04b7da8Stsutsui 	struct rasops_info *ri = cookie;
395b04b7da8Stsutsui 	struct diofb *fb = ri->ri_hw;
396b04b7da8Stsutsui 	int fg, bg;
397b04b7da8Stsutsui 	int snum, scol, srow;
398*f4485e64Stsutsui 	int fontwidth = fb->wsd.fontwidth;
399b04b7da8Stsutsui 
400b04b7da8Stsutsui 	rasops_unpack_attr(attr, &fg, &bg, NULL);
401b04b7da8Stsutsui 
402*f4485e64Stsutsui 	snum = num * fontwidth;
403*f4485e64Stsutsui 	scol = col * fontwidth + ri->ri_xorigin;
404b04b7da8Stsutsui 	srow = row * ri->ri_font->fontheight + ri->ri_yorigin;
405b04b7da8Stsutsui 
406b04b7da8Stsutsui 	/*
407b04b7da8Stsutsui 	 * If this is too tricky for the simple raster ops engine,
408b04b7da8Stsutsui 	 * pass the fun to rasops.
409b04b7da8Stsutsui 	 */
410b04b7da8Stsutsui 	if ((*fb->bmv)(fb, scol, srow, scol, srow, snum,
411b04b7da8Stsutsui 	    ri->ri_font->fontheight, RR_CLEAR, 0xff ^ bg) != 0)
412b04b7da8Stsutsui 		rasops_erasecols(cookie, row, col, num, attr);
413b04b7da8Stsutsui }
414b04b7da8Stsutsui 
415b04b7da8Stsutsui void
diofb_eraserows(void * cookie,int row,int num,long attr)416b04b7da8Stsutsui diofb_eraserows(void *cookie, int row, int num, long attr)
417b04b7da8Stsutsui {
418b04b7da8Stsutsui 	struct rasops_info *ri = cookie;
419b04b7da8Stsutsui 	struct diofb *fb = ri->ri_hw;
420b04b7da8Stsutsui 	int fg, bg;
421b04b7da8Stsutsui 	int srow, snum;
422b04b7da8Stsutsui 	int rc;
423b04b7da8Stsutsui 
424b04b7da8Stsutsui 	rasops_unpack_attr(attr, &fg, &bg, NULL);
425b04b7da8Stsutsui 	bg ^= 0xff;
426b04b7da8Stsutsui 
427b04b7da8Stsutsui 	if (num == ri->ri_rows && (ri->ri_flg & RI_FULLCLEAR)) {
428*f4485e64Stsutsui 		rc = (*fb->bmv)(fb, 0, 0, 0, 0, fb->fbwidth, ri->ri_height,
429b04b7da8Stsutsui 		    RR_CLEAR, bg);
430b04b7da8Stsutsui 	} else {
431b04b7da8Stsutsui 		srow = row * ri->ri_font->fontheight + ri->ri_yorigin;
432b04b7da8Stsutsui 		snum = num * ri->ri_font->fontheight;
433b04b7da8Stsutsui 		rc = (*fb->bmv)(fb, ri->ri_xorigin, srow, ri->ri_xorigin,
434b04b7da8Stsutsui 		    srow, ri->ri_emuwidth, snum, RR_CLEAR, bg);
435b04b7da8Stsutsui 	}
436b04b7da8Stsutsui 	if (rc != 0)
437b04b7da8Stsutsui 		rasops_eraserows(cookie, row, num, attr);
438b04b7da8Stsutsui }
439b04b7da8Stsutsui 
440b04b7da8Stsutsui void
diofb_do_cursor(struct rasops_info * ri)441b04b7da8Stsutsui diofb_do_cursor(struct rasops_info *ri)
442b04b7da8Stsutsui {
443b04b7da8Stsutsui 	struct diofb *fb = ri->ri_hw;
444b04b7da8Stsutsui 	int x, y;
445*f4485e64Stsutsui 	int fontwidth = fb->wsd.fontwidth;
446b04b7da8Stsutsui 
447*f4485e64Stsutsui 	x = ri->ri_ccol * fontwidth + ri->ri_xorigin;
448b04b7da8Stsutsui 	y = ri->ri_crow * ri->ri_font->fontheight + ri->ri_yorigin;
449*f4485e64Stsutsui 	(*fb->bmv)(fb, x, y, x, y, fontwidth,
450b04b7da8Stsutsui 	    ri->ri_font->fontheight, RR_INVERT, 0xff);
451b04b7da8Stsutsui }
452b04b7da8Stsutsui 
453b04b7da8Stsutsui /*
454b04b7da8Stsutsui  * Common wsdisplay accessops for DIO frame buffers
455b04b7da8Stsutsui  */
456b04b7da8Stsutsui 
457b04b7da8Stsutsui int
diofb_alloc_screen(void * v,const struct wsscreen_descr * type,void ** cookiep,int * curxp,int * curyp,long * attrp)458b04b7da8Stsutsui diofb_alloc_screen(void *v, const struct wsscreen_descr *type,
459b04b7da8Stsutsui     void **cookiep, int *curxp, int *curyp, long *attrp)
460b04b7da8Stsutsui {
461b04b7da8Stsutsui 	struct diofb *fb = v;
462b04b7da8Stsutsui 	struct rasops_info *ri = &fb->ri;
463b04b7da8Stsutsui 
464b04b7da8Stsutsui 	if (fb->nscreens > 0)
4655d7f465dStsutsui 		return ENOMEM;
466b04b7da8Stsutsui 
467b04b7da8Stsutsui 	*cookiep = ri;
468b04b7da8Stsutsui 	*curxp = *curyp = 0;
469b04b7da8Stsutsui 	ri->ri_ops.allocattr(ri, 0, 0, 0, attrp);
470b04b7da8Stsutsui 	fb->nscreens++;
471b04b7da8Stsutsui 
4725d7f465dStsutsui 	return 0;
473b04b7da8Stsutsui }
474b04b7da8Stsutsui 
475b04b7da8Stsutsui void
diofb_free_screen(void * v,void * cookie)476b04b7da8Stsutsui diofb_free_screen(void *v, void *cookie)
477b04b7da8Stsutsui {
478b04b7da8Stsutsui 	struct diofb *fb = v;
479b04b7da8Stsutsui 
480b04b7da8Stsutsui 	fb->nscreens--;
481b04b7da8Stsutsui }
482b04b7da8Stsutsui 
483b04b7da8Stsutsui int
diofb_show_screen(void * v,void * cookie,int waitok,void (* cb)(void *,int,int),void * cbarg)484b04b7da8Stsutsui diofb_show_screen(void *v, void *cookie, int waitok,
485b04b7da8Stsutsui     void (*cb)(void *, int, int), void *cbarg)
486b04b7da8Stsutsui {
4875d7f465dStsutsui 
4885d7f465dStsutsui 	return 0;
489b04b7da8Stsutsui }
490b04b7da8Stsutsui 
491b04b7da8Stsutsui paddr_t
diofb_mmap(void * v,void * vs,off_t offset,int prot)492b04b7da8Stsutsui diofb_mmap(void *v, void *vs, off_t offset, int prot)
493b04b7da8Stsutsui {
494b04b7da8Stsutsui 	struct diofb *fb = v;
495b04b7da8Stsutsui 
496b04b7da8Stsutsui 	if ((offset & PAGE_MASK) != 0)
4975d7f465dStsutsui 		return -1;
498b04b7da8Stsutsui 
499b04b7da8Stsutsui 	switch (fb->mapmode) {
500b04b7da8Stsutsui 	case WSDISPLAYIO_MODE_MAPPED:
501b04b7da8Stsutsui 		if (offset >= 0 && offset < DIOFB_REGSPACE)
502b04b7da8Stsutsui 			return m68k_btop(fb->regaddr + offset);
503b04b7da8Stsutsui 		offset -= DIOFB_REGSPACE;
504b04b7da8Stsutsui 		/* FALLTHROUGH */
505b04b7da8Stsutsui 	case WSDISPLAYIO_MODE_DUMBFB:
506b04b7da8Stsutsui 		if (offset >= 0 && offset < fb->fbsize)
507b04b7da8Stsutsui 			return m68k_btop(fb->fbaddr + offset);
508b04b7da8Stsutsui 		break;
509b04b7da8Stsutsui 	}
510b04b7da8Stsutsui 
5115d7f465dStsutsui 	return -1;
512b04b7da8Stsutsui }
513b04b7da8Stsutsui 
514b04b7da8Stsutsui int
diofb_getcmap(struct diofb * fb,struct wsdisplay_cmap * cm)515b04b7da8Stsutsui diofb_getcmap(struct diofb *fb, struct wsdisplay_cmap *cm)
516b04b7da8Stsutsui {
517b04b7da8Stsutsui 	u_int index = cm->index, count = cm->count;
518b04b7da8Stsutsui 	u_int colcount = 1 << fb->planes;
519b04b7da8Stsutsui 	int error;
520b04b7da8Stsutsui 
521b04b7da8Stsutsui 	if (index >= colcount || count > colcount - index)
5225d7f465dStsutsui 		return EINVAL;
523b04b7da8Stsutsui 
524b04b7da8Stsutsui 	if ((error = copyout(fb->cmap.r + index, cm->red, count)) != 0)
5255d7f465dStsutsui 		return error;
526b04b7da8Stsutsui 	if ((error = copyout(fb->cmap.g + index, cm->green, count)) != 0)
5275d7f465dStsutsui 		return error;
528b04b7da8Stsutsui 	if ((error = copyout(fb->cmap.b + index, cm->blue, count)) != 0)
5295d7f465dStsutsui 		return error;
530b04b7da8Stsutsui 
5315d7f465dStsutsui 	return 0;
532b04b7da8Stsutsui }
533