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