xref: /netbsd-src/sys/arch/luna68k/dev/omrasops.c (revision 7788a0781fe6ff2cce37368b4578a7ade0850cb1)
1 /* $NetBSD: omrasops.c,v 1.13 2012/07/20 19:31:53 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.13 2012/07/20 19:31:53 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  *	- every memory references is done in aligned 32bit chunk,
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	om_cursor(void *, int, int, int);
57 static int	om_mapchar(void *, int, unsigned int *);
58 static void	om_putchar(void *, int, int, u_int, long);
59 static void	om_copycols(void *, int, int, int, int);
60 static void	om_copyrows(void *, int, int, int num);
61 static void	om_erasecols(void *, int, int, int, long);
62 static void	om_eraserows(void *, int, int, long);
63 static int	om_allocattr(void *, int, int, int, long *);
64 
65 #define	ALL1BITS	(~0U)
66 #define	ALL0BITS	(0U)
67 #define	BLITWIDTH	(32)
68 #define	ALIGNMASK	(0x1f)
69 #define	BYTESDONE	(4)
70 
71 #define	W(p) (*(uint32_t *)(p))
72 #define	R(p) (*(uint32_t *)((uint8_t *)(p) + 0x40000))
73 
74 /*
75  * Blit a character at the specified co-ordinates.
76  */
77 static void
78 om_putchar(void *cookie, int row, int startcol, u_int uc, long attr)
79 {
80 	struct rasops_info *ri = cookie;
81 	uint8_t *p;
82 	int scanspan, startx, height, width, align, y;
83 	uint32_t lmask, rmask, glyph, inverse;
84 	int i;
85 	uint8_t *fb;
86 
87 	scanspan = ri->ri_stride;
88 	y = ri->ri_font->fontheight * row;
89 	startx = ri->ri_font->fontwidth * startcol;
90 	height = ri->ri_font->fontheight;
91 	fb = (uint8_t *)ri->ri_font->data +
92 	    (uc - ri->ri_font->firstchar) * ri->ri_fontscale;
93 	inverse = (attr != 0) ? ALL1BITS : ALL0BITS;
94 
95 	p = (uint8_t *)ri->ri_bits + y * scanspan + ((startx / 32) * 4);
96 	align = startx & ALIGNMASK;
97 	width = ri->ri_font->fontwidth + align;
98 	lmask = ALL1BITS >> align;
99 	rmask = ALL1BITS << (-width & ALIGNMASK);
100 	if (width <= BLITWIDTH) {
101 		lmask &= rmask;
102 		while (height > 0) {
103 			glyph = 0;
104 			for (i = ri->ri_font->stride; i != 0; i--)
105 				glyph = (glyph << 8) | *fb++;
106 			glyph <<= (4 - ri->ri_font->stride) * NBBY;
107 			glyph = (glyph >> align) ^ inverse;
108 			W(p) = (R(p) & ~lmask) | (glyph & lmask);
109 			p += scanspan;
110 			height--;
111 		}
112 	} else {
113 		uint8_t *q = p;
114 		uint32_t lhalf, rhalf;
115 
116 		while (height > 0) {
117 			glyph = 0;
118 			for (i = ri->ri_font->stride; i != 0; i--)
119 				glyph = (glyph << 8) | *fb++;
120 			glyph <<= (4 - ri->ri_font->stride) * NBBY;
121 			lhalf = (glyph >> align) ^ inverse;
122 			W(p) = (R(p) & ~lmask) | (lhalf & lmask);
123 			p += BYTESDONE;
124 			rhalf = (glyph << (BLITWIDTH - align)) ^ inverse;
125 			W(p) = (rhalf & rmask) | (R(p) & ~rmask);
126 
127 			p = (q += scanspan);
128 			height--;
129 		}
130 	}
131 }
132 
133 static void
134 om_erasecols(void *cookie, int row, int startcol, int ncols, long attr)
135 {
136 	struct rasops_info *ri = cookie;
137 	uint8_t *p;
138 	int scanspan, startx, height, width, align, w, y;
139 	uint32_t lmask, rmask, fill;
140 
141 	scanspan = ri->ri_stride;;
142 	fill = (attr != 0) ? ALL1BITS : ALL0BITS;
143 	y = ri->ri_font->fontheight * row;
144 	startx = ri->ri_font->fontwidth * startcol;
145 	height = ri->ri_font->fontheight;
146 	w = ri->ri_font->fontwidth * ncols;
147 	fill = (attr != 0) ? ALL1BITS : ALL0BITS;
148 
149 	p = (uint8_t *)ri->ri_bits + y * scanspan + ((startx / 32) * 4);
150 	align = startx & ALIGNMASK;
151 	width = w + align;
152 	lmask = ALL1BITS >> align;
153 	rmask = ALL1BITS << (-width & ALIGNMASK);
154 	if (width <= BLITWIDTH) {
155 		lmask &= rmask;
156 		fill &= lmask;
157 		while (height > 0) {
158 			W(p) = (R(p) & ~lmask) | fill;
159 			p += scanspan;
160 			height--;
161 		}
162 	} else {
163 		uint8_t *q = p;
164 		while (height > 0) {
165 			W(p) = (R(p) & ~lmask) | (fill & lmask);
166 			width -= 2 * BLITWIDTH;
167 			while (width > 0) {
168 				p += BYTESDONE;
169 				W(p) = fill;
170 				width -= BLITWIDTH;
171 			}
172 			p += BYTESDONE;
173 			W(p) = (fill & rmask) | (R(p) & ~rmask);
174 
175 			p = (q += scanspan);
176 			width = w + align;
177 			height--;
178 		}
179 	}
180 }
181 
182 static void
183 om_eraserows(void *cookie, int startrow, int nrows, long attr)
184 {
185 	struct rasops_info *ri = cookie;
186 	uint8_t *p, *q;
187 	int scanspan, starty, height, width, w;
188 	uint32_t rmask, fill;
189 
190 	scanspan = ri->ri_stride;
191 	starty = ri->ri_font->fontheight * startrow;
192 	height = ri->ri_font->fontheight * nrows;
193 	w = ri->ri_emuwidth;
194 	fill = (attr != 0) ? ALL1BITS : ALL0BITS;
195 
196 	p = (uint8_t *)ri->ri_bits + starty * scanspan;
197 	width = w;
198 	rmask = ALL1BITS << (-width & ALIGNMASK);
199 	q = p;
200 	while (height > 0) {
201 		W(p) = fill;				/* always aligned */
202 		width -= 2 * BLITWIDTH;
203 		while (width > 0) {
204 			p += BYTESDONE;
205 			W(p) = fill;
206 			width -= BLITWIDTH;
207 		}
208 		p += BYTESDONE;
209 		W(p) = (fill & rmask) | (R(p) & ~rmask);
210 		p = (q += scanspan);
211 		width = w;
212 		height--;
213 	}
214 }
215 
216 static void
217 om_copyrows(void *cookie, int srcrow, int dstrow, int nrows)
218 {
219 	struct rasops_info *ri = cookie;
220 	uint8_t *p, *q;
221 	int scanspan, offset, srcy, height, width, w;
222 	uint32_t rmask;
223 
224 	scanspan = ri->ri_stride;
225 	height = ri->ri_font->fontheight * nrows;
226 	offset = (dstrow - srcrow) * scanspan * ri->ri_font->fontheight;
227 	srcy = ri->ri_font->fontheight * srcrow;
228 	if (srcrow < dstrow && srcrow + nrows > dstrow) {
229 		scanspan = -scanspan;
230 		srcy += height;
231 	}
232 
233 	p = (uint8_t *)ri->ri_bits + srcy * ri->ri_stride;
234 	w = ri->ri_emuwidth;
235 	width = w;
236 	rmask = ALL1BITS << (-width & ALIGNMASK);
237 	q = p;
238 	while (height > 0) {
239 		W(p + offset) = R(p);			/* always aligned */
240 		width -= 2 * BLITWIDTH;
241 		while (width > 0) {
242 			p += BYTESDONE;
243 			W(p + offset) = R(p);
244 			width -= BLITWIDTH;
245 		}
246 		p += BYTESDONE;
247 		W(p + offset) = (R(p) & rmask) | (R(p + offset) & ~rmask);
248 
249 		p = (q += scanspan);
250 		width = w;
251 		height--;
252 	}
253 }
254 
255 static void
256 om_copycols(void *cookie, int startrow, int srccol, int dstcol, int ncols)
257 {
258 	struct rasops_info *ri = cookie;
259 	uint8_t *sp, *dp, *basep;
260 	int scanspan, height, width, align, shift, w, y, srcx, dstx;
261 	uint32_t lmask, rmask;
262 
263 	scanspan = ri->ri_stride;
264 	y = ri->ri_font->fontheight * startrow;
265 	srcx = ri->ri_font->fontwidth * srccol;
266 	dstx = ri->ri_font->fontwidth * dstcol;
267 	height = ri->ri_font->fontheight;
268 	w = ri->ri_font->fontwidth * ncols;
269 	basep = (uint8_t *)ri->ri_bits + y * scanspan;
270 
271 	align = shift = srcx & ALIGNMASK;
272 	width = w + align;
273 	align = dstx & ALIGNMASK;
274 	lmask = ALL1BITS >> align;
275 	rmask = ALL1BITS << (-(w + align) & ALIGNMASK);
276 	shift = align - shift;
277 	sp = basep + (srcx / 32) * 4;
278 	dp = basep + (dstx / 32) * 4;
279 
280 	if (shift != 0)
281 		goto hardluckalignment;
282 
283 	/* alignments comfortably match */
284 	if (width <= BLITWIDTH) {
285 		lmask &= rmask;
286 		while (height > 0) {
287 			W(dp) = (R(dp) & ~lmask) | (R(sp) & lmask);
288 			dp += scanspan;
289 			sp += scanspan;
290 			height--;
291 		}
292 	}
293 	/* copy forward (left-to-right) */
294 	else if (dstcol < srccol || srccol + ncols < dstcol) {
295 		uint8_t *sq = sp, *dq = dp;
296 
297 		w = width;
298 		while (height > 0) {
299 			W(dp) = (R(dp) & ~lmask) | (R(sp) & lmask);
300 			width -= 2 * BLITWIDTH;
301 			while (width > 0) {
302 				sp += BYTESDONE;
303 				dp += BYTESDONE;
304 				W(dp) = R(sp);
305 				width -= BLITWIDTH;
306 			}
307 			sp += BYTESDONE;
308 			dp += BYTESDONE;
309 			W(dp) = (R(sp) & rmask) | (R(dp) & ~rmask);
310 			sp = (sq += scanspan);
311 			dp = (dq += scanspan);
312 			width = w;
313 			height--;
314 		}
315 	}
316 	/* copy backward (right-to-left) */
317 	else {
318 		uint8_t *sq, *dq;
319 
320 		sq = (sp += width / 32 * 4);
321 		dq = (dp += width / 32 * 4);
322 		w = width;
323 		while (height > 0) {
324 			W(dp) = (R(sp) & rmask) | (R(dp) & ~rmask);
325 			width -= 2 * BLITWIDTH;
326 			while (width > 0) {
327 				sp -= BYTESDONE;
328 				dp -= BYTESDONE;
329 				W(dp) = R(sp);
330 				width -= BLITWIDTH;
331 			}
332 			sp -= BYTESDONE;
333 			dp -= BYTESDONE;
334 			W(dp) = (R(dp) & ~lmask) | (R(sp) & lmask);
335 
336 			sp = (sq += scanspan);
337 			dp = (dq += scanspan);
338 			width = w;
339 			height--;
340 		}
341 	}
342 	return;
343 
344     hardluckalignment:
345 	/* alignments painfully disagree */
346 	return;
347 }
348 
349 /*
350  * Map a character.
351  */
352 static int
353 om_mapchar(void *cookie, int c, u_int *cp)
354 {
355 	struct rasops_info *ri = cookie;
356 	struct wsdisplay_font *wf = ri->ri_font;
357 
358 	if (wf->encoding != WSDISPLAY_FONTENC_ISO) {
359 		c = wsfont_map_unichar(wf, c);
360 
361 		if (c < 0)
362 			goto fail;
363 	}
364 	if (c < wf->firstchar || c >= (wf->firstchar + wf->numchars))
365 		goto fail;
366 
367 	*cp = c;
368 	return 5;
369 
370  fail:
371 	*cp = ' ';
372 	return 0;
373 }
374 
375 /*
376  * Position|{enable|disable} the cursor at the specified location.
377  */
378 static void
379 om_cursor(void *cookie, int on, int row, int col)
380 {
381 	struct rasops_info *ri = cookie;
382 	uint8_t *p;
383 	int scanspan, startx, height, width, align, y;
384 	uint32_t lmask, rmask, image;
385 
386 	if (!on) {
387 		/* make sure it's on */
388 		if ((ri->ri_flg & RI_CURSOR) == 0)
389 			return;
390 
391 		row = ri->ri_crow;
392 		col = ri->ri_ccol;
393 	} else {
394 		/* unpaint the old copy. */
395 		ri->ri_crow = row;
396 		ri->ri_ccol = col;
397 	}
398 
399 	scanspan = ri->ri_stride;
400 	y = ri->ri_font->fontheight * row;
401 	startx = ri->ri_font->fontwidth * col;
402 	height = ri->ri_font->fontheight;
403 
404 	p = (uint8_t *)ri->ri_bits + y * scanspan + ((startx / 32) * 4);
405 	align = startx & ALIGNMASK;
406 	width = ri->ri_font->fontwidth + align;
407 	lmask = ALL1BITS >> align;
408 	rmask = ALL1BITS << (-width & ALIGNMASK);
409 	if (width <= BLITWIDTH) {
410 		lmask &= rmask;
411 		while (height > 0) {
412 			image = R(p);
413 			W(p) = (image & ~lmask) | ((image ^ ALL1BITS) & lmask);
414 			p += scanspan;
415 			height--;
416 		}
417 	} else {
418 		uint8_t *q = p;
419 
420 		while (height > 0) {
421 			image = R(p);
422 			W(p) = (image & ~lmask) | ((image ^ ALL1BITS) & lmask);
423 			p += BYTESDONE;
424 			image = R(p);
425 			W(p) = ((image ^ ALL1BITS) & rmask) | (image & ~rmask);
426 
427 			p = (q += scanspan);
428 			height--;
429 		}
430 	}
431 	ri->ri_flg ^= RI_CURSOR;
432 }
433 
434 /*
435  * Allocate attribute. We just pack these into an integer.
436  */
437 static int
438 om_allocattr(void *id, int fg, int bg, int flags, long *attrp)
439 {
440 
441 	if (flags & (WSATTR_HILIT | WSATTR_BLINK |
442 	    WSATTR_UNDERLINE | WSATTR_WSCOLORS))
443 		return EINVAL;
444 	if (flags & WSATTR_REVERSE)
445 		*attrp = 1;
446 	else
447 		*attrp = 0;
448 	return 0;
449 }
450 
451 /*
452  * Init subset of rasops(9) for omrasops.
453  */
454 int
455 omrasops_init(struct rasops_info *ri, int wantrows, int wantcols)
456 {
457 	int wsfcookie, bpp;
458 
459 	if (wantrows == 0)
460 		wantrows = 34;
461 	if (wantrows < 10)
462 		wantrows = 10;
463 	if (wantcols == 0)
464 		wantcols = 80;
465 	if (wantcols < 20)
466 		wantcols = 20;
467 
468 	/* Use default font */
469 	wsfont_init();
470 	wsfcookie = wsfont_find(NULL, 0, 0, 0, WSDISPLAY_FONTORDER_L2R,
471 	    WSDISPLAY_FONTORDER_L2R, WSFONT_FIND_BITMAP);
472 	if (wsfcookie < 0)
473 		panic("%s: no font available", __func__);
474 	if (wsfont_lock(wsfcookie, &ri->ri_font))
475 		panic("%s: unable to lock font", __func__);
476 	ri->ri_wsfcookie = wsfcookie;
477 
478 	KASSERT(ri->ri_font->fontwidth > 4 && ri->ri_font->fontwidth <= 32);
479 
480 	bpp = ri->ri_depth;
481 
482 	/* Now constrain what they get */
483 	ri->ri_emuwidth = ri->ri_font->fontwidth * wantcols;
484 	ri->ri_emuheight = ri->ri_font->fontheight * wantrows;
485 	if (ri->ri_emuwidth > ri->ri_width)
486 		ri->ri_emuwidth = ri->ri_width;
487 	if (ri->ri_emuheight > ri->ri_height)
488 		ri->ri_emuheight = ri->ri_height;
489 
490 	/* Reduce width until aligned on a 32-bit boundary */
491 	while ((ri->ri_emuwidth * bpp & 31) != 0)
492 		ri->ri_emuwidth--;
493 
494 	ri->ri_cols = ri->ri_emuwidth / ri->ri_font->fontwidth;
495 	ri->ri_rows = ri->ri_emuheight / ri->ri_font->fontheight;
496 	ri->ri_emustride = ri->ri_emuwidth * bpp >> 3;
497 	ri->ri_delta = ri->ri_stride - ri->ri_emustride;
498 	ri->ri_ccol = 0;
499 	ri->ri_crow = 0;
500 	ri->ri_pelbytes = bpp >> 3;
501 
502 	ri->ri_xscale = (ri->ri_font->fontwidth * bpp) >> 3;
503 	ri->ri_yscale = ri->ri_font->fontheight * ri->ri_stride;
504 	ri->ri_fontscale = ri->ri_font->fontheight * ri->ri_font->stride;
505 
506 	/* Clear the entire display */
507 	if ((ri->ri_flg & RI_CLEAR) != 0)
508 		memset(ri->ri_bits, 0, ri->ri_stride * ri->ri_height);
509 
510 	/* Now centre our window if needs be */
511 	ri->ri_origbits = ri->ri_bits;
512 
513 	if ((ri->ri_flg & RI_CENTER) != 0) {
514 		ri->ri_bits += (((ri->ri_width * bpp >> 3) -
515 		    ri->ri_emustride) >> 1) & ~3;
516 		ri->ri_bits += ((ri->ri_height - ri->ri_emuheight) >> 1) *
517 		    ri->ri_stride;
518 		ri->ri_yorigin = (int)(ri->ri_bits - ri->ri_origbits)
519 		   / ri->ri_stride;
520 		ri->ri_xorigin = (((int)(ri->ri_bits - ri->ri_origbits)
521 		   % ri->ri_stride) * 8 / bpp);
522 	} else
523 		ri->ri_xorigin = ri->ri_yorigin = 0;
524 
525 	/* fill our own emulops */
526 	ri->ri_ops.cursor    = om_cursor;
527 	ri->ri_ops.mapchar   = om_mapchar;
528 	ri->ri_ops.putchar   = om_putchar;
529 	ri->ri_ops.copycols  = om_copycols;
530 	ri->ri_ops.erasecols = om_erasecols;
531 	ri->ri_ops.copyrows  = om_copyrows;
532 	ri->ri_ops.eraserows = om_eraserows;
533 	ri->ri_ops.allocattr = om_allocattr;
534 	ri->ri_caps = WSSCREEN_REVERSE;
535 
536 	ri->ri_flg |= RI_CFGDONE;
537 
538 	return 0;
539 }
540