omrasops.c revision 1.17 1 /* $NetBSD: omrasops.c,v 1.17 2014/09/28 04:43:01 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.17 2014/09/28 04:43:01 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 * - first column is at 32bit aligned address,
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 om1_cursor(void *, int, int, int);
57 static void om4_cursor(void *, int, int, int);
58 static int om_mapchar(void *, int, unsigned int *);
59 static void om1_putchar(void *, int, int, u_int, long);
60 static void om4_putchar(void *, int, int, u_int, long);
61 static void om1_copycols(void *, int, int, int, int);
62 static void om4_copycols(void *, int, int, int, int);
63 static void om1_copyrows(void *, int, int, int num);
64 static void om4_copyrows(void *, int, int, int num);
65 static void om1_erasecols(void *, int, int, int, long);
66 static void om4_erasecols(void *, int, int, int, long);
67 static void om1_eraserows(void *, int, int, long);
68 static void om4_eraserows(void *, int, int, long);
69 static int om1_allocattr(void *, int, int, int, long *);
70 static int om4_allocattr(void *, int, int, int, long *);
71 static void om4_unpack_attr(long, int *, int *, int *);
72
73 static int omrasops_init(struct rasops_info *, int, int);
74
75 #define ALL1BITS (~0U)
76 #define ALL0BITS (0U)
77 #define BLITWIDTH (32)
78 #define ALIGNMASK (0x1f)
79 #define BYTESDONE (4)
80
81 #define W(p) (*(uint32_t *)(p))
82 #define R(p) (*(uint32_t *)((uint8_t *)(p) + 0x40000))
83 #define P0(p) (*(uint32_t *)((uint8_t *)(p) + 0x40000))
84 #define P1(p) (*(uint32_t *)((uint8_t *)(p) + 0x80000))
85 #define P2(p) (*(uint32_t *)((uint8_t *)(p) + 0xc0000))
86 #define P3(p) (*(uint32_t *)((uint8_t *)(p) + 0x100000))
87
88 /*
89 * macros to handle unaligned bit copy ops.
90 * See src/sys/dev/rasops/rasops_mask.h for MI version.
91 * Also refer src/sys/arch/hp300/dev/maskbits.h.
92 * (which was implemented for ancient src/sys/arch/hp300/dev/grf_hy.c)
93 */
94
95 /* luna68k version GETBITS() that gets w bits from bit x at psrc memory */
96 #define FASTGETBITS(psrc, x, w, dst) \
97 asm("bfextu %3{%1:%2},%0" \
98 : "=d" (dst) \
99 : "di" (x), "di" (w), "o" ((uint32_t *)(psrc)))
100
101 /* luna68k version PUTBITS() that puts w bits from bit x at pdst memory */
102 /* XXX this macro assumes (x + w) <= 32 to handle unaligned residual bits */
103 #define FASTPUTBITS(src, x, w, pdst) \
104 asm("bfins %3,%0{%1:%2}" \
105 : "+o" ((uint32_t *)(pdst)) \
106 : "di" (x), "di" (w), "d" (src) \
107 : "memory" );
108
109 #define GETBITS(psrc, x, w, dst) FASTGETBITS(psrc, x, w, dst)
110 #define PUTBITS(src, x, w, pdst) FASTPUTBITS(src, x, w, pdst)
111
112 /*
113 * Blit a character at the specified co-ordinates.
114 */
115 static void
116 om1_putchar(void *cookie, int row, int startcol, u_int uc, long attr)
117 {
118 struct rasops_info *ri = cookie;
119 uint8_t *p;
120 int scanspan, startx, height, width, align, y;
121 uint32_t lmask, rmask, glyph, inverse;
122 int i;
123 uint8_t *fb;
124
125 scanspan = ri->ri_stride;
126 y = ri->ri_font->fontheight * row;
127 startx = ri->ri_font->fontwidth * startcol;
128 height = ri->ri_font->fontheight;
129 fb = (uint8_t *)ri->ri_font->data +
130 (uc - ri->ri_font->firstchar) * ri->ri_fontscale;
131 inverse = ((attr & 0x00000001) != 0) ? ALL1BITS : ALL0BITS;
132
133 p = (uint8_t *)ri->ri_bits + y * scanspan + ((startx / 32) * 4);
134 align = startx & ALIGNMASK;
135 width = ri->ri_font->fontwidth + align;
136 lmask = ALL1BITS >> align;
137 rmask = ALL1BITS << (-width & ALIGNMASK);
138 if (width <= BLITWIDTH) {
139 lmask &= rmask;
140 while (height > 0) {
141 glyph = 0;
142 for (i = ri->ri_font->stride; i != 0; i--)
143 glyph = (glyph << 8) | *fb++;
144 glyph <<= (4 - ri->ri_font->stride) * NBBY;
145 glyph = (glyph >> align) ^ inverse;
146 P0(p) = (P0(p) & ~lmask) | (glyph & lmask);
147 p += scanspan;
148 height--;
149 }
150 } else {
151 uint8_t *q = p;
152 uint32_t lhalf, rhalf;
153
154 while (height > 0) {
155 glyph = 0;
156 for (i = ri->ri_font->stride; i != 0; i--)
157 glyph = (glyph << 8) | *fb++;
158 glyph <<= (4 - ri->ri_font->stride) * NBBY;
159 lhalf = (glyph >> align) ^ inverse;
160 P0(p) = (P0(p) & ~lmask) | (lhalf & lmask);
161 p += BYTESDONE;
162 rhalf = (glyph << (BLITWIDTH - align)) ^ inverse;
163 P0(p) = (rhalf & rmask) | (P0(p) & ~rmask);
164
165 p = (q += scanspan);
166 height--;
167 }
168 }
169 }
170
171 static void
172 om4_putchar(void *cookie, int row, int startcol, u_int uc, long attr)
173 {
174 struct rasops_info *ri = cookie;
175 uint8_t *p;
176 int scanspan, startx, height, width, align, y;
177 uint32_t lmask, rmask, glyph, glyphbg, fgpat, bgpat;
178 int i, fg, bg;
179 uint8_t *fb;
180
181 scanspan = ri->ri_stride;
182 y = ri->ri_font->fontheight * row;
183 startx = ri->ri_font->fontwidth * startcol;
184 height = ri->ri_font->fontheight;
185 fb = (uint8_t *)ri->ri_font->data +
186 (uc - ri->ri_font->firstchar) * ri->ri_fontscale;
187 om4_unpack_attr(attr, &fg, &bg, NULL);
188
189 p = (uint8_t *)ri->ri_bits + y * scanspan + ((startx / 32) * 4);
190 align = startx & ALIGNMASK;
191 width = ri->ri_font->fontwidth + align;
192 lmask = ALL1BITS >> align;
193 rmask = ALL1BITS << (-width & ALIGNMASK);
194 if (width <= BLITWIDTH) {
195 lmask &= rmask;
196 while (height > 0) {
197 glyph = 0;
198 for (i = ri->ri_font->stride; i != 0; i--)
199 glyph = (glyph << 8) | *fb++;
200 glyph <<= (4 - ri->ri_font->stride) * NBBY;
201 glyph = (glyph >> align);
202 glyphbg = glyph ^ ALL1BITS;
203 fgpat = (fg & 0x01) ? glyph : 0;
204 bgpat = (bg & 0x01) ? glyphbg : 0;
205 P0(p) = (P0(p) & ~lmask) | ((fgpat | bgpat) & lmask);
206 fgpat = (fg & 0x02) ? glyph : 0;
207 bgpat = (bg & 0x02) ? glyphbg : 0;
208 P1(p) = (P1(p) & ~lmask) | ((fgpat | bgpat) & lmask);
209 fgpat = (fg & 0x04) ? glyph : 0;
210 bgpat = (bg & 0x04) ? glyphbg : 0;
211 P2(p) = (P2(p) & ~lmask) | ((fgpat | bgpat) & lmask);
212 fgpat = (fg & 0x08) ? glyph : 0;
213 bgpat = (bg & 0x08) ? glyphbg : 0;
214 P3(p) = (P3(p) & ~lmask) | ((fgpat | bgpat) & lmask);
215 p += scanspan;
216 height--;
217 }
218 } else {
219 uint8_t *q = p;
220 uint32_t lhalf, rhalf;
221 uint32_t lhalfbg, rhalfbg;
222
223 while (height > 0) {
224 glyph = 0;
225 for (i = ri->ri_font->stride; i != 0; i--)
226 glyph = (glyph << 8) | *fb++;
227 glyph <<= (4 - ri->ri_font->stride) * NBBY;
228 lhalf = (glyph >> align);
229 lhalfbg = lhalf ^ ALL1BITS;
230 fgpat = (fg & 0x01) ? lhalf : 0;
231 bgpat = (bg & 0x01) ? lhalfbg : 0;
232 P0(p) = (P0(p) & ~lmask) | ((fgpat | bgpat) & lmask);
233 fgpat = (fg & 0x02) ? lhalf : 0;
234 bgpat = (bg & 0x02) ? lhalfbg : 0;
235 P1(p) = (P1(p) & ~lmask) | ((fgpat | bgpat) & lmask);
236 fgpat = (fg & 0x04) ? lhalf : 0;
237 bgpat = (bg & 0x04) ? lhalfbg : 0;
238 P2(p) = (P2(p) & ~lmask) | ((fgpat | bgpat) & lmask);
239 fgpat = (fg & 0x08) ? lhalf : 0;
240 bgpat = (bg & 0x08) ? lhalfbg : 0;
241 P3(p) = (P3(p) & ~lmask) | ((fgpat | bgpat) & lmask);
242 p += BYTESDONE;
243 rhalf = (glyph << (BLITWIDTH - align));
244 rhalfbg = rhalf ^ ALL1BITS;
245 fgpat = (fg & 0x01) ? rhalf : 0;
246 bgpat = (bg & 0x01) ? rhalfbg : 0;
247 P0(p) = ((fgpat | bgpat) & rmask) | (P0(p) & ~rmask);
248 fgpat = (fg & 0x02) ? rhalf : 0;
249 bgpat = (bg & 0x02) ? rhalfbg : 0;
250 P1(p) = ((fgpat | bgpat) & rmask) | (P1(p) & ~rmask);
251 fgpat = (fg & 0x04) ? rhalf : 0;
252 bgpat = (bg & 0x04) ? rhalfbg : 0;
253 P2(p) = ((fgpat | bgpat) & rmask) | (P2(p) & ~rmask);
254 fgpat = (fg & 0x08) ? rhalf : 0;
255 bgpat = (bg & 0x08) ? rhalfbg : 0;
256 P3(p) = ((fgpat | bgpat) & rmask) | (P3(p) & ~rmask);
257
258 p = (q += scanspan);
259 height--;
260 }
261 }
262 }
263
264 static void
265 om1_erasecols(void *cookie, int row, int startcol, int ncols, long attr)
266 {
267 struct rasops_info *ri = cookie;
268 uint8_t *p;
269 int scanspan, startx, height, width, align, w, y;
270 uint32_t lmask, rmask, fill;
271
272 scanspan = ri->ri_stride;;
273 y = ri->ri_font->fontheight * row;
274 startx = ri->ri_font->fontwidth * startcol;
275 height = ri->ri_font->fontheight;
276 w = ri->ri_font->fontwidth * ncols;
277 fill = ((attr & 0x00000001) != 0) ? ALL1BITS : ALL0BITS;
278
279 p = (uint8_t *)ri->ri_bits + y * scanspan + ((startx / 32) * 4);
280 align = startx & ALIGNMASK;
281 width = w + align;
282 lmask = ALL1BITS >> align;
283 rmask = ALL1BITS << (-width & ALIGNMASK);
284 if (width <= BLITWIDTH) {
285 lmask &= rmask;
286 fill &= lmask;
287 while (height > 0) {
288 P0(p) = (P0(p) & ~lmask) | fill;
289 p += scanspan;
290 height--;
291 }
292 } else {
293 uint8_t *q = p;
294 while (height > 0) {
295 P0(p) = (P0(p) & ~lmask) | (fill & lmask);
296 width -= 2 * BLITWIDTH;
297 while (width > 0) {
298 p += BYTESDONE;
299 P0(p) = fill;
300 width -= BLITWIDTH;
301 }
302 p += BYTESDONE;
303 P0(p) = (fill & rmask) | (P0(p) & ~rmask);
304
305 p = (q += scanspan);
306 width = w + align;
307 height--;
308 }
309 }
310 }
311
312 static void
313 om4_erasecols(void *cookie, int row, int startcol, int ncols, long attr)
314 {
315 struct rasops_info *ri = cookie;
316 uint8_t *p;
317 int scanspan, startx, height, width, align, w, y, fg, bg;
318 uint32_t lmask, rmask, fill0, fill1, fill2, fill3;
319
320 scanspan = ri->ri_stride;;
321 y = ri->ri_font->fontheight * row;
322 startx = ri->ri_font->fontwidth * startcol;
323 height = ri->ri_font->fontheight;
324 w = ri->ri_font->fontwidth * ncols;
325 om4_unpack_attr(attr, &fg, &bg, NULL);
326 fill0 = ((bg & 0x01) != 0) ? ALL1BITS : ALL0BITS;
327 fill1 = ((bg & 0x02) != 0) ? ALL1BITS : ALL0BITS;
328 fill2 = ((bg & 0x04) != 0) ? ALL1BITS : ALL0BITS;
329 fill3 = ((bg & 0x08) != 0) ? ALL1BITS : ALL0BITS;
330
331 p = (uint8_t *)ri->ri_bits + y * scanspan + ((startx / 32) * 4);
332 align = startx & ALIGNMASK;
333 width = w + align;
334 lmask = ALL1BITS >> align;
335 rmask = ALL1BITS << (-width & ALIGNMASK);
336 if (width <= BLITWIDTH) {
337 lmask &= rmask;
338 fill0 &= lmask;
339 fill1 &= lmask;
340 fill2 &= lmask;
341 fill3 &= lmask;
342 while (height > 0) {
343 P0(p) = (P0(p) & ~lmask) | fill0;
344 P1(p) = (P1(p) & ~lmask) | fill1;
345 P2(p) = (P2(p) & ~lmask) | fill2;
346 P3(p) = (P3(p) & ~lmask) | fill3;
347 p += scanspan;
348 height--;
349 }
350 } else {
351 uint8_t *q = p;
352 while (height > 0) {
353 P0(p) = (P0(p) & ~lmask) | (fill0 & lmask);
354 P1(p) = (P1(p) & ~lmask) | (fill1 & lmask);
355 P2(p) = (P2(p) & ~lmask) | (fill2 & lmask);
356 P3(p) = (P3(p) & ~lmask) | (fill3 & lmask);
357 width -= 2 * BLITWIDTH;
358 while (width > 0) {
359 p += BYTESDONE;
360 P0(p) = fill0;
361 P1(p) = fill1;
362 P2(p) = fill2;
363 P3(p) = fill3;
364 width -= BLITWIDTH;
365 }
366 p += BYTESDONE;
367 P0(p) = (fill0 & rmask) | (P0(p) & ~rmask);
368 P1(p) = (fill1 & rmask) | (P1(p) & ~rmask);
369 P2(p) = (fill2 & rmask) | (P2(p) & ~rmask);
370 P3(p) = (fill3 & rmask) | (P3(p) & ~rmask);
371
372 p = (q += scanspan);
373 width = w + align;
374 height--;
375 }
376 }
377 }
378
379 static void
380 om1_eraserows(void *cookie, int startrow, int nrows, long attr)
381 {
382 struct rasops_info *ri = cookie;
383 uint8_t *p, *q;
384 int scanspan, starty, height, width, w;
385 uint32_t rmask, fill;
386
387 scanspan = ri->ri_stride;
388 starty = ri->ri_font->fontheight * startrow;
389 height = ri->ri_font->fontheight * nrows;
390 w = ri->ri_emuwidth;
391 fill = ((attr & 0x00000001) != 0) ? ALL1BITS : ALL0BITS;
392
393 p = (uint8_t *)ri->ri_bits + starty * scanspan;
394 width = w;
395 rmask = ALL1BITS << (-width & ALIGNMASK);
396 q = p;
397 while (height > 0) {
398 P0(p) = fill; /* always aligned */
399 width -= 2 * BLITWIDTH;
400 while (width > 0) {
401 p += BYTESDONE;
402 P0(p) = fill;
403 width -= BLITWIDTH;
404 }
405 p += BYTESDONE;
406 P0(p) = (fill & rmask) | (P0(p) & ~rmask);
407 p = (q += scanspan);
408 width = w;
409 height--;
410 }
411 }
412
413 static void
414 om4_eraserows(void *cookie, int startrow, int nrows, long attr)
415 {
416 struct rasops_info *ri = cookie;
417 uint8_t *p, *q;
418 int scanspan, starty, height, width, w, fg, bg;
419 uint32_t rmask, fill0, fill1, fill2, fill3;
420
421 scanspan = ri->ri_stride;
422 starty = ri->ri_font->fontheight * startrow;
423 height = ri->ri_font->fontheight * nrows;
424 w = ri->ri_emuwidth;
425 om4_unpack_attr(attr, &fg, &bg, NULL);
426 fill0 = ((bg & 0x01) != 0) ? ALL1BITS : ALL0BITS;
427 fill1 = ((bg & 0x02) != 0) ? ALL1BITS : ALL0BITS;
428 fill2 = ((bg & 0x04) != 0) ? ALL1BITS : ALL0BITS;
429 fill3 = ((bg & 0x08) != 0) ? ALL1BITS : ALL0BITS;
430
431 p = (uint8_t *)ri->ri_bits + starty * scanspan;
432 width = w;
433 rmask = ALL1BITS << (-width & ALIGNMASK);
434 q = p;
435 while (height > 0) {
436 P0(p) = fill0; /* always aligned */
437 P1(p) = fill1;
438 P2(p) = fill2;
439 P3(p) = fill3;
440 width -= 2 * BLITWIDTH;
441 while (width > 0) {
442 p += BYTESDONE;
443 P0(p) = fill0;
444 P1(p) = fill1;
445 P2(p) = fill2;
446 P3(p) = fill3;
447 width -= BLITWIDTH;
448 }
449 p += BYTESDONE;
450 P0(p) = (fill0 & rmask) | (P0(p) & ~rmask);
451 P1(p) = (fill1 & rmask) | (P1(p) & ~rmask);
452 P2(p) = (fill2 & rmask) | (P2(p) & ~rmask);
453 P3(p) = (fill3 & rmask) | (P3(p) & ~rmask);
454 p = (q += scanspan);
455 width = w;
456 height--;
457 }
458 }
459
460 static void
461 om1_copyrows(void *cookie, int srcrow, int dstrow, int nrows)
462 {
463 struct rasops_info *ri = cookie;
464 uint8_t *p, *q;
465 int scanspan, offset, srcy, height, width, w;
466 uint32_t rmask;
467
468 scanspan = ri->ri_stride;
469 height = ri->ri_font->fontheight * nrows;
470 offset = (dstrow - srcrow) * scanspan * ri->ri_font->fontheight;
471 srcy = ri->ri_font->fontheight * srcrow;
472 if (srcrow < dstrow && srcrow + nrows > dstrow) {
473 scanspan = -scanspan;
474 srcy = srcy + height - 1;
475 }
476
477 p = (uint8_t *)ri->ri_bits + srcy * ri->ri_stride;
478 w = ri->ri_emuwidth;
479 width = w;
480 rmask = ALL1BITS << (-width & ALIGNMASK);
481 q = p;
482 while (height > 0) {
483 P0(p + offset) = P0(p); /* always aligned */
484 width -= 2 * BLITWIDTH;
485 while (width > 0) {
486 p += BYTESDONE;
487 P0(p + offset) = P0(p);
488 width -= BLITWIDTH;
489 }
490 p += BYTESDONE;
491 P0(p + offset) = (P0(p) & rmask) | (P0(p + offset) & ~rmask);
492
493 p = (q += scanspan);
494 width = w;
495 height--;
496 }
497 }
498
499 static void
500 om4_copyrows(void *cookie, int srcrow, int dstrow, int nrows)
501 {
502 struct rasops_info *ri = cookie;
503 uint8_t *p, *q;
504 int scanspan, offset, srcy, height, width, w;
505 uint32_t rmask;
506
507 scanspan = ri->ri_stride;
508 height = ri->ri_font->fontheight * nrows;
509 offset = (dstrow - srcrow) * scanspan * ri->ri_font->fontheight;
510 srcy = ri->ri_font->fontheight * srcrow;
511 if (srcrow < dstrow && srcrow + nrows > dstrow) {
512 scanspan = -scanspan;
513 srcy = srcy + height - 1;
514 }
515
516 p = (uint8_t *)ri->ri_bits + srcy * ri->ri_stride;
517 w = ri->ri_emuwidth;
518 width = w;
519 rmask = ALL1BITS << (-width & ALIGNMASK);
520 q = p;
521 while (height > 0) {
522 P0(p + offset) = P0(p); /* always aligned */
523 P1(p + offset) = P1(p);
524 P2(p + offset) = P2(p);
525 P3(p + offset) = P3(p);
526 width -= 2 * BLITWIDTH;
527 while (width > 0) {
528 p += BYTESDONE;
529 P0(p + offset) = P0(p);
530 P1(p + offset) = P1(p);
531 P2(p + offset) = P2(p);
532 P3(p + offset) = P3(p);
533 width -= BLITWIDTH;
534 }
535 p += BYTESDONE;
536 P0(p + offset) = (P0(p) & rmask) | (P0(p + offset) & ~rmask);
537 P1(p + offset) = (P1(p) & rmask) | (P1(p + offset) & ~rmask);
538 P2(p + offset) = (P2(p) & rmask) | (P2(p + offset) & ~rmask);
539 P3(p + offset) = (P3(p) & rmask) | (P3(p + offset) & ~rmask);
540
541 p = (q += scanspan);
542 width = w;
543 height--;
544 }
545 }
546
547 static void
548 om1_copycols(void *cookie, int startrow, int srccol, int dstcol, int ncols)
549 {
550 struct rasops_info *ri = cookie;
551 uint8_t *sp, *dp, *sq, *dq, *basep;
552 int scanspan, height, w, y, srcx, dstx;
553 int sb, eb, db, sboff, full, cnt, lnum, rnum;
554 uint32_t lmask, rmask, tmp;
555 bool sbover;
556
557 scanspan = ri->ri_stride;
558 y = ri->ri_font->fontheight * startrow;
559 srcx = ri->ri_font->fontwidth * srccol;
560 dstx = ri->ri_font->fontwidth * dstcol;
561 height = ri->ri_font->fontheight;
562 w = ri->ri_font->fontwidth * ncols;
563 basep = (uint8_t *)ri->ri_bits + y * scanspan;
564
565 sb = srcx & ALIGNMASK;
566 db = dstx & ALIGNMASK;
567
568 if (db + w <= BLITWIDTH) {
569 /* Destination is contained within a single word */
570 sp = basep + (srcx / 32) * 4;
571 dp = basep + (dstx / 32) * 4;
572
573 while (height > 0) {
574 GETBITS(P0(sp), sb, w, tmp);
575 PUTBITS(tmp, db, w, P0(dp));
576 dp += scanspan;
577 sp += scanspan;
578 height--;
579 }
580 return;
581 }
582
583 lmask = (db == 0) ? 0 : ALL1BITS >> db;
584 eb = (db + w) & ALIGNMASK;
585 rmask = (eb == 0) ? 0 : ALL1BITS << (32 - eb);
586 lnum = (32 - db) & ALIGNMASK;
587 rnum = (dstx + w) & ALIGNMASK;
588
589 if (lmask != 0)
590 full = (w - (32 - db)) / 32;
591 else
592 full = w / 32;
593
594 sbover = (sb + lnum) >= 32;
595
596 if (dstcol < srccol || srccol + ncols < dstcol) {
597 /* copy forward (left-to-right) */
598 sp = basep + (srcx / 32) * 4;
599 dp = basep + (dstx / 32) * 4;
600
601 if (lmask != 0) {
602 sboff = sb + lnum;
603 if (sboff >= 32)
604 sboff -= 32;
605 } else
606 sboff = sb;
607
608 sq = sp;
609 dq = dp;
610 while (height > 0) {
611 if (lmask != 0) {
612 GETBITS(P0(sp), sb, lnum, tmp);
613 PUTBITS(tmp, db, lnum, P0(dp));
614 dp += BYTESDONE;
615 if (sbover)
616 sp += BYTESDONE;
617 }
618
619 for (cnt = full; cnt; cnt--) {
620 GETBITS(P0(sp), sboff, 32, tmp);
621 P0(dp) = tmp;
622 sp += BYTESDONE;
623 dp += BYTESDONE;
624 }
625
626 if (rmask != 0) {
627 GETBITS(P0(sp), sboff, rnum, tmp);
628 PUTBITS(tmp, 0, rnum, P0(dp));
629 }
630
631 sp = (sq += scanspan);
632 dp = (dq += scanspan);
633 height--;
634 }
635 } else {
636 /* copy backward (right-to-left) */
637 sp = basep + ((srcx + w) / 32) * 4;
638 dp = basep + ((dstx + w) / 32) * 4;
639
640 sboff = (srcx + w) & ALIGNMASK;
641 sboff -= rnum;
642 if (sboff < 0) {
643 sp -= BYTESDONE;
644 sboff += 32;
645 }
646
647 sq = sp;
648 dq = dp;
649 while (height > 0) {
650 if (rnum != 0) {
651 GETBITS(P0(sp), sboff, rnum, tmp);
652 PUTBITS(tmp, 0, rnum, P0(dp));
653 }
654
655 for (cnt = full; cnt; cnt--) {
656 sp -= BYTESDONE;
657 dp -= BYTESDONE;
658 GETBITS(P0(sp), sboff, 32, tmp);
659 P0(dp) = tmp;
660 }
661
662 if (lmask != 0) {
663 if (sbover)
664 sp -= BYTESDONE;
665 dp -= BYTESDONE;
666 GETBITS(P0(sp), sb, lnum, tmp);
667 PUTBITS(tmp, db, lnum, P0(dp));
668 }
669
670 sp = (sq += scanspan);
671 dp = (dq += scanspan);
672 height--;
673 }
674 }
675 }
676
677 static void
678 om4_copycols(void *cookie, int startrow, int srccol, int dstcol, int ncols)
679 {
680 struct rasops_info *ri = cookie;
681 uint8_t *sp, *dp, *sq, *dq, *basep;
682 int scanspan, height, w, y, srcx, dstx;
683 int sb, eb, db, sboff, full, cnt, lnum, rnum;
684 uint32_t lmask, rmask, tmp;
685 bool sbover;
686
687 scanspan = ri->ri_stride;
688 y = ri->ri_font->fontheight * startrow;
689 srcx = ri->ri_font->fontwidth * srccol;
690 dstx = ri->ri_font->fontwidth * dstcol;
691 height = ri->ri_font->fontheight;
692 w = ri->ri_font->fontwidth * ncols;
693 basep = (uint8_t *)ri->ri_bits + y * scanspan;
694
695 sb = srcx & ALIGNMASK;
696 db = dstx & ALIGNMASK;
697
698 if (db + w <= BLITWIDTH) {
699 /* Destination is contained within a single word */
700 sp = basep + (srcx / 32) * 4;
701 dp = basep + (dstx / 32) * 4;
702
703 while (height > 0) {
704 GETBITS(P0(sp), sb, w, tmp);
705 PUTBITS(tmp, db, w, P0(dp));
706 GETBITS(P1(sp), sb, w, tmp);
707 PUTBITS(tmp, db, w, P1(dp));
708 GETBITS(P2(sp), sb, w, tmp);
709 PUTBITS(tmp, db, w, P2(dp));
710 GETBITS(P3(sp), sb, w, tmp);
711 PUTBITS(tmp, db, w, P3(dp));
712 dp += scanspan;
713 sp += scanspan;
714 height--;
715 }
716 return;
717 }
718
719 lmask = (db == 0) ? 0 : ALL1BITS >> db;
720 eb = (db + w) & ALIGNMASK;
721 rmask = (eb == 0) ? 0 : ALL1BITS << (32 - eb);
722 lnum = (32 - db) & ALIGNMASK;
723 rnum = (dstx + w) & ALIGNMASK;
724
725 if (lmask != 0)
726 full = (w - (32 - db)) / 32;
727 else
728 full = w / 32;
729
730 sbover = (sb + lnum) >= 32;
731
732 if (dstcol < srccol || srccol + ncols < dstcol) {
733 /* copy forward (left-to-right) */
734 sp = basep + (srcx / 32) * 4;
735 dp = basep + (dstx / 32) * 4;
736
737 if (lmask != 0) {
738 sboff = sb + lnum;
739 if (sboff >= 32)
740 sboff -= 32;
741 } else
742 sboff = sb;
743
744 sq = sp;
745 dq = dp;
746 while (height > 0) {
747 if (lmask != 0) {
748 GETBITS(P0(sp), sb, lnum, tmp);
749 PUTBITS(tmp, db, lnum, P0(dp));
750 GETBITS(P1(sp), sb, lnum, tmp);
751 PUTBITS(tmp, db, lnum, P1(dp));
752 GETBITS(P2(sp), sb, lnum, tmp);
753 PUTBITS(tmp, db, lnum, P2(dp));
754 GETBITS(P3(sp), sb, lnum, tmp);
755 PUTBITS(tmp, db, lnum, P3(dp));
756 dp += BYTESDONE;
757 if (sbover)
758 sp += BYTESDONE;
759 }
760
761 for (cnt = full; cnt; cnt--) {
762 GETBITS(P0(sp), sboff, 32, tmp);
763 P0(dp) = tmp;
764 GETBITS(P1(sp), sboff, 32, tmp);
765 P1(dp) = tmp;
766 GETBITS(P2(sp), sboff, 32, tmp);
767 P2(dp) = tmp;
768 GETBITS(P3(sp), sboff, 32, tmp);
769 P3(dp) = tmp;
770 sp += BYTESDONE;
771 dp += BYTESDONE;
772 }
773
774 if (rmask != 0) {
775 GETBITS(P0(sp), sboff, rnum, tmp);
776 PUTBITS(tmp, 0, rnum, P0(dp));
777 GETBITS(P1(sp), sboff, rnum, tmp);
778 PUTBITS(tmp, 0, rnum, P1(dp));
779 GETBITS(P2(sp), sboff, rnum, tmp);
780 PUTBITS(tmp, 0, rnum, P2(dp));
781 GETBITS(P3(sp), sboff, rnum, tmp);
782 PUTBITS(tmp, 0, rnum, P3(dp));
783 }
784
785 sp = (sq += scanspan);
786 dp = (dq += scanspan);
787 height--;
788 }
789 } else {
790 /* copy backward (right-to-left) */
791 sp = basep + ((srcx + w) / 32) * 4;
792 dp = basep + ((dstx + w) / 32) * 4;
793
794 sboff = (srcx + w) & ALIGNMASK;
795 sboff -= rnum;
796 if (sboff < 0) {
797 sp -= BYTESDONE;
798 sboff += 32;
799 }
800
801 sq = sp;
802 dq = dp;
803 while (height > 0) {
804 if (rnum != 0) {
805 GETBITS(P0(sp), sboff, rnum, tmp);
806 PUTBITS(tmp, 0, rnum, P0(dp));
807 GETBITS(P1(sp), sboff, rnum, tmp);
808 PUTBITS(tmp, 0, rnum, P1(dp));
809 GETBITS(P2(sp), sboff, rnum, tmp);
810 PUTBITS(tmp, 0, rnum, P2(dp));
811 GETBITS(P3(sp), sboff, rnum, tmp);
812 PUTBITS(tmp, 0, rnum, P3(dp));
813 }
814
815 for (cnt = full; cnt; cnt--) {
816 sp -= BYTESDONE;
817 dp -= BYTESDONE;
818 GETBITS(P0(sp), sboff, 32, tmp);
819 P0(dp) = tmp;
820 GETBITS(P1(sp), sboff, 32, tmp);
821 P1(dp) = tmp;
822 GETBITS(P2(sp), sboff, 32, tmp);
823 P2(dp) = tmp;
824 GETBITS(P3(sp), sboff, 32, tmp);
825 P3(dp) = tmp;
826 }
827
828 if (lmask != 0) {
829 if (sbover)
830 sp -= BYTESDONE;
831 dp -= BYTESDONE;
832 GETBITS(P0(sp), sb, lnum, tmp);
833 PUTBITS(tmp, db, lnum, P0(dp));
834 GETBITS(P1(sp), sb, lnum, tmp);
835 PUTBITS(tmp, db, lnum, P1(dp));
836 GETBITS(P2(sp), sb, lnum, tmp);
837 PUTBITS(tmp, db, lnum, P2(dp));
838 GETBITS(P3(sp), sb, lnum, tmp);
839 PUTBITS(tmp, db, lnum, P3(dp));
840 }
841
842 sp = (sq += scanspan);
843 dp = (dq += scanspan);
844 height--;
845 }
846 }
847 }
848
849 /*
850 * Map a character.
851 */
852 static int
853 om_mapchar(void *cookie, int c, u_int *cp)
854 {
855 struct rasops_info *ri = cookie;
856 struct wsdisplay_font *wf = ri->ri_font;
857
858 if (wf->encoding != WSDISPLAY_FONTENC_ISO) {
859 c = wsfont_map_unichar(wf, c);
860
861 if (c < 0)
862 goto fail;
863 }
864 if (c < wf->firstchar || c >= (wf->firstchar + wf->numchars))
865 goto fail;
866
867 *cp = c;
868 return 5;
869
870 fail:
871 *cp = ' ';
872 return 0;
873 }
874
875 /*
876 * Position|{enable|disable} the cursor at the specified location.
877 */
878 static void
879 om1_cursor(void *cookie, int on, int row, int col)
880 {
881 struct rasops_info *ri = cookie;
882 uint8_t *p;
883 int scanspan, startx, height, width, align, y;
884 uint32_t lmask, rmask, image;
885
886 if (!on) {
887 /* make sure it's on */
888 if ((ri->ri_flg & RI_CURSOR) == 0)
889 return;
890
891 row = ri->ri_crow;
892 col = ri->ri_ccol;
893 } else {
894 /* unpaint the old copy. */
895 ri->ri_crow = row;
896 ri->ri_ccol = col;
897 }
898
899 scanspan = ri->ri_stride;
900 y = ri->ri_font->fontheight * row;
901 startx = ri->ri_font->fontwidth * col;
902 height = ri->ri_font->fontheight;
903
904 p = (uint8_t *)ri->ri_bits + y * scanspan + ((startx / 32) * 4);
905 align = startx & ALIGNMASK;
906 width = ri->ri_font->fontwidth + align;
907 lmask = ALL1BITS >> align;
908 rmask = ALL1BITS << (-width & ALIGNMASK);
909 if (width <= BLITWIDTH) {
910 lmask &= rmask;
911 while (height > 0) {
912 image = P0(p);
913 P0(p) = (image & ~lmask) | ((image ^ ALL1BITS) & lmask);
914 p += scanspan;
915 height--;
916 }
917 } else {
918 uint8_t *q = p;
919
920 while (height > 0) {
921 image = P0(p);
922 P0(p) = (image & ~lmask) | ((image ^ ALL1BITS) & lmask);
923 p += BYTESDONE;
924 image = P0(p);
925 P0(p) = ((image ^ ALL1BITS) & rmask) | (image & ~rmask);
926
927 p = (q += scanspan);
928 height--;
929 }
930 }
931 ri->ri_flg ^= RI_CURSOR;
932 }
933
934 static void
935 om4_cursor(void *cookie, int on, int row, int col)
936 {
937 struct rasops_info *ri = cookie;
938 uint8_t *p;
939 int scanspan, startx, height, width, align, y;
940 uint32_t lmask, rmask, image;
941
942 if (!on) {
943 /* make sure it's on */
944 if ((ri->ri_flg & RI_CURSOR) == 0)
945 return;
946
947 row = ri->ri_crow;
948 col = ri->ri_ccol;
949 } else {
950 /* unpaint the old copy. */
951 ri->ri_crow = row;
952 ri->ri_ccol = col;
953 }
954
955 scanspan = ri->ri_stride;
956 y = ri->ri_font->fontheight * row;
957 startx = ri->ri_font->fontwidth * col;
958 height = ri->ri_font->fontheight;
959
960 p = (uint8_t *)ri->ri_bits + y * scanspan + ((startx / 32) * 4);
961 align = startx & ALIGNMASK;
962 width = ri->ri_font->fontwidth + align;
963 lmask = ALL1BITS >> align;
964 rmask = ALL1BITS << (-width & ALIGNMASK);
965 if (width <= BLITWIDTH) {
966 lmask &= rmask;
967 while (height > 0) {
968 image = P0(p);
969 P0(p) = (image & ~lmask) | ((image ^ ALL1BITS) & lmask);
970 image = P1(p);
971 P1(p) = (image & ~lmask) | ((image ^ ALL1BITS) & lmask);
972 image = P2(p);
973 P2(p) = (image & ~lmask) | ((image ^ ALL1BITS) & lmask);
974 image = P3(p);
975 P3(p) = (image & ~lmask) | ((image ^ ALL1BITS) & lmask);
976 p += scanspan;
977 height--;
978 }
979 } else {
980 uint8_t *q = p;
981
982 while (height > 0) {
983 image = P0(p);
984 P0(p) = (image & ~lmask) | ((image ^ ALL1BITS) & lmask);
985 image = P1(p);
986 P1(p) = (image & ~lmask) | ((image ^ ALL1BITS) & lmask);
987 image = P2(p);
988 P2(p) = (image & ~lmask) | ((image ^ ALL1BITS) & lmask);
989 image = P3(p);
990 P3(p) = (image & ~lmask) | ((image ^ ALL1BITS) & lmask);
991 p += BYTESDONE;
992 image = P0(p);
993 P0(p) = ((image ^ ALL1BITS) & rmask) | (image & ~rmask);
994 image = P1(p);
995 P1(p) = ((image ^ ALL1BITS) & rmask) | (image & ~rmask);
996 image = P2(p);
997 P2(p) = ((image ^ ALL1BITS) & rmask) | (image & ~rmask);
998 image = P3(p);
999 P3(p) = ((image ^ ALL1BITS) & rmask) | (image & ~rmask);
1000
1001 p = (q += scanspan);
1002 height--;
1003 }
1004 }
1005 ri->ri_flg ^= RI_CURSOR;
1006 }
1007
1008 /*
1009 * Allocate attribute. We just pack these into an integer.
1010 */
1011 static int
1012 om1_allocattr(void *id, int fg, int bg, int flags, long *attrp)
1013 {
1014
1015 if ((flags & (WSATTR_HILIT | WSATTR_BLINK |
1016 WSATTR_UNDERLINE | WSATTR_WSCOLORS)) != 0)
1017 return EINVAL;
1018 if ((flags & WSATTR_REVERSE) != 0)
1019 *attrp = 1;
1020 else
1021 *attrp = 0;
1022 return 0;
1023 }
1024
1025 static int
1026 om4_allocattr(void *id, int fg, int bg, int flags, long *attrp)
1027 {
1028
1029 if ((flags & (WSATTR_BLINK | WSATTR_UNDERLINE)) != 0)
1030 return EINVAL;
1031 if ((flags & WSATTR_WSCOLORS) == 0) {
1032 fg = WSCOL_WHITE;
1033 bg = WSCOL_BLACK;
1034 }
1035
1036 if ((flags & WSATTR_REVERSE) != 0) {
1037 int swap;
1038 swap = fg;
1039 fg = bg;
1040 bg = swap;
1041 }
1042
1043 if ((flags & WSATTR_HILIT) != 0)
1044 fg += 8;
1045
1046 *attrp = (fg << 24) | (bg << 16);
1047 return 0;
1048 }
1049
1050 static void
1051 om4_unpack_attr(long attr, int *fg, int *bg, int *underline)
1052 {
1053
1054 *fg = ((u_int)attr >> 24) & 0xf;
1055 *bg = ((u_int)attr >> 16) & 0xf;
1056 }
1057
1058 /*
1059 * Init subset of rasops(9) for omrasops.
1060 */
1061 int
1062 omrasops1_init(struct rasops_info *ri, int wantrows, int wantcols)
1063 {
1064
1065 omrasops_init(ri, wantrows, wantcols);
1066
1067 /* fill our own emulops */
1068 ri->ri_ops.cursor = om1_cursor;
1069 ri->ri_ops.mapchar = om_mapchar;
1070 ri->ri_ops.putchar = om1_putchar;
1071 ri->ri_ops.copycols = om1_copycols;
1072 ri->ri_ops.erasecols = om1_erasecols;
1073 ri->ri_ops.copyrows = om1_copyrows;
1074 ri->ri_ops.eraserows = om1_eraserows;
1075 ri->ri_ops.allocattr = om1_allocattr;
1076 ri->ri_caps = WSSCREEN_REVERSE;
1077
1078 ri->ri_flg |= RI_CFGDONE;
1079
1080 return 0;
1081 }
1082
1083 int
1084 omrasops4_init(struct rasops_info *ri, int wantrows, int wantcols)
1085 {
1086
1087 omrasops_init(ri, wantrows, wantcols);
1088
1089 /* fill our own emulops */
1090 ri->ri_ops.cursor = om4_cursor;
1091 ri->ri_ops.mapchar = om_mapchar;
1092 ri->ri_ops.putchar = om4_putchar;
1093 ri->ri_ops.copycols = om4_copycols;
1094 ri->ri_ops.erasecols = om4_erasecols;
1095 ri->ri_ops.copyrows = om4_copyrows;
1096 ri->ri_ops.eraserows = om4_eraserows;
1097 ri->ri_ops.allocattr = om4_allocattr;
1098 ri->ri_caps = WSSCREEN_HILIT | WSSCREEN_WSCOLORS | WSSCREEN_REVERSE;
1099
1100 ri->ri_flg |= RI_CFGDONE;
1101
1102 return 0;
1103 }
1104
1105 static int
1106 omrasops_init(struct rasops_info *ri, int wantrows, int wantcols)
1107 {
1108 int wsfcookie, bpp;
1109
1110 if (wantrows == 0)
1111 wantrows = 34;
1112 if (wantrows < 10)
1113 wantrows = 10;
1114 if (wantcols == 0)
1115 wantcols = 80;
1116 if (wantcols < 20)
1117 wantcols = 20;
1118
1119 /* Use default font */
1120 wsfont_init();
1121 wsfcookie = wsfont_find(NULL, 0, 0, 0, WSDISPLAY_FONTORDER_L2R,
1122 WSDISPLAY_FONTORDER_L2R, WSFONT_FIND_BITMAP);
1123 if (wsfcookie < 0)
1124 panic("%s: no font available", __func__);
1125 if (wsfont_lock(wsfcookie, &ri->ri_font))
1126 panic("%s: unable to lock font", __func__);
1127 ri->ri_wsfcookie = wsfcookie;
1128
1129 KASSERT(ri->ri_font->fontwidth > 4 && ri->ri_font->fontwidth <= 32);
1130
1131 /* all planes are independently addressed */
1132 bpp = 1;
1133
1134 /* Now constrain what they get */
1135 ri->ri_emuwidth = ri->ri_font->fontwidth * wantcols;
1136 ri->ri_emuheight = ri->ri_font->fontheight * wantrows;
1137 if (ri->ri_emuwidth > ri->ri_width)
1138 ri->ri_emuwidth = ri->ri_width;
1139 if (ri->ri_emuheight > ri->ri_height)
1140 ri->ri_emuheight = ri->ri_height;
1141
1142 /* Reduce width until aligned on a 32-bit boundary */
1143 while ((ri->ri_emuwidth * bpp & 31) != 0)
1144 ri->ri_emuwidth--;
1145
1146 ri->ri_cols = ri->ri_emuwidth / ri->ri_font->fontwidth;
1147 ri->ri_rows = ri->ri_emuheight / ri->ri_font->fontheight;
1148 ri->ri_emustride = ri->ri_emuwidth * bpp >> 3;
1149 ri->ri_delta = ri->ri_stride - ri->ri_emustride;
1150 ri->ri_ccol = 0;
1151 ri->ri_crow = 0;
1152 ri->ri_pelbytes = bpp >> 3;
1153
1154 ri->ri_xscale = (ri->ri_font->fontwidth * bpp) >> 3;
1155 ri->ri_yscale = ri->ri_font->fontheight * ri->ri_stride;
1156 ri->ri_fontscale = ri->ri_font->fontheight * ri->ri_font->stride;
1157
1158 /* Clear the entire display */
1159 if ((ri->ri_flg & RI_CLEAR) != 0)
1160 memset(ri->ri_bits, 0, ri->ri_stride * ri->ri_height);
1161
1162 /* Now centre our window if needs be */
1163 ri->ri_origbits = ri->ri_bits;
1164
1165 if ((ri->ri_flg & RI_CENTER) != 0) {
1166 ri->ri_bits += (((ri->ri_width * bpp >> 3) -
1167 ri->ri_emustride) >> 1) & ~3;
1168 ri->ri_bits += ((ri->ri_height - ri->ri_emuheight) >> 1) *
1169 ri->ri_stride;
1170 ri->ri_yorigin = (int)(ri->ri_bits - ri->ri_origbits)
1171 / ri->ri_stride;
1172 ri->ri_xorigin = (((int)(ri->ri_bits - ri->ri_origbits)
1173 % ri->ri_stride) * 8 / bpp);
1174 } else
1175 ri->ri_xorigin = ri->ri_yorigin = 0;
1176
1177 return 0;
1178 }
1179