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