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