1 /* $NetBSD: omrasops.c,v 1.6 2008/04/28 20:23:26 martin 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.6 2008/04/28 20:23:26 martin 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 relys on; 41 * - every memory references is done in aligned 32bit chunk, 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/rcons/raster.h> 50 #include <dev/wscons/wscons_raster.h> 51 #include <dev/wscons/wscons_rfont.h> 52 #include <dev/wscons/wsdisplayvar.h> 53 54 void rcons_init __P((struct rcons *, int, int)); 55 56 /* wscons emulator operations */ 57 static void om_cursor __P((void *, int, int, int)); 58 static int om_mapchar __P((void *, int, unsigned int *)); 59 static void om_putchar __P((void *, int, int, u_int, long)); 60 static void om_copycols __P((void *, int, int, int, int)); 61 static void om_copyrows __P((void *, int, int, int num)); 62 static void om_erasecols __P((void *, int, int, int, long)); 63 static void om_eraserows __P((void *, int, int, long)); 64 static int om_allocattr __P((void *, int, int, int, long *)); 65 66 struct wsdisplay_emulops omfb_emulops = { 67 om_cursor, 68 om_mapchar, 69 om_putchar, 70 om_copycols, 71 om_erasecols, 72 om_copyrows, 73 om_eraserows, 74 om_allocattr 75 }; 76 77 #define ALL1BITS (~0U) 78 #define ALL0BITS (0U) 79 #define BLITWIDTH (32) 80 #define ALIGNMASK (0x1f) 81 #define BYTESDONE (4) 82 83 #define W(p) (*(u_int32_t *)(p)) 84 #define R(p) (*(u_int32_t *)((uint8_t *)(p) + 0x40000)) 85 86 /* 87 * Blit a character at the specified co-ordinates. 88 */ 89 static void 90 om_putchar(cookie, row, startcol, uc, attr) 91 void *cookie; 92 int row, startcol; 93 u_int uc; 94 long attr; 95 { 96 struct rcons *rc = cookie; 97 struct raster *rap = rc->rc_sp; 98 uint8_t *p; 99 int scanspan, startx, height, width, align, y; 100 u_int32_t lmask, rmask, glyph, inverse; 101 u_int32_t *g; 102 103 scanspan = rap->linelongs * 4; 104 y = rc->rc_yorigin + rc->rc_font->height * row; 105 startx = rc->rc_xorigin + rc->rc_font->width * startcol; 106 height = rc->rc_font->height; 107 g = rc->rc_font->chars[uc].r->pixels; 108 inverse = (attr != 0) ? ALL1BITS : ALL0BITS; 109 110 p = (uint8_t *)rap->pixels + y * scanspan + ((startx / 32) * 4); 111 align = startx & ALIGNMASK; 112 width = rc->rc_font->width + align; 113 lmask = ALL1BITS >> align; 114 rmask = ALL1BITS << (-width & ALIGNMASK); 115 if (width <= BLITWIDTH) { 116 lmask &= rmask; 117 while (height > 0) { 118 glyph = *g; 119 glyph = (glyph >> align) ^ inverse; 120 W(p) = (R(p) & ~lmask) | (glyph & lmask); 121 p += scanspan; 122 g += 1; 123 height--; 124 } 125 } 126 else { 127 uint8_t *q = p; 128 u_int32_t lhalf, rhalf; 129 130 while (height > 0) { 131 glyph = *g; 132 lhalf = (glyph >> align) ^ inverse; 133 W(p) = (R(p) & ~lmask) | (lhalf & lmask); 134 p += BYTESDONE; 135 rhalf = (glyph << (BLITWIDTH - align)) ^ inverse; 136 W(p) = (rhalf & rmask) | (R(p) & ~rmask); 137 138 p = (q += scanspan); 139 g += 1; 140 height--; 141 } 142 } 143 } 144 145 static void 146 om_erasecols(cookie, row, startcol, ncols, attr) 147 void *cookie; 148 int row, startcol, ncols; 149 long attr; 150 { 151 struct rcons *rc = cookie; 152 struct raster *rap = rc->rc_sp; 153 uint8_t *p; 154 int scanspan, startx, height, width, align, w, y; 155 u_int32_t lmask, rmask, fill; 156 157 scanspan = rap->linelongs * 4; 158 y = rc->rc_yorigin + rc->rc_font->height * row; 159 startx = rc->rc_xorigin + rc->rc_font->width * startcol; 160 height = rc->rc_font->height; 161 w = rc->rc_font->width * ncols; 162 fill = (attr != 0) ? ALL1BITS : ALL0BITS; 163 164 p = (uint8_t *)rap->pixels + y * scanspan + ((startx / 32) * 4); 165 align = startx & ALIGNMASK; 166 width = w + align; 167 lmask = ALL1BITS >> align; 168 rmask = ALL1BITS << (-width & ALIGNMASK); 169 if (width <= BLITWIDTH) { 170 lmask &= rmask; 171 fill &= lmask; 172 while (height > 0) { 173 W(p) = (R(p) & ~lmask) | fill; 174 p += scanspan; 175 height--; 176 } 177 } 178 else { 179 uint8_t *q = p; 180 while (height > 0) { 181 W(p) = (R(p) & ~lmask) | (fill & lmask); 182 width -= 2 * BLITWIDTH; 183 while (width > 0) { 184 p += BYTESDONE; 185 W(p) = fill; 186 width -= BLITWIDTH; 187 } 188 p += BYTESDONE; 189 W(p) = (fill & rmask) | (R(p) & ~rmask); 190 191 p = (q += scanspan); 192 width = w + align; 193 height--; 194 } 195 } 196 } 197 198 static void 199 om_eraserows(cookie, startrow, nrows, attr) 200 void *cookie; 201 int startrow, nrows; 202 long attr; 203 { 204 struct rcons *rc = cookie; 205 struct raster *rap = rc->rc_sp; 206 uint8_t *p, *q; 207 int scanspan, starty, height, width, w; 208 u_int32_t rmask, fill; 209 210 scanspan = rap->linelongs * 4; 211 starty = rc->rc_yorigin + rc->rc_font->height * startrow; 212 height = rc->rc_font->height * nrows; 213 w = rc->rc_font->width * rc->rc_maxcol; 214 fill = (attr == 1) ? ALL1BITS : ALL0BITS; 215 216 p = (uint8_t *)rap->pixels + starty * scanspan; 217 p += (rc->rc_xorigin / 32) * 4; 218 width = w; 219 rmask = ALL1BITS << (-width & ALIGNMASK); 220 q = p; 221 while (height > 0) { 222 W(p) = fill; /* always aligned */ 223 width -= 2 * BLITWIDTH; 224 while (width > 0) { 225 p += BYTESDONE; 226 W(p) = fill; 227 width -= BLITWIDTH; 228 } 229 p += BYTESDONE; 230 W(p) = (fill & rmask) | (R(p) & ~rmask); 231 p = (q += scanspan); 232 width = w; 233 height--; 234 } 235 } 236 237 static void 238 om_copyrows(cookie, srcrow, dstrow, nrows) 239 void *cookie; 240 int srcrow, dstrow, nrows; 241 { 242 struct rcons *rc = cookie; 243 struct raster *rap = rc->rc_sp; 244 uint8_t *p, *q; 245 int scanspan, offset, srcy, height, width, w; 246 u_int32_t rmask; 247 248 scanspan = rap->linelongs * 4; 249 height = rc->rc_font->height * nrows; 250 offset = (dstrow - srcrow) * scanspan * rc->rc_font->height; 251 srcy = rc->rc_yorigin + rc->rc_font->height * srcrow; 252 if (srcrow < dstrow && srcrow + nrows > dstrow) { 253 scanspan = -scanspan; 254 srcy += height; 255 } 256 257 p = (uint8_t *)rap->pixels + srcy * (rap->linelongs * 4); 258 p += (rc->rc_xorigin / 32) * 4; 259 w = rc->rc_font->width * rc->rc_maxcol; 260 width = w; 261 rmask = ALL1BITS << (-width & ALIGNMASK); 262 q = p; 263 while (height > 0) { 264 W(p + offset) = R(p); /* always aligned */ 265 width -= 2 * BLITWIDTH; 266 while (width > 0) { 267 p += BYTESDONE; 268 W(p + offset) = R(p); 269 width -= BLITWIDTH; 270 } 271 p += BYTESDONE; 272 W(p + offset) = (R(p) & rmask) | (R(p + offset) & ~rmask); 273 274 p = (q += scanspan); 275 width = w; 276 height--; 277 } 278 } 279 280 static void 281 om_copycols(cookie, startrow, srccol, dstcol, ncols) 282 void *cookie; 283 int startrow, srccol, dstcol, ncols; 284 { 285 struct rcons *rc = cookie; 286 struct raster *rap = rc->rc_sp; 287 uint8_t *sp, *dp, *basep; 288 int scanspan, height, width, align, shift, w, y, srcx, dstx; 289 u_int32_t lmask, rmask; 290 291 scanspan = rap->linelongs * 4; 292 y = rc->rc_yorigin + rc->rc_font->height * startrow; 293 srcx = rc->rc_xorigin + rc->rc_font->width * srccol; 294 dstx = rc->rc_xorigin + rc->rc_font->width * dstcol; 295 height = rc->rc_font->height; 296 w = rc->rc_font->width * ncols; 297 basep = (uint8_t *)rap->pixels + y * scanspan; 298 299 align = shift = srcx & ALIGNMASK; 300 width = w + align; 301 align = dstx & ALIGNMASK; 302 lmask = ALL1BITS >> align; 303 rmask = ALL1BITS << (-(w + align) & ALIGNMASK); 304 shift = align - shift; 305 sp = basep + (srcx / 32) * 4; 306 dp = basep + (dstx / 32) * 4; 307 308 if (shift != 0) 309 goto hardluckalignment; 310 311 /* alignments comfortably match */ 312 if (width <= BLITWIDTH) { 313 lmask &= rmask; 314 while (height > 0) { 315 W(dp) = (R(dp) & ~lmask) | (R(sp) & lmask); 316 dp += scanspan; 317 sp += scanspan; 318 height--; 319 } 320 } 321 /* copy forward (left-to-right) */ 322 else if (dstcol < srccol || srccol + ncols < dstcol) { 323 uint8_t *sq = sp, *dq = dp; 324 325 w = width; 326 while (height > 0) { 327 W(dp) = (R(dp) & ~lmask) | (R(sp) & lmask); 328 width -= 2 * BLITWIDTH; 329 while (width > 0) { 330 sp += BYTESDONE; 331 dp += BYTESDONE; 332 W(dp) = R(sp); 333 width -= BLITWIDTH; 334 } 335 sp += BYTESDONE; 336 dp += BYTESDONE; 337 W(dp) = (R(sp) & rmask) | (R(dp) & ~rmask); 338 sp = (sq += scanspan); 339 dp = (dq += scanspan); 340 width = w; 341 height--; 342 } 343 } 344 /* copy backward (right-to-left) */ 345 else { 346 uint8_t *sq, *dq; 347 348 sq = (sp += width / 32 * 4); 349 dq = (dp += width / 32 * 4); 350 w = width; 351 while (height > 0) { 352 W(dp) = (R(sp) & rmask) | (R(dp) & ~rmask); 353 width -= 2 * BLITWIDTH; 354 while (width > 0) { 355 sp -= BYTESDONE; 356 dp -= BYTESDONE; 357 W(dp) = R(sp); 358 width -= BLITWIDTH; 359 } 360 sp -= BYTESDONE; 361 dp -= BYTESDONE; 362 W(dp) = (R(dp) & ~lmask) | (R(sp) & lmask); 363 364 sp = (sq += scanspan); 365 dp = (dq += scanspan); 366 width = w; 367 height--; 368 } 369 } 370 return; 371 372 hardluckalignment: 373 /* alignments painfully disagree */ 374 return; 375 } 376 377 /* 378 * Map a character. 379 */ 380 static int 381 om_mapchar(cookie, c, cp) 382 void *cookie; 383 int c; 384 u_int *cp; 385 { 386 if (c < 128) { 387 *cp = c; 388 return (5); 389 } 390 *cp = ' '; 391 return (0); 392 } 393 394 /* 395 * Position|{enable|disable} the cursor at the specified location. 396 */ 397 static void 398 om_cursor(cookie, on, row, col) 399 void *cookie; 400 int on, row, col; 401 { 402 struct rcons *rc = cookie; 403 struct raster *rap = rc->rc_sp; 404 uint8_t *p; 405 int scanspan, startx, height, width, align, y; 406 u_int32_t lmask, rmask, image; 407 408 if (!on) { 409 /* make sure it's on */ 410 if ((rc->rc_bits & RC_CURSOR) == 0) 411 return; 412 413 row = *rc->rc_crowp; 414 col = *rc->rc_ccolp; 415 } else { 416 /* unpaint the old copy. */ 417 *rc->rc_crowp = row; 418 *rc->rc_ccolp = col; 419 } 420 421 scanspan = rap->linelongs * 4; 422 y = rc->rc_yorigin + rc->rc_font->height * row; 423 startx = rc->rc_xorigin + rc->rc_font->width * col; 424 height = rc->rc_font->height; 425 426 p = (uint8_t *)rap->pixels + y * scanspan + ((startx / 32) * 4); 427 align = startx & ALIGNMASK; 428 width = rc->rc_font->width + align; 429 lmask = ALL1BITS >> align; 430 rmask = ALL1BITS << (-width & ALIGNMASK); 431 if (width <= BLITWIDTH) { 432 lmask &= rmask; 433 while (height > 0) { 434 image = R(p); 435 W(p) = (image & ~lmask) | ((image ^ ALL1BITS) & lmask); 436 p += scanspan; 437 height--; 438 } 439 } 440 else { 441 uint8_t *q = p; 442 443 while (height > 0) { 444 image = R(p); 445 W(p) = (image & ~lmask) | ((image ^ ALL1BITS) & lmask); 446 p += BYTESDONE; 447 image = R(p); 448 W(p) = ((image ^ ALL1BITS) & rmask) | (image & ~rmask); 449 450 p = (q += scanspan); 451 height--; 452 } 453 } 454 rc->rc_bits ^= RC_CURSOR; 455 } 456 457 /* 458 * Allocate attribute. We just pack these into an integer. 459 */ 460 static int 461 om_allocattr(id, fg, bg, flags, attrp) 462 void *id; 463 int fg, bg, flags; 464 long *attrp; 465 { 466 if (flags & (WSATTR_HILIT | WSATTR_BLINK | 467 WSATTR_UNDERLINE | WSATTR_WSCOLORS)) 468 return (EINVAL); 469 if (flags & WSATTR_REVERSE) 470 *attrp = 1; 471 else 472 *attrp = 0; 473 return (0); 474 } 475 476 void 477 rcons_init(rc, mrow, mcol) 478 struct rcons *rc; 479 int mrow, mcol; 480 { 481 struct raster *rp = rc->rc_sp; 482 int i; 483 484 rc->rc_font = &gallant19; /* 12x22 monospacing font */ 485 486 /* Get distance to top and bottom of font from font origin */ 487 rc->rc_font_ascent = -(rc->rc_font->chars)['a'].homey; 488 489 i = rp->height / rc->rc_font->height; 490 rc->rc_maxrow = min(i, mrow); 491 492 i = rp->width / rc->rc_font->width; 493 rc->rc_maxcol = min(i, mcol); 494 495 /* Center emulator screen (but align x origin to 32 bits) */ 496 rc->rc_xorigin = 497 ((rp->width - rc->rc_maxcol * rc->rc_font->width) / 2) & ~ALIGNMASK; 498 rc->rc_yorigin = 499 (rp->height - rc->rc_maxrow * rc->rc_font->height) / 2; 500 #if 0 501 /* Raster width used for row copies */ 502 rc->rc_raswidth = rc->rc_maxcol * rc->rc_font->width; 503 if (rc->rc_raswidth & ALIGNMASK) { 504 /* Pad to 32 bits */ 505 i = (rc->rc_raswidth + ALIGNMASK) & ~ALIGNMASK; 506 /* Make sure width isn't too wide */ 507 if (rc->rc_xorigin + i <= rp->width) 508 rc->rc_raswidth = i; 509 } 510 #endif 511 rc->rc_bits = 0; 512 } 513