xref: /openbsd/sys/arch/luna88k/dev/omrasops.c (revision 404b540a)
1 /* $OpenBSD: omrasops.c,v 1.6 2009/09/05 14:09:35 miod Exp $ */
2 /* $NetBSD: omrasops.c,v 1.1 2000/01/05 08:48:56 nisimura Exp $ */
3 
4 /*-
5  * Copyright (c) 2000 The NetBSD Foundation, Inc.
6  * All rights reserved.
7  *
8  * This code is derived from software contributed to The NetBSD Foundation
9  * by Tohru Nishimura.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 /*
34  * Designed speficically for 'm68k bitorder';
35  *	- most significant byte is stored at lower address,
36  *	- most significant bit is displayed at left most on screen.
37  * Implementation relies on;
38  *	- every memory references is done in aligned 32bit chunk,
39  *	- font glyphs are stored in 32bit padded.
40  */
41 
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/device.h>
45 
46 #include <dev/wscons/wsconsio.h>
47 #include <dev/wscons/wsdisplayvar.h>
48 #include <dev/rasops/rasops.h>
49 
50 /* wscons emulator operations */
51 int	om_cursor(void *, int, int, int);
52 int	om_putchar(void *, int, int, u_int, long);
53 int	om_copycols(void *, int, int, int, int);
54 int	om_copyrows(void *, int, int, int num);
55 int	om_erasecols(void *, int, int, int, long);
56 int	om_eraserows(void *, int, int, long);
57 
58 #define	ALL1BITS	(~0U)
59 #define	ALL0BITS	(0U)
60 #define	BLITWIDTH	(32)
61 #define	ALIGNMASK	(0x1f)
62 #define	BYTESDONE	(4)
63 
64 #define	W(p) (*(u_int32_t *)(p))
65 #define	R(p) (*(u_int32_t *)((caddr_t)(p) + 0x40000))
66 
67 /*
68  * Blit a character at the specified co-ordinates.
69  */
70 int
71 om_putchar(cookie, row, startcol, uc, attr)
72 	void *cookie;
73 	int row, startcol;
74 	u_int uc;
75 	long attr;
76 {
77 	struct rasops_info *ri = cookie;
78 	caddr_t p;
79 	int scanspan, startx, height, width, align, y;
80 	u_int32_t lmask, rmask, glyph, inverse;
81 	int i, fg, bg;
82 	u_int8_t *fb;
83 
84 	scanspan = ri->ri_stride;
85 	y = ri->ri_font->fontheight * row;
86 	startx = ri->ri_font->fontwidth * startcol;
87 	height = ri->ri_font->fontheight;
88 	fb = ri->ri_font->data +
89 	    (uc - ri->ri_font->firstchar) * ri->ri_fontscale;
90 	ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL);
91 	inverse = (bg != 0) ? ALL1BITS : ALL0BITS;
92 
93 	p = (caddr_t)ri->ri_bits + y * scanspan + ((startx / 32) * 4);
94 	align = startx & ALIGNMASK;
95 	width = ri->ri_font->fontwidth + align;
96 	lmask = ALL1BITS >> align;
97 	rmask = ALL1BITS << (-width & ALIGNMASK);
98 	if (width <= BLITWIDTH) {
99 		lmask &= rmask;
100 		while (height > 0) {
101 			glyph = 0;
102 			for (i = ri->ri_font->stride; i != 0; i--)
103 				glyph = (glyph << 8) | *fb++;
104 			glyph <<= (4 - ri->ri_font->stride) * NBBY;
105 			glyph = (glyph >> align) ^ inverse;
106 			W(p) = (R(p) & ~lmask) | (glyph & lmask);
107 			p += scanspan;
108 			height--;
109 		}
110 	}
111 	else {
112 		caddr_t q = p;
113 		u_int32_t lhalf, rhalf;
114 
115 		while (height > 0) {
116 			glyph = 0;
117 			for (i = ri->ri_font->stride; i != 0; i--)
118 				glyph = (glyph << 8) | *fb++;
119 			glyph <<= (4 - ri->ri_font->stride) * NBBY;
120 			lhalf = (glyph >> align) ^ inverse;
121 			W(p) = (R(p) & ~lmask) | (lhalf & lmask);
122 			p += BYTESDONE;
123 			rhalf = (glyph << (BLITWIDTH - align)) ^ inverse;
124 			W(p) = (rhalf & rmask) | (R(p) & ~rmask);
125 
126 			p = (q += scanspan);
127 			height--;
128 		}
129 	}
130 
131 	return 0;
132 }
133 
134 int
135 om_erasecols(cookie, row, startcol, ncols, attr)
136 	void *cookie;
137 	int row, startcol, ncols;
138 	long attr;
139 {
140         struct rasops_info *ri = cookie;
141         caddr_t p;
142         int scanspan, startx, height, width, align, w, y;
143         u_int32_t lmask, rmask, fill;
144 
145         scanspan = ri->ri_stride;
146         y = ri->ri_font->fontheight * row;
147         startx = ri->ri_font->fontwidth * startcol;
148         height = ri->ri_font->fontheight;
149         w = ri->ri_font->fontwidth * ncols;
150 	fill = (attr != 0) ? ALL1BITS : ALL0BITS;
151 
152 	p = (caddr_t)ri->ri_bits + y * scanspan + ((startx / 32) * 4);
153 	align = startx & ALIGNMASK;
154 	width = w + align;
155 	lmask = ALL1BITS >> align;
156 	rmask = ALL1BITS << (-width & ALIGNMASK);
157 	if (width <= BLITWIDTH) {
158 		lmask &= rmask;
159 		fill &= lmask;
160 		while (height > 0) {
161 			W(p) = (R(p) & ~lmask) | fill;
162 			p += scanspan;
163 			height--;
164 		}
165 	}
166 	else {
167 		caddr_t q = p;
168 		while (height > 0) {
169 			W(p) = (R(p) & ~lmask) | (fill & lmask);
170 			width -= 2 * BLITWIDTH;
171 			while (width > 0) {
172 				p += BYTESDONE;
173 				W(p) = fill;
174 				width -= BLITWIDTH;
175 			}
176 			p += BYTESDONE;
177 			W(p) = (fill & rmask) | (R(p) & ~rmask);
178 
179 			p = (q += scanspan);
180 			width = w + align;
181 			height--;
182 		}
183 	}
184 
185 	return 0;
186 }
187 
188 int
189 om_eraserows(cookie, startrow, nrows, attr)
190 	void *cookie;
191 	int startrow, nrows;
192 	long attr;
193 {
194 	struct rasops_info *ri = cookie;
195 	caddr_t p, q;
196 	int scanspan, starty, height, width, w;
197 	u_int32_t rmask, fill;
198 
199 	scanspan = ri->ri_stride;
200 	starty = ri->ri_font->fontheight * startrow;
201 	height = ri->ri_font->fontheight * nrows;
202 	w = ri->ri_emuwidth;
203 	fill = (attr == 1) ? ALL1BITS : ALL0BITS;
204 
205 	p = (caddr_t)ri->ri_bits + starty * scanspan;
206 	width = w;
207         rmask = ALL1BITS << (-width & ALIGNMASK);
208 	q = p;
209 	while (height > 0) {
210 		W(p) = fill;				/* always aligned */
211 		width -= 2 * BLITWIDTH;
212 		while (width > 0) {
213 			p += BYTESDONE;
214 			W(p) = fill;
215 			width -= BLITWIDTH;
216 		}
217 		p += BYTESDONE;
218 		W(p) = (fill & rmask) | (R(p) & ~rmask);
219 		p = (q += scanspan);
220 		width = w;
221 		height--;
222 	}
223 
224 	return 0;
225 }
226 
227 int
228 om_copyrows(cookie, srcrow, dstrow, nrows)
229 	void *cookie;
230 	int srcrow, dstrow, nrows;
231 {
232         struct rasops_info *ri = cookie;
233         caddr_t p, q;
234 	int scanspan, offset, srcy, height, width, w;
235         u_int32_t rmask;
236 
237 	scanspan = ri->ri_stride;
238 	height = ri->ri_font->fontheight * nrows;
239 	offset = (dstrow - srcrow) * scanspan * ri->ri_font->fontheight;
240 	srcy = ri->ri_font->fontheight * srcrow;
241 	if (srcrow < dstrow && srcrow + nrows > dstrow) {
242 		scanspan = -scanspan;
243 		srcy += height;
244 	}
245 
246 	p = (caddr_t)ri->ri_bits + srcy * ri->ri_stride;
247 	w = ri->ri_emuwidth;
248 	width = w;
249 	rmask = ALL1BITS << (-width & ALIGNMASK);
250 	q = p;
251 	while (height > 0) {
252 		W(p + offset) = R(p);			/* always aligned */
253 		width -= 2 * BLITWIDTH;
254 		while (width > 0) {
255 			p += BYTESDONE;
256 			W(p + offset) = R(p);
257 			width -= BLITWIDTH;
258 		}
259 		p += BYTESDONE;
260 		W(p + offset) = (R(p) & rmask) | (R(p + offset) & ~rmask);
261 
262 		p = (q += scanspan);
263 		width = w;
264 		height--;
265 	}
266 
267 	return 0;
268 }
269 
270 int
271 om_copycols(cookie, startrow, srccol, dstcol, ncols)
272 	void *cookie;
273 	int startrow, srccol, dstcol, ncols;
274 {
275 	struct rasops_info *ri = cookie;
276 	caddr_t sp, dp, basep;
277 	int scanspan, height, width, align, shift, w, y, srcx, dstx;
278 	u_int32_t lmask, rmask;
279 
280 	scanspan = ri->ri_stride;
281 	y = ri->ri_font->fontheight * startrow;
282 	srcx = ri->ri_font->fontwidth * srccol;
283 	dstx = ri->ri_font->fontwidth * dstcol;
284 	height = ri->ri_font->fontheight;
285 	w = ri->ri_font->fontwidth * ncols;
286 	basep = (caddr_t)ri->ri_bits + y * scanspan;
287 
288 	align = shift = srcx & ALIGNMASK;
289 	width = w + align;
290 	align = dstx & ALIGNMASK;
291 	lmask = ALL1BITS >> align;
292 	rmask = ALL1BITS << (-(w + align) & ALIGNMASK);
293 	shift = align - shift;
294 	sp = basep + (srcx / 32) * 4;
295 	dp = basep + (dstx / 32) * 4;
296 
297 	if (shift != 0)
298 		goto hardluckalignment;
299 
300 	/* alignments comfortably match */
301 	if (width <= BLITWIDTH) {
302 		lmask &= rmask;
303 		while (height > 0) {
304 			W(dp) = (R(dp) & ~lmask) | (R(sp) & lmask);
305 			dp += scanspan;
306 			sp += scanspan;
307 			height--;
308 		}
309 	}
310 	/* copy forward (left-to-right) */
311 	else if (dstcol < srccol || srccol + ncols < dstcol) {
312 		caddr_t sq = sp, dq = dp;
313 
314 		w = width;
315 		while (height > 0) {
316 			W(dp) = (R(dp) & ~lmask) | (R(sp) & lmask);
317 			width -= 2 * BLITWIDTH;
318 			while (width > 0) {
319 				sp += BYTESDONE;
320 				dp += BYTESDONE;
321 				W(dp) = R(sp);
322 				width -= BLITWIDTH;
323 			}
324 			sp += BYTESDONE;
325 			dp += BYTESDONE;
326 			W(dp) = (R(sp) & rmask) | (R(dp) & ~rmask);
327 			sp = (sq += scanspan);
328 			dp = (dq += scanspan);
329 			width = w;
330 			height--;
331 		}
332 	}
333 	/* copy backward (right-to-left) */
334 	else {
335 		caddr_t sq, dq;
336 
337 		sq = (sp += width / 32 * 4);
338 		dq = (dp += width / 32 * 4);
339 		w = width;
340 		while (height > 0) {
341 			W(dp) = (R(sp) & rmask) | (R(dp) & ~rmask);
342 			width -= 2 * BLITWIDTH;
343 			while (width > 0) {
344 				sp -= BYTESDONE;
345 				dp -= BYTESDONE;
346 				W(dp) = R(sp);
347 				width -= BLITWIDTH;
348 			}
349 			sp -= BYTESDONE;
350 			dp -= BYTESDONE;
351 			W(dp) = (R(dp) & ~lmask) | (R(sp) & lmask);
352 
353 			sp = (sq += scanspan);
354 			dp = (dq += scanspan);
355 			width = w;
356 			height--;
357 		}
358 	}
359 	return 0;
360 
361     hardluckalignment:
362 	/* alignments painfully disagree */
363 
364 	return 0;
365 }
366 
367 /*
368  * Position|{enable|disable} the cursor at the specified location.
369  */
370 int
371 om_cursor(cookie, on, row, col)
372 	void *cookie;
373 	int on, row, col;
374 {
375 	struct rasops_info *ri = cookie;
376 	caddr_t p;
377 	int scanspan, startx, height, width, align, y;
378 	u_int32_t lmask, rmask, image;
379 
380 	if (!on) {
381 		/* make sure it's on */
382 		if ((ri->ri_flg & RI_CURSOR) == 0)
383 			return 0;
384 
385 		row = ri->ri_crow;
386 		col = ri->ri_ccol;
387 	} else {
388 		/* unpaint the old copy. */
389 		ri->ri_crow = row;
390 		ri->ri_ccol = col;
391 	}
392 
393 	scanspan = ri->ri_stride;
394 	y = ri->ri_font->fontheight * row;
395 	startx = ri->ri_font->fontwidth * col;
396 	height = ri->ri_font->fontheight;
397 
398 	p = (caddr_t)ri->ri_bits + y * scanspan + ((startx / 32) * 4);
399 	align = startx & ALIGNMASK;
400 	width = ri->ri_font->fontwidth + align;
401 	lmask = ALL1BITS >> align;
402 	rmask = ALL1BITS << (-width & ALIGNMASK);
403 	if (width <= BLITWIDTH) {
404 		lmask &= rmask;
405 		while (height > 0) {
406 			image = R(p);
407 			W(p) = (image & ~lmask) | ((image ^ ALL1BITS) & lmask);
408 			p += scanspan;
409 			height--;
410 		}
411 	}
412 	else {
413 		caddr_t q = p;
414 
415 		while (height > 0) {
416 			image = R(p);
417 			W(p) = (image & ~lmask) | ((image ^ ALL1BITS) & lmask);
418 			p += BYTESDONE;
419 			image = R(p);
420 			W(p) = ((image ^ ALL1BITS) & rmask) | (image & ~rmask);
421 
422 			p = (q += scanspan);
423 			height--;
424 		}
425 	}
426 	ri->ri_flg ^= RI_CURSOR;
427 
428 	return 0;
429 }
430