xref: /netbsd/sys/arch/luna68k/dev/omrasops.c (revision bf9ec67e)
1 /* $NetBSD: omrasops.c,v 1.1 2000/01/05 08:48:56 nisimura 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  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *	This product includes software developed by the NetBSD
21  *	Foundation, Inc. and its contributors.
22  * 4. Neither the name of The NetBSD Foundation nor the names of its
23  *    contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  */
38 
39 #include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
40 
41 __KERNEL_RCSID(0, "$NetBSD: omrasops.c,v 1.1 2000/01/05 08:48:56 nisimura Exp $");
42 
43 /*
44  * Designed speficically for 'm68k bitorder';
45  *	- most significant byte is stored at lower address,
46  *	- most significant bit is displayed at left most on screen.
47  * Implementation relys on;
48  *	- every memory references is done in aligned 32bit chunk,
49  *	- font glyphs are stored in 32bit padded.
50  */
51 
52 #include <sys/param.h>
53 #include <sys/systm.h>
54 #include <sys/device.h>
55 
56 #include <dev/rcons/raster.h>
57 #include <dev/wscons/wscons_raster.h>
58 #include <dev/wscons/wscons_rfont.h>
59 #include <dev/wscons/wsdisplayvar.h>
60 
61 void rcons_init __P((struct rcons *, int, int));
62 
63 /* wscons emulator operations */
64 static void	om_cursor __P((void *, int, int, int));
65 static int	om_mapchar __P((void *, int, unsigned int *));
66 static void	om_putchar __P((void *, int, int, u_int, long));
67 static void	om_copycols __P((void *, int, int, int, int));
68 static void	om_copyrows __P((void *, int, int, int num));
69 static void	om_erasecols __P((void *, int, int, int, long));
70 static void	om_eraserows __P((void *, int, int, long));
71 static int	om_alloc_attr __P((void *, int, int, int, long *));
72 
73 struct wsdisplay_emulops omfb_emulops = {
74 	om_cursor,
75 	om_mapchar,
76 	om_putchar,
77 	om_copycols,
78 	om_erasecols,
79 	om_copyrows,
80 	om_eraserows,
81 	om_alloc_attr
82 };
83 
84 #define	ALL1BITS	(~0U)
85 #define	ALL0BITS	(0U)
86 #define	BLITWIDTH	(32)
87 #define	ALIGNMASK	(0x1f)
88 #define	BYTESDONE	(4)
89 
90 #define	W(p) (*(u_int32_t *)(p))
91 #define	R(p) (*(u_int32_t *)((caddr_t)(p) + 0x40000))
92 
93 /*
94  * Blit a character at the specified co-ordinates.
95  */
96 static void
97 om_putchar(cookie, row, startcol, uc, attr)
98 	void *cookie;
99 	int row, startcol;
100 	u_int uc;
101 	long attr;
102 {
103 	struct rcons *rc = cookie;
104 	struct raster *rap = rc->rc_sp;
105 	caddr_t p;
106 	int scanspan, startx, height, width, align, y;
107 	u_int32_t lmask, rmask, glyph, inverse;
108 	u_int32_t *g;
109 
110 	scanspan = rap->linelongs * 4;
111 	y = rc->rc_yorigin + rc->rc_font->height * row;
112 	startx = rc->rc_xorigin + rc->rc_font->width * startcol;
113 	height = rc->rc_font->height;
114 	g = rc->rc_font->chars[uc].r->pixels;
115 	inverse = (attr != 0) ? ALL1BITS : ALL0BITS;
116 
117 	p = (caddr_t)rap->pixels + y * scanspan + ((startx / 32) * 4);
118 	align = startx & ALIGNMASK;
119 	width = rc->rc_font->width + align;
120 	lmask = ALL1BITS >> align;
121 	rmask = ALL1BITS << (-width & ALIGNMASK);
122 	if (width <= BLITWIDTH) {
123 		lmask &= rmask;
124 		while (height > 0) {
125 			glyph = *g;
126 			glyph = (glyph >> align) ^ inverse;
127 			W(p) = (R(p) & ~lmask) | (glyph & lmask);
128 			p += scanspan;
129 			g += 1;
130 			height--;
131 		}
132 	}
133 	else {
134 		caddr_t q = p;
135 		u_int32_t lhalf, rhalf;
136 
137 		while (height > 0) {
138 			glyph = *g;
139 			lhalf = (glyph >> align) ^ inverse;
140 			W(p) = (R(p) & ~lmask) | (lhalf & lmask);
141 			p += BYTESDONE;
142 			rhalf = (glyph << (BLITWIDTH - align)) ^ inverse;
143 			W(p) = (rhalf & rmask) | (R(p) & ~rmask);
144 
145 			p = (q += scanspan);
146 			g += 1;
147 			height--;
148 		}
149 	}
150 }
151 
152 static void
153 om_erasecols(cookie, row, startcol, ncols, attr)
154 	void *cookie;
155 	int row, startcol, ncols;
156 	long attr;
157 {
158         struct rcons *rc = cookie;
159         struct raster *rap = rc->rc_sp;
160         caddr_t p;
161         int scanspan, startx, height, width, align, w, y;
162         u_int32_t lmask, rmask, fill;
163 
164         scanspan = rap->linelongs * 4;
165         y = rc->rc_yorigin + rc->rc_font->height * row;
166         startx = rc->rc_xorigin + rc->rc_font->width * startcol;
167         height = rc->rc_font->height;
168         w = rc->rc_font->width * ncols;
169 	fill = (attr != 0) ? ALL1BITS : ALL0BITS;
170 
171 	p = (caddr_t)rap->pixels + y * scanspan + ((startx / 32) * 4);
172 	align = startx & ALIGNMASK;
173 	width = w + align;
174 	lmask = ALL1BITS >> align;
175 	rmask = ALL1BITS << (-width & ALIGNMASK);
176 	if (width <= BLITWIDTH) {
177 		lmask &= rmask;
178 		fill &= lmask;
179 		while (height > 0) {
180 			W(p) = (R(p) & ~lmask) | fill;
181 			p += scanspan;
182 			height--;
183 		}
184 	}
185 	else {
186 		caddr_t q = p;
187 		while (height > 0) {
188 			W(p) = (R(p) & ~lmask) | (fill & lmask);
189 			width -= 2 * BLITWIDTH;
190 			while (width > 0) {
191 				p += BYTESDONE;
192 				W(p) = fill;
193 				width -= BLITWIDTH;
194 			}
195 			p += BYTESDONE;
196 			W(p) = (fill & rmask) | (R(p) & ~rmask);
197 
198 			p = (q += scanspan);
199 			width = w + align;
200 			height--;
201 		}
202 	}
203 }
204 
205 static void
206 om_eraserows(cookie, startrow, nrows, attr)
207 	void *cookie;
208 	int startrow, nrows;
209 	long attr;
210 {
211 	struct rcons *rc = cookie;
212 	struct raster *rap = rc->rc_sp;
213 	caddr_t p, q;
214 	int scanspan, starty, height, width, w;
215 	u_int32_t rmask, fill;
216 
217 	scanspan = rap->linelongs * 4;
218 	starty = rc->rc_yorigin + rc->rc_font->height * startrow;
219 	height = rc->rc_font->height * nrows;
220 	w = rc->rc_font->width * rc->rc_maxcol;
221 	fill = (attr == 1) ? ALL1BITS : ALL0BITS;
222 
223 	p = (caddr_t)rap->pixels + starty * scanspan;
224 	p += (rc->rc_xorigin / 32) * 4;
225 	width = w;
226         rmask = ALL1BITS << (-width & ALIGNMASK);
227 	q = p;
228 	while (height > 0) {
229 		W(p) = fill;				/* always aligned */
230 		width -= 2 * BLITWIDTH;
231 		while (width > 0) {
232 			p += BYTESDONE;
233 			W(p) = fill;
234 			width -= BLITWIDTH;
235 		}
236 		p += BYTESDONE;
237 		W(p) = (fill & rmask) | (R(p) & ~rmask);
238 		p = (q += scanspan);
239 		width = w;
240 		height--;
241 	}
242 }
243 
244 static void
245 om_copyrows(cookie, srcrow, dstrow, nrows)
246 	void *cookie;
247 	int srcrow, dstrow, nrows;
248 {
249         struct rcons *rc = cookie;
250         struct raster *rap = rc->rc_sp;
251         caddr_t p, q;
252 	int scanspan, offset, srcy, height, width, w;
253         u_int32_t rmask;
254 
255 	scanspan = rap->linelongs * 4;
256 	height = rc->rc_font->height * nrows;
257 	offset = (dstrow - srcrow) * scanspan * rc->rc_font->height;
258 	srcy = rc->rc_yorigin + rc->rc_font->height * srcrow;
259 	if (srcrow < dstrow && srcrow + nrows > dstrow) {
260 		scanspan = -scanspan;
261 		srcy += height;
262 	}
263 
264 	p = (caddr_t)rap->pixels + srcy * (rap->linelongs * 4);
265 	p += (rc->rc_xorigin / 32) * 4;
266 	w = rc->rc_font->width * rc->rc_maxcol;
267 	width = w;
268 	rmask = ALL1BITS << (-width & ALIGNMASK);
269 	q = p;
270 	while (height > 0) {
271 		W(p + offset) = R(p);			/* always aligned */
272 		width -= 2 * BLITWIDTH;
273 		while (width > 0) {
274 			p += BYTESDONE;
275 			W(p + offset) = R(p);
276 			width -= BLITWIDTH;
277 		}
278 		p += BYTESDONE;
279 		W(p + offset) = (R(p) & rmask) | (R(p + offset) & ~rmask);
280 
281 		p = (q += scanspan);
282 		width = w;
283 		height--;
284 	}
285 }
286 
287 static void
288 om_copycols(cookie, startrow, srccol, dstcol, ncols)
289 	void *cookie;
290 	int startrow, srccol, dstcol, ncols;
291 {
292 	struct rcons *rc = cookie;
293 	struct raster *rap = rc->rc_sp;
294 	caddr_t sp, dp, basep;
295 	int scanspan, height, width, align, shift, w, y, srcx, dstx;
296 	u_int32_t lmask, rmask;
297 
298 	scanspan = rap->linelongs * 4;
299 	y = rc->rc_yorigin + rc->rc_font->height * startrow;
300 	srcx = rc->rc_xorigin + rc->rc_font->width * srccol;
301 	dstx = rc->rc_xorigin + rc->rc_font->width * dstcol;
302 	height = rc->rc_font->height;
303 	w = rc->rc_font->width * ncols;
304 	basep = (caddr_t)rap->pixels + y * scanspan;
305 
306 	align = shift = srcx & ALIGNMASK;
307 	width = w + align;
308 	align = dstx & ALIGNMASK;
309 	lmask = ALL1BITS >> align;
310 	rmask = ALL1BITS << (-(w + align) & ALIGNMASK);
311 	shift = align - shift;
312 	sp = basep + (srcx / 32) * 4;
313 	dp = basep + (dstx / 32) * 4;
314 
315 	if (shift != 0)
316 		goto hardluckalignment;
317 
318 	/* alignments comfortably match */
319 	if (width <= BLITWIDTH) {
320 		lmask &= rmask;
321 		while (height > 0) {
322 			W(dp) = (R(dp) & ~lmask) | (R(sp) & lmask);
323 			dp += scanspan;
324 			sp += scanspan;
325 			height--;
326 		}
327 	}
328 	/* copy forward (left-to-right) */
329 	else if (dstcol < srccol || srccol + ncols < dstcol) {
330 		caddr_t sq = sp, dq = dp;
331 
332 		w = width;
333 		while (height > 0) {
334 			W(dp) = (R(dp) & ~lmask) | (R(sp) & lmask);
335 			width -= 2 * BLITWIDTH;
336 			while (width > 0) {
337 				sp += BYTESDONE;
338 				dp += BYTESDONE;
339 				W(dp) = R(sp);
340 				width -= BLITWIDTH;
341 			}
342 			sp += BYTESDONE;
343 			dp += BYTESDONE;
344 			W(dp) = (R(sp) & rmask) | (R(dp) & ~rmask);
345 			sp = (sq += scanspan);
346 			dp = (dq += scanspan);
347 			width = w;
348 			height--;
349 		}
350 	}
351 	/* copy backward (right-to-left) */
352 	else {
353 		caddr_t sq, dq;
354 
355 		sq = (sp += width / 32 * 4);
356 		dq = (dp += width / 32 * 4);
357 		w = width;
358 		while (height > 0) {
359 			W(dp) = (R(sp) & rmask) | (R(dp) & ~rmask);
360 			width -= 2 * BLITWIDTH;
361 			while (width > 0) {
362 				sp -= BYTESDONE;
363 				dp -= BYTESDONE;
364 				W(dp) = R(sp);
365 				width -= BLITWIDTH;
366 			}
367 			sp -= BYTESDONE;
368 			dp -= BYTESDONE;
369 			W(dp) = (R(dp) & ~lmask) | (R(sp) & lmask);
370 
371 			sp = (sq += scanspan);
372 			dp = (dq += scanspan);
373 			width = w;
374 			height--;
375 		}
376 	}
377 	return;
378 
379     hardluckalignment:
380 	/* alignments painfully disagree */
381 }
382 
383 /*
384  * Map a character.
385  */
386 static int
387 om_mapchar(cookie, c, cp)
388 	void *cookie;
389 	int c;
390 	u_int *cp;
391 {
392 	if (c < 128) {
393 		*cp = c;
394 		return (5);
395 	}
396 	*cp = ' ';
397 	return (0);
398 }
399 
400 /*
401  * Position|{enable|disable} the cursor at the specified location.
402  */
403 static void
404 om_cursor(cookie, on, row, col)
405 	void *cookie;
406 	int on, row, col;
407 {
408 	struct rcons *rc = cookie;
409 	struct raster *rap = rc->rc_sp;
410 	caddr_t p;
411 	int scanspan, startx, height, width, align, y;
412 	u_int32_t lmask, rmask, image;
413 
414 	if (!on) {
415 		/* make sure it's on */
416 		if ((rc->rc_bits & RC_CURSOR) == 0)
417 			return;
418 
419 		row = *rc->rc_crowp;
420 		col = *rc->rc_ccolp;
421 	} else {
422 		/* unpaint the old copy. */
423 		*rc->rc_crowp = row;
424 		*rc->rc_ccolp = col;
425 	}
426 
427 	scanspan = rap->linelongs * 4;
428 	y = rc->rc_yorigin + rc->rc_font->height * row;
429 	startx = rc->rc_xorigin + rc->rc_font->width * col;
430 	height = rc->rc_font->height;
431 
432 	p = (caddr_t)rap->pixels + y * scanspan + ((startx / 32) * 4);
433 	align = startx & ALIGNMASK;
434 	width = rc->rc_font->width + align;
435 	lmask = ALL1BITS >> align;
436 	rmask = ALL1BITS << (-width & ALIGNMASK);
437 	if (width <= BLITWIDTH) {
438 		lmask &= rmask;
439 		while (height > 0) {
440 			image = R(p);
441 			W(p) = (image & ~lmask) | ((image ^ ALL1BITS) & lmask);
442 			p += scanspan;
443 			height--;
444 		}
445 	}
446 	else {
447 		caddr_t q = p;
448 
449 		while (height > 0) {
450 			image = R(p);
451 			W(p) = (image & ~lmask) | ((image ^ ALL1BITS) & lmask);
452 			p += BYTESDONE;
453 			image = R(p);
454 			W(p) = ((image ^ ALL1BITS) & rmask) | (image & ~rmask);
455 
456 			p = (q += scanspan);
457 			height--;
458 		}
459 	}
460 	rc->rc_bits ^= RC_CURSOR;
461 }
462 
463 /*
464  * Allocate attribute. We just pack these into an integer.
465  */
466 static int
467 om_alloc_attr(id, fg, bg, flags, attrp)
468 	void *id;
469 	int fg, bg, flags;
470 	long *attrp;
471 {
472 	if (flags & (WSATTR_HILIT | WSATTR_BLINK |
473 		     WSATTR_UNDERLINE | WSATTR_WSCOLORS))
474 		return (EINVAL);
475 	if (flags & WSATTR_REVERSE)
476 		*attrp = 1;
477 	else
478 		*attrp = 0;
479 	return (0);
480 }
481 
482 void
483 rcons_init(rc, mrow, mcol)
484 	struct rcons *rc;
485 	int mrow, mcol;
486 {
487 	struct raster *rp = rc->rc_sp;
488 	int i;
489 
490 	rc->rc_font = &gallant19; /* 12x22 monospacing font */
491 
492 	/* Get distance to top and bottom of font from font origin */
493 	rc->rc_font_ascent = -(rc->rc_font->chars)['a'].homey;
494 
495 	i = rp->height / rc->rc_font->height;
496 	rc->rc_maxrow = min(i, mrow);
497 
498 	i = rp->width / rc->rc_font->width;
499 	rc->rc_maxcol = min(i, mcol);
500 
501 	/* Center emulator screen (but align x origin to 32 bits) */
502 	rc->rc_xorigin =
503 	    ((rp->width - rc->rc_maxcol * rc->rc_font->width) / 2) & ~ALIGNMASK;
504 	rc->rc_yorigin =
505 	    (rp->height - rc->rc_maxrow * rc->rc_font->height) / 2;
506 #if 0
507 	/* Raster width used for row copies */
508 	rc->rc_raswidth = rc->rc_maxcol * rc->rc_font->width;
509 	if (rc->rc_raswidth & ALIGNMASK) {
510 		/* Pad to 32 bits */
511 		i = (rc->rc_raswidth + ALIGNMASK) & ~ALIGNMASK;
512 		/* Make sure width isn't too wide */
513 		if (rc->rc_xorigin + i <= rp->width)
514 			rc->rc_raswidth = i;
515 	}
516 #endif
517 	rc->rc_bits = 0;
518 }
519