xref: /netbsd/sys/arch/luna68k/dev/omrasops.c (revision dd56f03d)
1 /* $NetBSD: omrasops.c,v 1.19 2014/10/04 16:58:17 tsutsui Exp $ */
2 
3 /*-
4  * Copyright (c) 2000 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Tohru Nishimura.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
33 
34 __KERNEL_RCSID(0, "$NetBSD: omrasops.c,v 1.19 2014/10/04 16:58:17 tsutsui Exp $");
35 
36 /*
37  * Designed speficically for 'm68k bitorder';
38  *	- most significant byte is stored at lower address,
39  *	- most significant bit is displayed at left most on screen.
40  * Implementation relies on;
41  *	- first column is at 32bit aligned address,
42  *	- font glyphs are stored in 32bit padded.
43  */
44 
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/device.h>
48 
49 #include <dev/wscons/wsconsio.h>
50 #include <dev/wscons/wsdisplayvar.h>
51 #include <dev/rasops/rasops.h>
52 
53 #include <arch/luna68k/dev/omrasopsvar.h>
54 
55 /* wscons emulator operations */
56 static void	om1_cursor(void *, int, int, int);
57 static void	om4_cursor(void *, int, int, int);
58 static int	om_mapchar(void *, int, unsigned int *);
59 static void	om1_putchar(void *, int, int, u_int, long);
60 static void	om4_putchar(void *, int, int, u_int, long);
61 static void	om1_copycols(void *, int, int, int, int);
62 static void	om4_copycols(void *, int, int, int, int);
63 static void	om1_copyrows(void *, int, int, int num);
64 static void	om4_copyrows(void *, int, int, int num);
65 static void	om1_erasecols(void *, int, int, int, long);
66 static void	om4_erasecols(void *, int, int, int, long);
67 static void	om1_eraserows(void *, int, int, long);
68 static void	om4_eraserows(void *, int, int, long);
69 static int	om1_allocattr(void *, int, int, int, long *);
70 static int	om4_allocattr(void *, int, int, int, long *);
71 static void	om4_unpack_attr(long, int *, int *, int *);
72 
73 static int	omrasops_init(struct rasops_info *, int, int);
74 
75 #define	ALL1BITS	(~0U)
76 #define	ALL0BITS	(0U)
77 #define	BLITWIDTH	(32)
78 #define	ALIGNMASK	(0x1f)
79 #define	BYTESDONE	(4)
80 
81 /*
82  * macros to handle unaligned bit copy ops.
83  * See src/sys/dev/rasops/rasops_mask.h for MI version.
84  * Also refer src/sys/arch/hp300/dev/maskbits.h.
85  * (which was implemented for ancient src/sys/arch/hp300/dev/grf_hy.c)
86  */
87 
88 /* luna68k version GETBITS() that gets w bits from bit x at psrc memory */
89 #define	FASTGETBITS(psrc, x, w, dst)					\
90 	asm("bfextu %3{%1:%2},%0"					\
91 	    : "=d" (dst) 						\
92 	    : "di" (x), "di" (w), "o" (*(uint32_t *)(psrc)))
93 
94 /* luna68k version PUTBITS() that puts w bits from bit x at pdst memory */
95 /* XXX this macro assumes (x + w) <= 32 to handle unaligned residual bits */
96 #define	FASTPUTBITS(src, x, w, pdst)					\
97 	asm("bfins %3,%0{%1:%2}"					\
98 	    : "+o" (*(uint32_t *)(pdst))				\
99 	    : "di" (x), "di" (w), "d" (src)				\
100 	    : "memory" );
101 
102 #define	GETBITS(psrc, x, w, dst)	FASTGETBITS(psrc, x, w, dst)
103 #define	PUTBITS(src, x, w, pdst)	FASTPUTBITS(src, x, w, pdst)
104 
105 /*
106  * Blit a character at the specified co-ordinates.
107  */
108 static void
109 om1_putchar(void *cookie, int row, int startcol, u_int uc, long attr)
110 {
111 	struct rasops_info *ri = cookie;
112 	uint8_t *p;
113 	int scanspan, startx, height, width, align, y;
114 	uint32_t lmask, rmask, glyph, inverse;
115 	int i;
116 	uint8_t *fb;
117 
118 	scanspan = ri->ri_stride;
119 	y = ri->ri_font->fontheight * row;
120 	startx = ri->ri_font->fontwidth * startcol;
121 	height = ri->ri_font->fontheight;
122 	fb = (uint8_t *)ri->ri_font->data +
123 	    (uc - ri->ri_font->firstchar) * ri->ri_fontscale;
124 	inverse = ((attr & 0x00000001) != 0) ? ALL1BITS : ALL0BITS;
125 
126 	p = (uint8_t *)ri->ri_bits + y * scanspan + ((startx / 32) * 4);
127 	align = startx & ALIGNMASK;
128 	width = ri->ri_font->fontwidth + align;
129 	lmask = ALL1BITS >> align;
130 	rmask = ALL1BITS << (-width & ALIGNMASK);
131 	if (width <= BLITWIDTH) {
132 		lmask &= rmask;
133 		/* set lmask as ROP mask value, with THROUGH mode */
134 		((volatile uint32_t *)OMFB_ROPFUNC)[ROP_THROUGH] = lmask;
135 
136 		while (height > 0) {
137 			glyph = 0;
138 			for (i = ri->ri_font->stride; i != 0; i--)
139 				glyph = (glyph << 8) | *fb++;
140 			glyph <<= (4 - ri->ri_font->stride) * NBBY;
141 			glyph = (glyph >> align) ^ inverse;
142 
143 			*W(p) = glyph;
144 
145 			p += scanspan;
146 			height--;
147 		}
148 		/* reset mask value */
149 		((volatile uint32_t *)OMFB_ROPFUNC)[ROP_THROUGH] = ALL1BITS;
150 	} else {
151 		uint8_t *q = p;
152 		uint32_t lhalf, rhalf;
153 
154 		while (height > 0) {
155 			glyph = 0;
156 			for (i = ri->ri_font->stride; i != 0; i--)
157 				glyph = (glyph << 8) | *fb++;
158 			glyph <<= (4 - ri->ri_font->stride) * NBBY;
159 			lhalf = (glyph >> align) ^ inverse;
160 			/* set lmask as ROP mask value, with THROUGH mode */
161 			((volatile uint32_t *)OMFB_ROPFUNC)[ROP_THROUGH] =
162 			    lmask;
163 
164 			*W(p) = lhalf;
165 
166 			p += BYTESDONE;
167 
168 			rhalf = (glyph << (BLITWIDTH - align)) ^ inverse;
169 			/* set rmask as ROP mask value, with THROUGH mode */
170 			((volatile uint32_t *)OMFB_ROPFUNC)[ROP_THROUGH] =
171 			    rmask;
172 
173 			*W(p) = rhalf;
174 
175 			p = (q += scanspan);
176 			height--;
177 		}
178 		/* reset mask value */
179 		((volatile uint32_t *)OMFB_ROPFUNC)[ROP_THROUGH] = ALL1BITS;
180 	}
181 }
182 
183 static void
184 om4_putchar(void *cookie, int row, int startcol, u_int uc, long attr)
185 {
186 	struct rasops_info *ri = cookie;
187 	uint8_t *p;
188 	int scanspan, startx, height, width, align, y;
189 	uint32_t lmask, rmask, glyph, glyphbg, fgpat, bgpat;
190 	uint32_t fgmask0, fgmask1, fgmask2, fgmask3;
191 	uint32_t bgmask0, bgmask1, bgmask2, bgmask3;
192 	int i, fg, bg;
193 	uint8_t *fb;
194 
195 	scanspan = ri->ri_stride;
196 	y = ri->ri_font->fontheight * row;
197 	startx = ri->ri_font->fontwidth * startcol;
198 	height = ri->ri_font->fontheight;
199 	fb = (uint8_t *)ri->ri_font->data +
200 	    (uc - ri->ri_font->firstchar) * ri->ri_fontscale;
201 	om4_unpack_attr(attr, &fg, &bg, NULL);
202 	fgmask0 = (fg & 0x01) ? ALL1BITS : ALL0BITS;
203 	fgmask1 = (fg & 0x02) ? ALL1BITS : ALL0BITS;
204 	fgmask2 = (fg & 0x04) ? ALL1BITS : ALL0BITS;
205 	fgmask3 = (fg & 0x08) ? ALL1BITS : ALL0BITS;
206 	bgmask0 = (bg & 0x01) ? ALL1BITS : ALL0BITS;
207 	bgmask1 = (bg & 0x02) ? ALL1BITS : ALL0BITS;
208 	bgmask2 = (bg & 0x04) ? ALL1BITS : ALL0BITS;
209 	bgmask3 = (bg & 0x08) ? ALL1BITS : ALL0BITS;
210 
211 	p = (uint8_t *)ri->ri_bits + y * scanspan + ((startx / 32) * 4);
212 	align = startx & ALIGNMASK;
213 	width = ri->ri_font->fontwidth + align;
214 	lmask = ALL1BITS >> align;
215 	rmask = ALL1BITS << (-width & ALIGNMASK);
216 
217 	/* select all planes for later ROP function target */
218 	*(volatile uint32_t *)OMFB_PLANEMASK = 0xff;
219 
220 	if (width <= BLITWIDTH) {
221 		lmask &= rmask;
222 		/* set lmask as ROP mask value, with THROUGH mode */
223 		((volatile uint32_t *)OMFB_ROPFUNC)[ROP_THROUGH] = lmask;
224 
225 		while (height > 0) {
226 			glyph = 0;
227 			for (i = ri->ri_font->stride; i != 0; i--)
228 				glyph = (glyph << 8) | *fb++;
229 			glyph <<= (4 - ri->ri_font->stride) * NBBY;
230 			glyph = (glyph >> align);
231 			glyphbg = glyph ^ ALL1BITS;
232 
233 			fgpat = glyph   & fgmask0;
234 			bgpat = glyphbg & bgmask0;
235 			*P0(p) = (fgpat | bgpat);
236 			fgpat = glyph   & fgmask1;
237 			bgpat = glyphbg & bgmask1;
238 			*P1(p) = (fgpat | bgpat);
239 			fgpat = glyph   & fgmask2;
240 			bgpat = glyphbg & bgmask2;
241 			*P2(p) = (fgpat | bgpat);
242 			fgpat = glyph   & fgmask3;
243 			bgpat = glyphbg & bgmask3;
244 			*P3(p) = (fgpat | bgpat);
245 
246 			p += scanspan;
247 			height--;
248 		}
249 		/* reset mask value */
250 		((volatile uint32_t *)OMFB_ROPFUNC)[ROP_THROUGH] = ALL1BITS;
251 	} else {
252 		uint8_t *q = p;
253 		uint32_t lhalf, rhalf;
254 		uint32_t lhalfbg, rhalfbg;
255 
256 		while (height > 0) {
257 			glyph = 0;
258 			for (i = ri->ri_font->stride; i != 0; i--)
259 				glyph = (glyph << 8) | *fb++;
260 			glyph <<= (4 - ri->ri_font->stride) * NBBY;
261 			lhalf = (glyph >> align);
262 			lhalfbg = lhalf ^ ALL1BITS;
263 			/* set lmask as ROP mask value, with THROUGH mode */
264 			((volatile uint32_t *)OMFB_ROPFUNC)[ROP_THROUGH] =
265 			    lmask;
266 
267 			fgpat = lhalf   & fgmask0;
268 			bgpat = lhalfbg & bgmask0;
269 			*P0(p) = (fgpat | bgpat);
270 			fgpat = lhalf   & fgmask1;
271 			bgpat = lhalfbg & bgmask1;
272 			*P1(p) = (fgpat | bgpat);
273 			fgpat = lhalf   & fgmask2;
274 			bgpat = lhalfbg & bgmask2;
275 			*P2(p) = (fgpat | bgpat);
276 			fgpat = lhalf   & fgmask3;
277 			bgpat = lhalfbg & bgmask3;
278 			*P3(p) = (fgpat | bgpat);
279 
280 			p += BYTESDONE;
281 
282 			rhalf = (glyph << (BLITWIDTH - align));
283 			rhalfbg = rhalf ^ ALL1BITS;
284 			/* set rmask as ROP mask value, with THROUGH mode */
285 			((volatile uint32_t *)OMFB_ROPFUNC)[ROP_THROUGH] =
286 			    rmask;
287 
288 			fgpat = rhalf   & fgmask0;
289 			bgpat = rhalfbg & bgmask0;
290 			*P0(p) = (fgpat | bgpat);
291 			fgpat = rhalf   & fgmask1;
292 			bgpat = rhalfbg & bgmask1;
293 			*P1(p) = (fgpat | bgpat);
294 			fgpat = rhalf   & fgmask2;
295 			bgpat = rhalfbg & bgmask2;
296 			*P2(p) = (fgpat | bgpat);
297 			fgpat = rhalf   & fgmask3;
298 			bgpat = rhalfbg & bgmask3;
299 			*P3(p) = (fgpat | bgpat);
300 
301 			p = (q += scanspan);
302 			height--;
303 		}
304 		/* reset mask value */
305 		((volatile uint32_t *)OMFB_ROPFUNC)[ROP_THROUGH] = ALL1BITS;
306 	}
307 	/* select plane #0 only; XXX need this ? */
308 	*(volatile uint32_t *)OMFB_PLANEMASK = 0x01;
309 }
310 
311 static void
312 om1_erasecols(void *cookie, int row, int startcol, int ncols, long attr)
313 {
314 	struct rasops_info *ri = cookie;
315 	uint8_t *p;
316 	int scanspan, startx, height, width, align, w, y;
317 	uint32_t lmask, rmask, fill;
318 
319 	scanspan = ri->ri_stride;;
320 	y = ri->ri_font->fontheight * row;
321 	startx = ri->ri_font->fontwidth * startcol;
322 	height = ri->ri_font->fontheight;
323 	w = ri->ri_font->fontwidth * ncols;
324 	fill = ((attr & 0x00000001) != 0) ? ALL1BITS : ALL0BITS;
325 
326 	p = (uint8_t *)ri->ri_bits + y * scanspan + ((startx / 32) * 4);
327 	align = startx & ALIGNMASK;
328 	width = w + align;
329 	lmask = ALL1BITS >> align;
330 	rmask = ALL1BITS << (-width & ALIGNMASK);
331 	if (width <= BLITWIDTH) {
332 		lmask &= rmask;
333 		fill  &= lmask;
334 		while (height > 0) {
335 			*P0(p) = (*P0(p) & ~lmask) | fill;
336 			p += scanspan;
337 			height--;
338 		}
339 	} else {
340 		uint8_t *q = p;
341 		while (height > 0) {
342 			*P0(p) = (*P0(p) & ~lmask) | (fill & lmask);
343 			width -= 2 * BLITWIDTH;
344 			while (width > 0) {
345 				p += BYTESDONE;
346 				*P0(p) = fill;
347 				width -= BLITWIDTH;
348 			}
349 			p += BYTESDONE;
350 			*P0(p) = (fill & rmask) | (*P0(p) & ~rmask);
351 
352 			p = (q += scanspan);
353 			width = w + align;
354 			height--;
355 		}
356 	}
357 }
358 
359 static void
360 om4_erasecols(void *cookie, int row, int startcol, int ncols, long attr)
361 {
362 	struct rasops_info *ri = cookie;
363 	uint8_t *p;
364 	int scanspan, startx, height, width, align, w, y, fg, bg;
365 	uint32_t lmask, rmask, fill0, fill1, fill2, fill3;
366 
367 	scanspan = ri->ri_stride;;
368 	y = ri->ri_font->fontheight * row;
369 	startx = ri->ri_font->fontwidth * startcol;
370 	height = ri->ri_font->fontheight;
371 	w = ri->ri_font->fontwidth * ncols;
372 	om4_unpack_attr(attr, &fg, &bg, NULL);
373 	fill0 = ((bg & 0x01) != 0) ? ALL1BITS : ALL0BITS;
374 	fill1 = ((bg & 0x02) != 0) ? ALL1BITS : ALL0BITS;
375 	fill2 = ((bg & 0x04) != 0) ? ALL1BITS : ALL0BITS;
376 	fill3 = ((bg & 0x08) != 0) ? ALL1BITS : ALL0BITS;
377 
378 	p = (uint8_t *)ri->ri_bits + y * scanspan + ((startx / 32) * 4);
379 	align = startx & ALIGNMASK;
380 	width = w + align;
381 	lmask = ALL1BITS >> align;
382 	rmask = ALL1BITS << (-width & ALIGNMASK);
383 	if (width <= BLITWIDTH) {
384 		lmask &= rmask;
385 		fill0 &= lmask;
386 		fill1 &= lmask;
387 		fill2 &= lmask;
388 		fill3 &= lmask;
389 		while (height > 0) {
390 			*P0(p) = (*P0(p) & ~lmask) | fill0;
391 			*P1(p) = (*P1(p) & ~lmask) | fill1;
392 			*P2(p) = (*P2(p) & ~lmask) | fill2;
393 			*P3(p) = (*P3(p) & ~lmask) | fill3;
394 			p += scanspan;
395 			height--;
396 		}
397 	} else {
398 		uint8_t *q = p;
399 		while (height > 0) {
400 			*P0(p) = (*P0(p) & ~lmask) | (fill0 & lmask);
401 			*P1(p) = (*P1(p) & ~lmask) | (fill1 & lmask);
402 			*P2(p) = (*P2(p) & ~lmask) | (fill2 & lmask);
403 			*P3(p) = (*P3(p) & ~lmask) | (fill3 & lmask);
404 			width -= 2 * BLITWIDTH;
405 			while (width > 0) {
406 				p += BYTESDONE;
407 				*P0(p) = fill0;
408 				*P1(p) = fill1;
409 				*P2(p) = fill2;
410 				*P3(p) = fill3;
411 				width -= BLITWIDTH;
412 			}
413 			p += BYTESDONE;
414 			*P0(p) = (fill0 & rmask) | (*P0(p) & ~rmask);
415 			*P1(p) = (fill1 & rmask) | (*P1(p) & ~rmask);
416 			*P2(p) = (fill2 & rmask) | (*P2(p) & ~rmask);
417 			*P3(p) = (fill3 & rmask) | (*P3(p) & ~rmask);
418 
419 			p = (q += scanspan);
420 			width = w + align;
421 			height--;
422 		}
423 	}
424 }
425 
426 static void
427 om1_eraserows(void *cookie, int startrow, int nrows, long attr)
428 {
429 	struct rasops_info *ri = cookie;
430 	uint8_t *p, *q;
431 	int scanspan, starty, height, width, w;
432 	uint32_t rmask, fill;
433 
434 	scanspan = ri->ri_stride;
435 	starty = ri->ri_font->fontheight * startrow;
436 	height = ri->ri_font->fontheight * nrows;
437 	w = ri->ri_emuwidth;
438 	fill = ((attr & 0x00000001) != 0) ? ALL1BITS : ALL0BITS;
439 
440 	p = (uint8_t *)ri->ri_bits + starty * scanspan;
441 	width = w;
442 	rmask = ALL1BITS << (-width & ALIGNMASK);
443 	q = p;
444 	while (height > 0) {
445 		*P0(p) = fill;				/* always aligned */
446 		width -= 2 * BLITWIDTH;
447 		while (width > 0) {
448 			p += BYTESDONE;
449 			*P0(p) = fill;
450 			width -= BLITWIDTH;
451 		}
452 		p += BYTESDONE;
453 		*P0(p) = (fill & rmask) | (*P0(p) & ~rmask);
454 		p = (q += scanspan);
455 		width = w;
456 		height--;
457 	}
458 }
459 
460 static void
461 om4_eraserows(void *cookie, int startrow, int nrows, long attr)
462 {
463 	struct rasops_info *ri = cookie;
464 	uint8_t *p, *q;
465 	int scanspan, starty, height, width, w, fg, bg;
466 	uint32_t rmask, fill0, fill1, fill2, fill3;
467 
468 	scanspan = ri->ri_stride;
469 	starty = ri->ri_font->fontheight * startrow;
470 	height = ri->ri_font->fontheight * nrows;
471 	w = ri->ri_emuwidth;
472 	om4_unpack_attr(attr, &fg, &bg, NULL);
473 	fill0 = ((bg & 0x01) != 0) ? ALL1BITS : ALL0BITS;
474 	fill1 = ((bg & 0x02) != 0) ? ALL1BITS : ALL0BITS;
475 	fill2 = ((bg & 0x04) != 0) ? ALL1BITS : ALL0BITS;
476 	fill3 = ((bg & 0x08) != 0) ? ALL1BITS : ALL0BITS;
477 
478 	p = (uint8_t *)ri->ri_bits + starty * scanspan;
479 	width = w;
480 	rmask = ALL1BITS << (-width & ALIGNMASK);
481 	q = p;
482 	while (height > 0) {
483 		*P0(p) = fill0;				/* always aligned */
484 		*P1(p) = fill1;
485 		*P2(p) = fill2;
486 		*P3(p) = fill3;
487 		width -= 2 * BLITWIDTH;
488 		while (width > 0) {
489 			p += BYTESDONE;
490 			*P0(p) = fill0;
491 			*P1(p) = fill1;
492 			*P2(p) = fill2;
493 			*P3(p) = fill3;
494 			width -= BLITWIDTH;
495 		}
496 		p += BYTESDONE;
497 		*P0(p) = (fill0 & rmask) | (*P0(p) & ~rmask);
498 		*P1(p) = (fill1 & rmask) | (*P1(p) & ~rmask);
499 		*P2(p) = (fill2 & rmask) | (*P2(p) & ~rmask);
500 		*P3(p) = (fill3 & rmask) | (*P3(p) & ~rmask);
501 		p = (q += scanspan);
502 		width = w;
503 		height--;
504 	}
505 }
506 
507 static void
508 om1_copyrows(void *cookie, int srcrow, int dstrow, int nrows)
509 {
510 	struct rasops_info *ri = cookie;
511 	uint8_t *p, *q;
512 	int scanspan, offset, srcy, height, width, w;
513 	uint32_t rmask;
514 
515 	scanspan = ri->ri_stride;
516 	height = ri->ri_font->fontheight * nrows;
517 	offset = (dstrow - srcrow) * scanspan * ri->ri_font->fontheight;
518 	srcy = ri->ri_font->fontheight * srcrow;
519 	if (srcrow < dstrow && srcrow + nrows > dstrow) {
520 		scanspan = -scanspan;
521 		srcy = srcy + height - 1;
522 	}
523 
524 	p = (uint8_t *)ri->ri_bits + srcy * ri->ri_stride;
525 	w = ri->ri_emuwidth;
526 	width = w;
527 	rmask = ALL1BITS << (-width & ALIGNMASK);
528 	q = p;
529 	while (height > 0) {
530 		*P0(p + offset) = *P0(p);		/* always aligned */
531 		width -= 2 * BLITWIDTH;
532 		while (width > 0) {
533 			p += BYTESDONE;
534 			*P0(p + offset) = *P0(p);
535 			width -= BLITWIDTH;
536 		}
537 		p += BYTESDONE;
538 		*P0(p + offset) = (*P0(p) & rmask) | (*P0(p + offset) & ~rmask);
539 
540 		p = (q += scanspan);
541 		width = w;
542 		height--;
543 	}
544 }
545 
546 static void
547 om4_copyrows(void *cookie, int srcrow, int dstrow, int nrows)
548 {
549 	struct rasops_info *ri = cookie;
550 	uint8_t *p, *q;
551 	int scanspan, offset, srcy, height, width, w;
552 	uint32_t rmask;
553 
554 	scanspan = ri->ri_stride;
555 	height = ri->ri_font->fontheight * nrows;
556 	offset = (dstrow - srcrow) * scanspan * ri->ri_font->fontheight;
557 	srcy = ri->ri_font->fontheight * srcrow;
558 	if (srcrow < dstrow && srcrow + nrows > dstrow) {
559 		scanspan = -scanspan;
560 		srcy = srcy + height - 1;
561 	}
562 
563 	p = (uint8_t *)ri->ri_bits + srcy * ri->ri_stride;
564 	w = ri->ri_emuwidth;
565 	width = w;
566 	rmask = ALL1BITS << (-width & ALIGNMASK);
567 	q = p;
568 	while (height > 0) {
569 		*P0(p + offset) = *P0(p);		/* always aligned */
570 		*P1(p + offset) = *P1(p);
571 		*P2(p + offset) = *P2(p);
572 		*P3(p + offset) = *P3(p);
573 		width -= 2 * BLITWIDTH;
574 		while (width > 0) {
575 			p += BYTESDONE;
576 			*P0(p + offset) = *P0(p);
577 			*P1(p + offset) = *P1(p);
578 			*P2(p + offset) = *P2(p);
579 			*P3(p + offset) = *P3(p);
580 			width -= BLITWIDTH;
581 		}
582 		p += BYTESDONE;
583 		*P0(p + offset) = (*P0(p) & rmask) | (*P0(p + offset) & ~rmask);
584 		*P1(p + offset) = (*P1(p) & rmask) | (*P1(p + offset) & ~rmask);
585 		*P2(p + offset) = (*P2(p) & rmask) | (*P2(p + offset) & ~rmask);
586 		*P3(p + offset) = (*P3(p) & rmask) | (*P3(p + offset) & ~rmask);
587 
588 		p = (q += scanspan);
589 		width = w;
590 		height--;
591 	}
592 }
593 
594 static void
595 om1_copycols(void *cookie, int startrow, int srccol, int dstcol, int ncols)
596 {
597 	struct rasops_info *ri = cookie;
598 	uint8_t *sp, *dp, *sq, *dq, *basep;
599 	int scanspan, height, w, y, srcx, dstx;
600 	int sb, eb, db, sboff, full, cnt, lnum, rnum;
601 	uint32_t lmask, rmask, tmp;
602 	bool sbover;
603 
604 	scanspan = ri->ri_stride;
605 	y = ri->ri_font->fontheight * startrow;
606 	srcx = ri->ri_font->fontwidth * srccol;
607 	dstx = ri->ri_font->fontwidth * dstcol;
608 	height = ri->ri_font->fontheight;
609 	w = ri->ri_font->fontwidth * ncols;
610 	basep = (uint8_t *)ri->ri_bits + y * scanspan;
611 
612 	sb = srcx & ALIGNMASK;
613 	db = dstx & ALIGNMASK;
614 
615 	if (db + w <= BLITWIDTH) {
616 		/* Destination is contained within a single word */
617 		sp = basep + (srcx / 32) * 4;
618 		dp = basep + (dstx / 32) * 4;
619 
620 		while (height > 0) {
621 			GETBITS(P0(sp), sb, w, tmp);
622 			PUTBITS(tmp, db, w, P0(dp));
623 			dp += scanspan;
624 			sp += scanspan;
625 			height--;
626 		}
627 		return;
628 	}
629 
630 	lmask = (db == 0) ? 0 : ALL1BITS >> db;
631 	eb = (db + w) & ALIGNMASK;
632 	rmask = (eb == 0) ? 0 : ALL1BITS << (32 - eb);
633 	lnum = (32 - db) & ALIGNMASK;
634 	rnum = (dstx + w) & ALIGNMASK;
635 
636 	if (lmask != 0)
637 		full = (w - (32 - db)) / 32;
638 	else
639 		full = w / 32;
640 
641 	sbover = (sb + lnum) >= 32;
642 
643 	if (dstcol < srccol || srccol + ncols < dstcol) {
644 		/* copy forward (left-to-right) */
645 		sp = basep + (srcx / 32) * 4;
646 		dp = basep + (dstx / 32) * 4;
647 
648 		if (lmask != 0) {
649 			sboff = sb + lnum;
650 			if (sboff >= 32)
651 				sboff -= 32;
652 		} else
653 			sboff = sb;
654 
655 		sq = sp;
656 		dq = dp;
657 		while (height > 0) {
658 			if (lmask != 0) {
659 				GETBITS(P0(sp), sb, lnum, tmp);
660 				PUTBITS(tmp, db, lnum, P0(dp));
661 				dp += BYTESDONE;
662 				if (sbover)
663 					sp += BYTESDONE;
664 			}
665 
666 			for (cnt = full; cnt; cnt--) {
667 				GETBITS(P0(sp), sboff, 32, tmp);
668 				*P0(dp) = tmp;
669 				sp += BYTESDONE;
670 				dp += BYTESDONE;
671 			}
672 
673 			if (rmask != 0) {
674 				GETBITS(P0(sp), sboff, rnum, tmp);
675 				PUTBITS(tmp, 0, rnum, P0(dp));
676 			}
677 
678 			sp = (sq += scanspan);
679 			dp = (dq += scanspan);
680 			height--;
681 		}
682 	} else {
683 		/* copy backward (right-to-left) */
684 		sp = basep + ((srcx + w) / 32) * 4;
685 		dp = basep + ((dstx + w) / 32) * 4;
686 
687 		sboff = (srcx + w) & ALIGNMASK;
688 		sboff -= rnum;
689 		if (sboff < 0) {
690 			sp -= BYTESDONE;
691 			sboff += 32;
692 		}
693 
694 		sq = sp;
695 		dq = dp;
696 		while (height > 0) {
697 			if (rnum != 0) {
698 				GETBITS(P0(sp), sboff, rnum, tmp);
699 				PUTBITS(tmp, 0, rnum, P0(dp));
700 			}
701 
702 			for (cnt = full; cnt; cnt--) {
703 				sp -= BYTESDONE;
704 				dp -= BYTESDONE;
705 				GETBITS(P0(sp), sboff, 32, tmp);
706 				*P0(dp) = tmp;
707 			}
708 
709 			if (lmask != 0) {
710 				if (sbover)
711 					sp -= BYTESDONE;
712 				dp -= BYTESDONE;
713 				GETBITS(P0(sp), sb, lnum, tmp);
714 				PUTBITS(tmp, db, lnum, P0(dp));
715 			}
716 
717 			sp = (sq += scanspan);
718 			dp = (dq += scanspan);
719 			height--;
720 		}
721 	}
722 }
723 
724 static void
725 om4_copycols(void *cookie, int startrow, int srccol, int dstcol, int ncols)
726 {
727 	struct rasops_info *ri = cookie;
728 	uint8_t *sp, *dp, *sq, *dq, *basep;
729 	int scanspan, height, w, y, srcx, dstx;
730 	int sb, eb, db, sboff, full, cnt, lnum, rnum;
731 	uint32_t lmask, rmask, tmp;
732 	bool sbover;
733 
734 	scanspan = ri->ri_stride;
735 	y = ri->ri_font->fontheight * startrow;
736 	srcx = ri->ri_font->fontwidth * srccol;
737 	dstx = ri->ri_font->fontwidth * dstcol;
738 	height = ri->ri_font->fontheight;
739 	w = ri->ri_font->fontwidth * ncols;
740 	basep = (uint8_t *)ri->ri_bits + y * scanspan;
741 
742 	sb = srcx & ALIGNMASK;
743 	db = dstx & ALIGNMASK;
744 
745 	if (db + w <= BLITWIDTH) {
746 		/* Destination is contained within a single word */
747 		sp = basep + (srcx / 32) * 4;
748 		dp = basep + (dstx / 32) * 4;
749 
750 		while (height > 0) {
751 			GETBITS(P0(sp), sb, w, tmp);
752 			PUTBITS(tmp, db, w, P0(dp));
753 			GETBITS(P1(sp), sb, w, tmp);
754 			PUTBITS(tmp, db, w, P1(dp));
755 			GETBITS(P2(sp), sb, w, tmp);
756 			PUTBITS(tmp, db, w, P2(dp));
757 			GETBITS(P3(sp), sb, w, tmp);
758 			PUTBITS(tmp, db, w, P3(dp));
759 			dp += scanspan;
760 			sp += scanspan;
761 			height--;
762 		}
763 		return;
764 	}
765 
766 	lmask = (db == 0) ? 0 : ALL1BITS >> db;
767 	eb = (db + w) & ALIGNMASK;
768 	rmask = (eb == 0) ? 0 : ALL1BITS << (32 - eb);
769 	lnum = (32 - db) & ALIGNMASK;
770 	rnum = (dstx + w) & ALIGNMASK;
771 
772 	if (lmask != 0)
773 		full = (w - (32 - db)) / 32;
774 	else
775 		full = w / 32;
776 
777 	sbover = (sb + lnum) >= 32;
778 
779 	if (dstcol < srccol || srccol + ncols < dstcol) {
780 		/* copy forward (left-to-right) */
781 		sp = basep + (srcx / 32) * 4;
782 		dp = basep + (dstx / 32) * 4;
783 
784 		if (lmask != 0) {
785 			sboff = sb + lnum;
786 			if (sboff >= 32)
787 				sboff -= 32;
788 		} else
789 			sboff = sb;
790 
791 		sq = sp;
792 		dq = dp;
793 		while (height > 0) {
794 			if (lmask != 0) {
795 				GETBITS(P0(sp), sb, lnum, tmp);
796 				PUTBITS(tmp, db, lnum, P0(dp));
797 				GETBITS(P1(sp), sb, lnum, tmp);
798 				PUTBITS(tmp, db, lnum, P1(dp));
799 				GETBITS(P2(sp), sb, lnum, tmp);
800 				PUTBITS(tmp, db, lnum, P2(dp));
801 				GETBITS(P3(sp), sb, lnum, tmp);
802 				PUTBITS(tmp, db, lnum, P3(dp));
803 				dp += BYTESDONE;
804 				if (sbover)
805 					sp += BYTESDONE;
806 			}
807 
808 			for (cnt = full; cnt; cnt--) {
809 				GETBITS(P0(sp), sboff, 32, tmp);
810 				*P0(dp) = tmp;
811 				GETBITS(P1(sp), sboff, 32, tmp);
812 				*P1(dp) = tmp;
813 				GETBITS(P2(sp), sboff, 32, tmp);
814 				*P2(dp) = tmp;
815 				GETBITS(P3(sp), sboff, 32, tmp);
816 				*P3(dp) = tmp;
817 				sp += BYTESDONE;
818 				dp += BYTESDONE;
819 			}
820 
821 			if (rmask != 0) {
822 				GETBITS(P0(sp), sboff, rnum, tmp);
823 				PUTBITS(tmp, 0, rnum, P0(dp));
824 				GETBITS(P1(sp), sboff, rnum, tmp);
825 				PUTBITS(tmp, 0, rnum, P1(dp));
826 				GETBITS(P2(sp), sboff, rnum, tmp);
827 				PUTBITS(tmp, 0, rnum, P2(dp));
828 				GETBITS(P3(sp), sboff, rnum, tmp);
829 				PUTBITS(tmp, 0, rnum, P3(dp));
830 			}
831 
832 			sp = (sq += scanspan);
833 			dp = (dq += scanspan);
834 			height--;
835 		}
836 	} else {
837 		/* copy backward (right-to-left) */
838 		sp = basep + ((srcx + w) / 32) * 4;
839 		dp = basep + ((dstx + w) / 32) * 4;
840 
841 		sboff = (srcx + w) & ALIGNMASK;
842 		sboff -= rnum;
843 		if (sboff < 0) {
844 			sp -= BYTESDONE;
845 			sboff += 32;
846 		}
847 
848 		sq = sp;
849 		dq = dp;
850 		while (height > 0) {
851 			if (rnum != 0) {
852 				GETBITS(P0(sp), sboff, rnum, tmp);
853 				PUTBITS(tmp, 0, rnum, P0(dp));
854 				GETBITS(P1(sp), sboff, rnum, tmp);
855 				PUTBITS(tmp, 0, rnum, P1(dp));
856 				GETBITS(P2(sp), sboff, rnum, tmp);
857 				PUTBITS(tmp, 0, rnum, P2(dp));
858 				GETBITS(P3(sp), sboff, rnum, tmp);
859 				PUTBITS(tmp, 0, rnum, P3(dp));
860 			}
861 
862 			for (cnt = full; cnt; cnt--) {
863 				sp -= BYTESDONE;
864 				dp -= BYTESDONE;
865 				GETBITS(P0(sp), sboff, 32, tmp);
866 				*P0(dp) = tmp;
867 				GETBITS(P1(sp), sboff, 32, tmp);
868 				*P1(dp) = tmp;
869 				GETBITS(P2(sp), sboff, 32, tmp);
870 				*P2(dp) = tmp;
871 				GETBITS(P3(sp), sboff, 32, tmp);
872 				*P3(dp) = tmp;
873 			}
874 
875 			if (lmask != 0) {
876 				if (sbover)
877 					sp -= BYTESDONE;
878 				dp -= BYTESDONE;
879 				GETBITS(P0(sp), sb, lnum, tmp);
880 				PUTBITS(tmp, db, lnum, P0(dp));
881 				GETBITS(P1(sp), sb, lnum, tmp);
882 				PUTBITS(tmp, db, lnum, P1(dp));
883 				GETBITS(P2(sp), sb, lnum, tmp);
884 				PUTBITS(tmp, db, lnum, P2(dp));
885 				GETBITS(P3(sp), sb, lnum, tmp);
886 				PUTBITS(tmp, db, lnum, P3(dp));
887 			}
888 
889 			sp = (sq += scanspan);
890 			dp = (dq += scanspan);
891 			height--;
892 		}
893 	}
894 }
895 
896 /*
897  * Map a character.
898  */
899 static int
900 om_mapchar(void *cookie, int c, u_int *cp)
901 {
902 	struct rasops_info *ri = cookie;
903 	struct wsdisplay_font *wf = ri->ri_font;
904 
905 	if (wf->encoding != WSDISPLAY_FONTENC_ISO) {
906 		c = wsfont_map_unichar(wf, c);
907 
908 		if (c < 0)
909 			goto fail;
910 	}
911 	if (c < wf->firstchar || c >= (wf->firstchar + wf->numchars))
912 		goto fail;
913 
914 	*cp = c;
915 	return 5;
916 
917  fail:
918 	*cp = ' ';
919 	return 0;
920 }
921 
922 /*
923  * Position|{enable|disable} the cursor at the specified location.
924  */
925 static void
926 om1_cursor(void *cookie, int on, int row, int col)
927 {
928 	struct rasops_info *ri = cookie;
929 	uint8_t *p;
930 	int scanspan, startx, height, width, align, y;
931 	uint32_t lmask, rmask;
932 
933 	if (!on) {
934 		/* make sure it's on */
935 		if ((ri->ri_flg & RI_CURSOR) == 0)
936 			return;
937 
938 		row = ri->ri_crow;
939 		col = ri->ri_ccol;
940 	} else {
941 		/* unpaint the old copy. */
942 		ri->ri_crow = row;
943 		ri->ri_ccol = col;
944 	}
945 
946 	scanspan = ri->ri_stride;
947 	y = ri->ri_font->fontheight * row;
948 	startx = ri->ri_font->fontwidth * col;
949 	height = ri->ri_font->fontheight;
950 
951 	p = (uint8_t *)ri->ri_bits + y * scanspan + ((startx / 32) * 4);
952 	align = startx & ALIGNMASK;
953 	width = ri->ri_font->fontwidth + align;
954 	lmask = ALL1BITS >> align;
955 	rmask = ALL1BITS << (-width & ALIGNMASK);
956 	if (width <= BLITWIDTH) {
957 		lmask &= rmask;
958 		/* set lmask as ROP mask value, with INV2 mode */
959 		((volatile uint32_t *)OMFB_ROPFUNC)[ROP_INV2] = lmask;
960 
961 		while (height > 0) {
962 			*P0(p) = ALL1BITS;
963 			p += scanspan;
964 			height--;
965 		}
966 		/* reset mask value */
967 		((volatile uint32_t *)OMFB_ROPFUNC)[ROP_THROUGH] = ALL1BITS;
968 	} else {
969 		uint8_t *q = p;
970 
971 		while (height > 0) {
972 			/* set lmask as ROP mask value, with INV2 mode */
973 			((volatile uint32_t *)OMFB_ROPFUNC)[ROP_INV2] = lmask;
974 			*W(p) = ALL1BITS;
975 
976 			p += BYTESDONE;
977 
978 			/* set lmask as ROP mask value, with INV2 mode */
979 			((volatile uint32_t *)OMFB_ROPFUNC)[ROP_INV2] = rmask;
980 			*W(p) = ALL1BITS;
981 
982 			p = (q += scanspan);
983 			height--;
984 		}
985 		/* reset mask value */
986 		((volatile uint32_t *)OMFB_ROPFUNC)[ROP_THROUGH] = ALL1BITS;
987 	}
988 	ri->ri_flg ^= RI_CURSOR;
989 }
990 
991 static void
992 om4_cursor(void *cookie, int on, int row, int col)
993 {
994 	struct rasops_info *ri = cookie;
995 	uint8_t *p;
996 	int scanspan, startx, height, width, align, y;
997 	uint32_t lmask, rmask;
998 
999 	if (!on) {
1000 		/* make sure it's on */
1001 		if ((ri->ri_flg & RI_CURSOR) == 0)
1002 			return;
1003 
1004 		row = ri->ri_crow;
1005 		col = ri->ri_ccol;
1006 	} else {
1007 		/* unpaint the old copy. */
1008 		ri->ri_crow = row;
1009 		ri->ri_ccol = col;
1010 	}
1011 
1012 	scanspan = ri->ri_stride;
1013 	y = ri->ri_font->fontheight * row;
1014 	startx = ri->ri_font->fontwidth * col;
1015 	height = ri->ri_font->fontheight;
1016 
1017 	p = (uint8_t *)ri->ri_bits + y * scanspan + ((startx / 32) * 4);
1018 	align = startx & ALIGNMASK;
1019 	width = ri->ri_font->fontwidth + align;
1020 	lmask = ALL1BITS >> align;
1021 	rmask = ALL1BITS << (-width & ALIGNMASK);
1022 
1023 	/* select all planes for later ROP function target */
1024 	*(volatile uint32_t *)OMFB_PLANEMASK = 0xff;
1025 
1026 	if (width <= BLITWIDTH) {
1027 		lmask &= rmask;
1028 		/* set lmask as ROP mask value, with INV2 mode */
1029 		((volatile uint32_t *)OMFB_ROPFUNC)[ROP_INV2] = lmask;
1030 
1031 		while (height > 0) {
1032 			*W(p) = ALL1BITS;
1033 			p += scanspan;
1034 			height--;
1035 		}
1036 		/* reset mask value */
1037 		((volatile uint32_t *)OMFB_ROPFUNC)[ROP_THROUGH] = ALL1BITS;
1038 	} else {
1039 		uint8_t *q = p;
1040 
1041 		while (height > 0) {
1042 			/* set lmask as ROP mask value, with INV2 mode */
1043 			((volatile uint32_t *)OMFB_ROPFUNC)[ROP_INV2] = lmask;
1044 			*W(p) = ALL1BITS;
1045 
1046 			p += BYTESDONE;
1047 
1048 			/* set rmask as ROP mask value, with INV2 mode */
1049 			((volatile uint32_t *)OMFB_ROPFUNC)[ROP_INV2] = rmask;
1050 			*W(p) = ALL1BITS;
1051 
1052 			p = (q += scanspan);
1053 			height--;
1054 		}
1055 		/* reset mask value */
1056 		((volatile uint32_t *)OMFB_ROPFUNC)[ROP_THROUGH] = ALL1BITS;
1057 	}
1058 	/* select plane #0 only; XXX need this ? */
1059 	*(volatile uint32_t *)OMFB_PLANEMASK = 0x01;
1060 
1061 	ri->ri_flg ^= RI_CURSOR;
1062 }
1063 
1064 /*
1065  * Allocate attribute. We just pack these into an integer.
1066  */
1067 static int
1068 om1_allocattr(void *id, int fg, int bg, int flags, long *attrp)
1069 {
1070 
1071 	if ((flags & (WSATTR_HILIT | WSATTR_BLINK |
1072 	    WSATTR_UNDERLINE | WSATTR_WSCOLORS)) != 0)
1073 		return EINVAL;
1074 	if ((flags & WSATTR_REVERSE) != 0)
1075 		*attrp = 1;
1076 	else
1077 		*attrp = 0;
1078 	return 0;
1079 }
1080 
1081 static int
1082 om4_allocattr(void *id, int fg, int bg, int flags, long *attrp)
1083 {
1084 
1085 	if ((flags & (WSATTR_BLINK | WSATTR_UNDERLINE)) != 0)
1086 		return EINVAL;
1087 	if ((flags & WSATTR_WSCOLORS) == 0) {
1088 		fg = WSCOL_WHITE;
1089 		bg = WSCOL_BLACK;
1090 	}
1091 
1092 	if ((flags & WSATTR_REVERSE) != 0) {
1093 		int swap;
1094 		swap = fg;
1095 		fg = bg;
1096 		bg = swap;
1097 	}
1098 
1099 	if ((flags & WSATTR_HILIT) != 0)
1100 		fg += 8;
1101 
1102 	*attrp = (fg << 24) | (bg << 16);
1103 	return 0;
1104 }
1105 
1106 static void
1107 om4_unpack_attr(long attr, int *fg, int *bg, int *underline)
1108 {
1109 
1110 	*fg = ((u_int)attr >> 24) & 0xf;
1111 	*bg = ((u_int)attr >> 16) & 0xf;
1112 }
1113 
1114 /*
1115  * Init subset of rasops(9) for omrasops.
1116  */
1117 int
1118 omrasops1_init(struct rasops_info *ri, int wantrows, int wantcols)
1119 {
1120 
1121 	omrasops_init(ri, wantrows, wantcols);
1122 
1123 	/* fill our own emulops */
1124 	ri->ri_ops.cursor    = om1_cursor;
1125 	ri->ri_ops.mapchar   = om_mapchar;
1126 	ri->ri_ops.putchar   = om1_putchar;
1127 	ri->ri_ops.copycols  = om1_copycols;
1128 	ri->ri_ops.erasecols = om1_erasecols;
1129 	ri->ri_ops.copyrows  = om1_copyrows;
1130 	ri->ri_ops.eraserows = om1_eraserows;
1131 	ri->ri_ops.allocattr = om1_allocattr;
1132 	ri->ri_caps = WSSCREEN_REVERSE;
1133 
1134 	ri->ri_flg |= RI_CFGDONE;
1135 
1136 	return 0;
1137 }
1138 
1139 int
1140 omrasops4_init(struct rasops_info *ri, int wantrows, int wantcols)
1141 {
1142 
1143 	omrasops_init(ri, wantrows, wantcols);
1144 
1145 	/* fill our own emulops */
1146 	ri->ri_ops.cursor    = om4_cursor;
1147 	ri->ri_ops.mapchar   = om_mapchar;
1148 	ri->ri_ops.putchar   = om4_putchar;
1149 	ri->ri_ops.copycols  = om4_copycols;
1150 	ri->ri_ops.erasecols = om4_erasecols;
1151 	ri->ri_ops.copyrows  = om4_copyrows;
1152 	ri->ri_ops.eraserows = om4_eraserows;
1153 	ri->ri_ops.allocattr = om4_allocattr;
1154 	ri->ri_caps = WSSCREEN_HILIT | WSSCREEN_WSCOLORS | WSSCREEN_REVERSE;
1155 
1156 	ri->ri_flg |= RI_CFGDONE;
1157 
1158 	return 0;
1159 }
1160 
1161 static int
1162 omrasops_init(struct rasops_info *ri, int wantrows, int wantcols)
1163 {
1164 	int wsfcookie, bpp;
1165 
1166 	if (wantrows == 0)
1167 		wantrows = 34;
1168 	if (wantrows < 10)
1169 		wantrows = 10;
1170 	if (wantcols == 0)
1171 		wantcols = 80;
1172 	if (wantcols < 20)
1173 		wantcols = 20;
1174 
1175 	/* Use default font */
1176 	wsfont_init();
1177 	wsfcookie = wsfont_find(NULL, 0, 0, 0, WSDISPLAY_FONTORDER_L2R,
1178 	    WSDISPLAY_FONTORDER_L2R, WSFONT_FIND_BITMAP);
1179 	if (wsfcookie < 0)
1180 		panic("%s: no font available", __func__);
1181 	if (wsfont_lock(wsfcookie, &ri->ri_font))
1182 		panic("%s: unable to lock font", __func__);
1183 	ri->ri_wsfcookie = wsfcookie;
1184 
1185 	KASSERT(ri->ri_font->fontwidth > 4 && ri->ri_font->fontwidth <= 32);
1186 
1187 	/* all planes are independently addressed */
1188 	bpp = 1;
1189 
1190 	/* Now constrain what they get */
1191 	ri->ri_emuwidth = ri->ri_font->fontwidth * wantcols;
1192 	ri->ri_emuheight = ri->ri_font->fontheight * wantrows;
1193 	if (ri->ri_emuwidth > ri->ri_width)
1194 		ri->ri_emuwidth = ri->ri_width;
1195 	if (ri->ri_emuheight > ri->ri_height)
1196 		ri->ri_emuheight = ri->ri_height;
1197 
1198 	/* Reduce width until aligned on a 32-bit boundary */
1199 	while ((ri->ri_emuwidth * bpp & 31) != 0)
1200 		ri->ri_emuwidth--;
1201 
1202 	ri->ri_cols = ri->ri_emuwidth / ri->ri_font->fontwidth;
1203 	ri->ri_rows = ri->ri_emuheight / ri->ri_font->fontheight;
1204 	ri->ri_emustride = ri->ri_emuwidth * bpp >> 3;
1205 	ri->ri_delta = ri->ri_stride - ri->ri_emustride;
1206 	ri->ri_ccol = 0;
1207 	ri->ri_crow = 0;
1208 	ri->ri_pelbytes = bpp >> 3;
1209 
1210 	ri->ri_xscale = (ri->ri_font->fontwidth * bpp) >> 3;
1211 	ri->ri_yscale = ri->ri_font->fontheight * ri->ri_stride;
1212 	ri->ri_fontscale = ri->ri_font->fontheight * ri->ri_font->stride;
1213 
1214 	/* Clear the entire display */
1215 	if ((ri->ri_flg & RI_CLEAR) != 0)
1216 		memset(ri->ri_bits, 0, ri->ri_stride * ri->ri_height);
1217 
1218 	/* Now centre our window if needs be */
1219 	ri->ri_origbits = ri->ri_bits;
1220 
1221 	if ((ri->ri_flg & RI_CENTER) != 0) {
1222 		ri->ri_bits += (((ri->ri_width * bpp >> 3) -
1223 		    ri->ri_emustride) >> 1) & ~3;
1224 		ri->ri_bits += ((ri->ri_height - ri->ri_emuheight) >> 1) *
1225 		    ri->ri_stride;
1226 		ri->ri_yorigin = (int)(ri->ri_bits - ri->ri_origbits)
1227 		   / ri->ri_stride;
1228 		ri->ri_xorigin = (((int)(ri->ri_bits - ri->ri_origbits)
1229 		   % ri->ri_stride) * 8 / bpp);
1230 	} else
1231 		ri->ri_xorigin = ri->ri_yorigin = 0;
1232 
1233 	return 0;
1234 }
1235