xref: /openbsd/sys/arch/luna88k/dev/omrasops.c (revision 369bbb89)
1 /* $OpenBSD: omrasops.c,v 1.18 2022/11/06 13:01:22 aoyama 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 specifically 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 reference is done in aligned 32bit chunks,
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 #include <luna88k/dev/omrasops.h>
51 
52 #include <machine/board.h>
53 #define	OMFB_PLANEMASK	BMAP_BMSEL	/* planemask register */
54 #define	OMFB_ROPFUNC	BMAP_FN		/* ROP function code */
55 
56 /* wscons emulator operations */
57 int	om_copycols(void *, int, int, int, int);
58 int	om_copyrows(void *, int, int, int num);
59 int	om_erasecols(void *, int, int, int, uint32_t);
60 int	om_eraserows(void *, int, int, uint32_t);
61 int	om1_cursor(void *, int, int, int);
62 int	om1_putchar(void *, int, int, u_int, uint32_t);
63 int	om4_cursor(void *, int, int, int);
64 int	om4_putchar(void *, int, int, u_int, uint32_t);
65 
66 /* depth-depended setup functions */
67 void	setup_omrasops1(struct rasops_info *);
68 void	setup_omrasops4(struct rasops_info *);
69 
70 /* internal functions for 1bpp/4bpp */
71 int	om1_windowmove(struct rasops_info *, u_int16_t, u_int16_t, u_int16_t,
72 		u_int16_t, u_int16_t, u_int16_t, int16_t, int16_t);
73 int	om4_windowmove(struct rasops_info *, u_int16_t, u_int16_t, u_int16_t,
74 		u_int16_t, u_int16_t, u_int16_t, int16_t, int16_t);
75 
76 /* MI function in src/sys/dev/rasops/rasops.c */
77 int     rasops_pack_cattr(void *, int, int, int, uint32_t *);
78 int     rasops_pack_mattr(void *, int, int, int, uint32_t *);
79 
80 static int (*om_windowmove)(struct rasops_info *, u_int16_t, u_int16_t,
81 		u_int16_t, u_int16_t, u_int16_t, u_int16_t, int16_t, int16_t);
82 
83 extern struct wsscreen_descr omfb_stdscreen;
84 
85 #define	ALL1BITS	(~0U)
86 #define	ALL0BITS	(0U)
87 #define	BLITWIDTH	(32)
88 #define	ALIGNMASK	(0x1f)
89 #define	BYTESDONE	(4)
90 
91 /*
92  * Blit a character at the specified co-ordinates.
93  * - 1bpp version -
94  */
95 int
om1_putchar(void * cookie,int row,int startcol,u_int uc,uint32_t attr)96 om1_putchar(void *cookie, int row, int startcol, u_int uc, uint32_t attr)
97 {
98 	struct rasops_info *ri = cookie;
99 	u_int8_t *p;
100 	int scanspan, startx, height, width, align, y;
101 	u_int32_t lmask, rmask, glyph, inverse;
102 	int i, fg, bg;
103 	u_int8_t *fb;
104 
105 	scanspan = ri->ri_stride;
106 	y = ri->ri_font->fontheight * row;
107 	startx = ri->ri_font->fontwidth * startcol;
108 	height = ri->ri_font->fontheight;
109 	fb = (u_int8_t *)ri->ri_font->data +
110 	    (uc - ri->ri_font->firstchar) * ri->ri_fontscale;
111 	ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL);
112 	inverse = (bg != 0) ? ALL1BITS : ALL0BITS;
113 
114 	p = (u_int8_t *)ri->ri_bits + y * scanspan + ((startx / 32) * 4);
115 	align = startx & ALIGNMASK;
116 	width = ri->ri_font->fontwidth + align;
117 	lmask = ALL1BITS >> align;
118 	rmask = ALL1BITS << (-width & ALIGNMASK);
119 	if (width <= BLITWIDTH) {
120 		lmask &= rmask;
121 		while (height > 0) {
122 			glyph = 0;
123 			for (i = ri->ri_font->stride; i != 0; i--)
124 				glyph = (glyph << 8) | *fb++;
125 			glyph <<= (4 - ri->ri_font->stride) * NBBY;
126 			glyph = (glyph >> align) ^ inverse;
127 			*P0(p) = (*P0(p) & ~lmask) | (glyph & lmask);
128 			p += scanspan;
129 			height--;
130 		}
131 	} else {
132 		u_int8_t *q = p;
133 		u_int32_t lhalf, rhalf;
134 
135 		while (height > 0) {
136 			glyph = 0;
137 			for (i = ri->ri_font->stride; i != 0; i--)
138 				glyph = (glyph << 8) | *fb++;
139 			glyph <<= (4 - ri->ri_font->stride) * NBBY;
140 			lhalf = (glyph >> align) ^ inverse;
141 			*P0(p) = (*P0(p) & ~lmask) | (lhalf & lmask);
142 
143 			p += BYTESDONE;
144 
145 			rhalf = (glyph << (BLITWIDTH - align)) ^ inverse;
146 			*P0(p) = (rhalf & rmask) | (*P0(p) & ~rmask);
147 
148 			p = (q += scanspan);
149 			height--;
150 		}
151 	}
152 
153 	return 0;
154 }
155 
156 /*
157  * Blit a character at the specified co-ordinates
158  * - 4bpp version -
159  */
160 int
om4_putchar(void * cookie,int row,int startcol,u_int uc,uint32_t attr)161 om4_putchar(void *cookie, int row, int startcol, u_int uc, uint32_t attr)
162 {
163 	struct rasops_info *ri = cookie;
164 	u_int8_t *p;
165 	int scanspan, startx, height, width, align, y;
166 	u_int32_t lmask, rmask, glyph, glyphbg, fgpat, bgpat;
167 	u_int32_t fgmask0, fgmask1, fgmask2, fgmask3;
168 	u_int32_t bgmask0, bgmask1, bgmask2, bgmask3;
169 	int i, fg, bg;
170 	u_int8_t *fb;
171 
172 	scanspan = ri->ri_stride;
173 	y = ri->ri_font->fontheight * row;
174 	startx = ri->ri_font->fontwidth * startcol;
175 	height = ri->ri_font->fontheight;
176 	fb = (u_int8_t *)ri->ri_font->data +
177 	    (uc - ri->ri_font->firstchar) * ri->ri_fontscale;
178 	ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL);
179 	fgmask0 = (fg & 0x01) ? ALL1BITS : ALL0BITS;
180 	fgmask1 = (fg & 0x02) ? ALL1BITS : ALL0BITS;
181 	fgmask2 = (fg & 0x04) ? ALL1BITS : ALL0BITS;
182 	fgmask3 = (fg & 0x08) ? ALL1BITS : ALL0BITS;
183 	bgmask0 = (bg & 0x01) ? ALL1BITS : ALL0BITS;
184 	bgmask1 = (bg & 0x02) ? ALL1BITS : ALL0BITS;
185 	bgmask2 = (bg & 0x04) ? ALL1BITS : ALL0BITS;
186 	bgmask3 = (bg & 0x08) ? ALL1BITS : ALL0BITS;
187 
188 	p = (u_int8_t *)ri->ri_bits + y * scanspan + ((startx / 32) * 4);
189 	align = startx & ALIGNMASK;
190 	width = ri->ri_font->fontwidth + align;
191 	lmask = ALL1BITS >> align;
192 	rmask = ALL1BITS << (-width & ALIGNMASK);
193 
194 	/* select all planes for later ROP function target */
195 	*(volatile u_int32_t *)OMFB_PLANEMASK = 0xff;
196 
197 	if (width <= BLITWIDTH) {
198 		lmask &= rmask;
199 		/* set lmask as ROP mask value, with THROUGH mode */
200 		((volatile u_int32_t *)OMFB_ROPFUNC)[ROP_THROUGH] = lmask;
201 
202 		while (height > 0) {
203 			glyph = 0;
204 			for (i = ri->ri_font->stride; i != 0; i--)
205 				glyph = (glyph << 8) | *fb++;
206 			glyph <<= (4 - ri->ri_font->stride) * NBBY;
207 			glyph = (glyph >> align);
208 			glyphbg = glyph ^ ALL1BITS;
209 
210 			fgpat = glyph & fgmask0;
211 			bgpat = glyphbg & bgmask0;
212 			*P0(p) = (fgpat | bgpat);
213 			fgpat = glyph & fgmask1;
214 			bgpat = glyphbg & bgmask1;
215 			*P1(p) = (fgpat | bgpat);
216 			fgpat = glyph & fgmask2;
217 			bgpat = glyphbg & bgmask2;
218 			*P2(p) = (fgpat | bgpat);
219 			fgpat = glyph & fgmask3;
220 			bgpat = glyphbg & bgmask3;
221 			*P3(p) = (fgpat | bgpat);
222 
223 			p += scanspan;
224 			height--;
225 		}
226 		/* reset mask value */
227 		((volatile u_int32_t *)OMFB_ROPFUNC)[ROP_THROUGH] = ALL1BITS;
228 	} else {
229 		u_int8_t *q = p;
230 		u_int32_t lhalf, rhalf;
231 		u_int32_t lhalfbg, rhalfbg;
232 
233 		while (height > 0) {
234 			glyph = 0;
235 			for (i = ri->ri_font->stride; i != 0; i--)
236 				glyph = (glyph << 8) | *fb++;
237 			glyph <<= (4 - ri->ri_font->stride) * NBBY;
238 			lhalf = (glyph >> align);
239 			lhalfbg = lhalf ^ ALL1BITS;
240 			/* set lmask as ROP mask value, with THROUGH mode */
241 			((volatile u_int32_t *)OMFB_ROPFUNC)[ROP_THROUGH]
242 				= lmask;
243 
244 			fgpat = lhalf & fgmask0;
245 			bgpat = lhalfbg & bgmask0;
246 			*P0(p) = (fgpat | bgpat);
247 			fgpat = lhalf & fgmask1;
248 			bgpat = lhalfbg & bgmask1;
249 			*P1(p) = (fgpat | bgpat);
250 			fgpat = lhalf & fgmask2;
251 			bgpat = lhalfbg & bgmask2;
252 			*P2(p) = (fgpat | bgpat);
253 			fgpat = lhalf & fgmask3;
254 			bgpat = lhalfbg & bgmask3;
255 			*P3(p) = (fgpat | bgpat);
256 
257 			p += BYTESDONE;
258 
259 			rhalf = (glyph << (BLITWIDTH - align));
260 			rhalfbg = rhalf ^ ALL1BITS;
261 			/* set rmask as ROP mask value, with THROUGH mode */
262 			((volatile u_int32_t *)OMFB_ROPFUNC)[ROP_THROUGH]
263 				= rmask;
264 
265 			fgpat = rhalf & fgmask0;
266 			bgpat = rhalfbg & bgmask0;
267 			*P0(p) = (fgpat | bgpat);
268 			fgpat = rhalf & fgmask1;
269 			bgpat = rhalfbg & bgmask1;
270 			*P1(p) = (fgpat | bgpat);
271 			fgpat = rhalf & fgmask2;
272 			bgpat = rhalfbg & bgmask2;
273 			*P2(p) = (fgpat | bgpat);
274 			fgpat = rhalf & fgmask3;
275 			bgpat = rhalfbg & bgmask3;
276 			*P3(p) = (fgpat | bgpat);
277 
278 			p = (q += scanspan);
279 			height--;
280 		}
281 		/* reset mask value */
282 		((volatile u_int32_t *)OMFB_ROPFUNC)[ROP_THROUGH] = ALL1BITS;
283 	}
284 	/* select plane #0 only; XXX need this ? */
285 	*(volatile u_int32_t *)OMFB_PLANEMASK = 0x01;
286 
287 	return 0;
288 }
289 
290 int
om_erasecols(void * cookie,int row,int col,int num,uint32_t attr)291 om_erasecols(void *cookie, int row, int col, int num, uint32_t attr)
292 {
293 	struct rasops_info *ri = cookie;
294 	int fg, bg;
295 	int snum, scol, srow;
296 
297 	ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL);
298 
299 	snum = num * ri->ri_font->fontwidth;
300 	scol = col * ri->ri_font->fontwidth  + ri->ri_xorigin;
301 	srow = row * ri->ri_font->fontheight + ri->ri_yorigin;
302 
303 	/*
304 	 * If this is too tricky for the simple raster ops engine,
305 	 * pass the fun to rasops.
306 	 */
307 	if ((*om_windowmove)(ri, scol, srow, scol, srow, snum,
308 	    ri->ri_font->fontheight, RR_CLEAR, 0xff ^ bg) != 0)
309 		rasops_erasecols(cookie, row, col, num, attr);
310 
311 	return 0;
312 }
313 
314 int
om_eraserows(void * cookie,int row,int num,uint32_t attr)315 om_eraserows(void *cookie, int row, int num, uint32_t attr)
316 {
317 	struct rasops_info *ri = cookie;
318 	int fg, bg;
319 	int srow, snum;
320 	int rc;
321 
322 	ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL);
323 	bg ^= 0xff;
324 
325 	if (num == ri->ri_rows && (ri->ri_flg & RI_FULLCLEAR)) {
326 		rc = (*om_windowmove)(ri, 0, 0, 0, 0, ri->ri_width,
327 			ri->ri_height, RR_CLEAR, bg);
328 	} else {
329 		srow = row * ri->ri_font->fontheight + ri->ri_yorigin;
330 		snum = num * ri->ri_font->fontheight;
331 		rc = (*om_windowmove)(ri, ri->ri_xorigin, srow, ri->ri_xorigin,
332 		    srow, ri->ri_emuwidth, snum, RR_CLEAR, bg);
333 	}
334 	if (rc != 0)
335 		rasops_eraserows(cookie, row, num, attr);
336 
337 	return 0;
338 }
339 
340 int
om_copyrows(void * cookie,int src,int dst,int n)341 om_copyrows(void *cookie, int src, int dst, int n)
342 {
343 	struct rasops_info *ri = cookie;
344 
345 	n   *= ri->ri_font->fontheight;
346 	src *= ri->ri_font->fontheight;
347 	dst *= ri->ri_font->fontheight;
348 
349 	(*om_windowmove)(ri, ri->ri_xorigin, ri->ri_yorigin + src,
350 		ri->ri_xorigin, ri->ri_yorigin + dst,
351 		ri->ri_emuwidth, n, RR_COPY, 0xff);
352 
353 	return 0;
354 }
355 
356 int
om_copycols(void * cookie,int row,int src,int dst,int n)357 om_copycols(void *cookie, int row, int src, int dst, int n)
358 {
359 	struct rasops_info *ri = cookie;
360 
361 	n   *= ri->ri_font->fontwidth;
362 	src *= ri->ri_font->fontwidth;
363 	dst *= ri->ri_font->fontwidth;
364 	row *= ri->ri_font->fontheight;
365 
366 	(*om_windowmove)(ri, ri->ri_xorigin + src, ri->ri_yorigin + row,
367 		ri->ri_xorigin + dst, ri->ri_yorigin + row,
368 		n, ri->ri_font->fontheight, RR_COPY, 0xff);
369 
370 	return 0;
371 }
372 
373 /*
374  * Position|{enable|disable} the cursor at the specified location.
375  * - 1bpp version -
376  */
377 int
om1_cursor(void * cookie,int on,int row,int col)378 om1_cursor(void *cookie, int on, int row, int col)
379 {
380 	struct rasops_info *ri = cookie;
381 	u_int8_t *p;
382 	int scanspan, startx, height, width, align, y;
383 	u_int32_t lmask, rmask, image;
384 
385 	if (!on) {
386 		/* make sure it's on */
387 		if ((ri->ri_flg & RI_CURSOR) == 0)
388 			return 0;
389 
390 		row = ri->ri_crow;
391 		col = ri->ri_ccol;
392 	} else {
393 		/* unpaint the old copy. */
394 		ri->ri_crow = row;
395 		ri->ri_ccol = col;
396 	}
397 
398 	scanspan = ri->ri_stride;
399 	y = ri->ri_font->fontheight * row;
400 	startx = ri->ri_font->fontwidth * col;
401 	height = ri->ri_font->fontheight;
402 
403 	p = (u_int8_t *)ri->ri_bits + y * scanspan + ((startx / 32) * 4);
404 	align = startx & ALIGNMASK;
405 	width = ri->ri_font->fontwidth + align;
406 	lmask = ALL1BITS >> align;
407 	rmask = ALL1BITS << (-width & ALIGNMASK);
408 	if (width <= BLITWIDTH) {
409 		lmask &= rmask;
410 		while (height > 0) {
411 			image = *P0(p);
412 			*P0(p) = (image & ~lmask) | ((image ^ ALL1BITS) & lmask);
413 			p += scanspan;
414 			height--;
415 		}
416 	} else {
417 		u_int8_t *q = p;
418 
419 		while (height > 0) {
420 			image = *P0(p);
421 			*P0(p) = (image & ~lmask) | ((image ^ ALL1BITS) & lmask);
422 			p += BYTESDONE;
423 
424 			image = *P0(p);
425 			*P0(p) = ((image ^ ALL1BITS) & rmask) | (image & ~rmask);
426 			p = (q += scanspan);
427 			height--;
428 		}
429 	}
430 	ri->ri_flg ^= RI_CURSOR;
431 
432 	return 0;
433 }
434 
435 /*
436  * Position|{enable|disable} the cursor at the specified location
437  * - 4bpp version -
438  */
439 int
om4_cursor(void * cookie,int on,int row,int col)440 om4_cursor(void *cookie, int on, int row, int col)
441 {
442 	struct rasops_info *ri = cookie;
443 	u_int8_t *p;
444 	int scanspan, startx, height, width, align, y;
445 	u_int32_t lmask, rmask;
446 
447 	if (!on) {
448 		/* make sure it's on */
449 		if ((ri->ri_flg & RI_CURSOR) == 0)
450 			return 0;
451 
452 		row = ri->ri_crow;
453 		col = ri->ri_ccol;
454 	} else {
455 		/* unpaint the old copy. */
456 		ri->ri_crow = row;
457 		ri->ri_ccol = col;
458 	}
459 
460 	scanspan = ri->ri_stride;
461 	y = ri->ri_font->fontheight * row;
462 	startx = ri->ri_font->fontwidth * col;
463 	height = ri->ri_font->fontheight;
464 
465 	p = (u_int8_t *)ri->ri_bits + y * scanspan + ((startx / 32) * 4);
466 	align = startx & ALIGNMASK;
467 	width = ri->ri_font->fontwidth + align;
468 	lmask = ALL1BITS >> align;
469 	rmask = ALL1BITS << (-width & ALIGNMASK);
470 
471 	/* select all planes for later ROP function target */
472 	*(volatile u_int32_t *)OMFB_PLANEMASK = 0xff;
473 
474 	if (width <= BLITWIDTH) {
475 		lmask &= rmask;
476 		/* set lmask as ROP mask value, with INV2 mode */
477 		((volatile u_int32_t *)OMFB_ROPFUNC)[ROP_INV2] = lmask;
478 
479 		while (height > 0) {
480 			*W(p) = ALL1BITS;
481 			p += scanspan;
482 			height--;
483 		}
484 		/* reset mask value */
485 		((volatile u_int32_t *)OMFB_ROPFUNC)[ROP_THROUGH] = ALL1BITS;
486 	} else {
487 		u_int8_t *q = p;
488 
489 		while (height > 0) {
490 			/* set lmask as ROP mask value, with INV2 mode */
491 			((volatile u_int32_t *)OMFB_ROPFUNC)[ROP_INV2] = lmask;
492 			*W(p) = ALL1BITS;
493 
494 			p += BYTESDONE;
495 
496 			/* set rmask as ROP mask value, with INV2 mode */
497 			((volatile u_int32_t *)OMFB_ROPFUNC)[ROP_INV2] = rmask;
498 			*W(p) = ALL1BITS;
499 
500 			p = (q += scanspan);
501 			height--;
502 		}
503 		/* reset mask value */
504 		((volatile u_int32_t *)OMFB_ROPFUNC)[ROP_THROUGH] = ALL1BITS;
505 	}
506 	/* select plane #0 only; XXX need this ? */
507 	*(volatile u_int32_t *)OMFB_PLANEMASK = 0x01;
508 
509 	ri->ri_flg ^= RI_CURSOR;
510 
511 	return 0;
512 }
513 
514 /*
515  * After calling rasops_init(), set up our depth-depend emulops,
516  * block move function and capabilities.
517  */
518 void
setup_omrasops1(struct rasops_info * ri)519 setup_omrasops1(struct rasops_info *ri)
520 {
521 	om_windowmove = om1_windowmove;
522 	ri->ri_ops.cursor  = om1_cursor;
523 	ri->ri_ops.putchar = om1_putchar;
524 	omfb_stdscreen.capabilities
525 		= ri->ri_caps & ~WSSCREEN_UNDERLINE;
526 	ri->ri_ops.pack_attr = rasops_pack_mattr;
527 }
528 
529 void
setup_omrasops4(struct rasops_info * ri)530 setup_omrasops4(struct rasops_info *ri)
531 {
532 	om_windowmove = om4_windowmove;
533 	ri->ri_ops.cursor  = om4_cursor;
534 	ri->ri_ops.putchar = om4_putchar;
535 	omfb_stdscreen.capabilities
536 		= WSSCREEN_HILIT | WSSCREEN_WSCOLORS | WSSCREEN_REVERSE;
537 	/*
538 	 * Since we set ri->ri_depth == 1, rasops_init() set
539 	 * rasops_pack_mattr for us.  But we use the color version,
540 	 * rasops_pack_cattr, on 4bpp/8bpp frame buffer.
541 	 */
542 	ri->ri_ops.pack_attr = rasops_pack_cattr;
543 }
544