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