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