1 /* $NetBSD: omrasops.c,v 1.3 2002/07/04 14:43:49 junyoung 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 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 40 41 __KERNEL_RCSID(0, "$NetBSD: omrasops.c,v 1.3 2002/07/04 14:43:49 junyoung Exp $"); 42 43 /* 44 * Designed speficically for 'm68k bitorder'; 45 * - most significant byte is stored at lower address, 46 * - most significant bit is displayed at left most on screen. 47 * Implementation relys on; 48 * - every memory references is done in aligned 32bit chunk, 49 * - font glyphs are stored in 32bit padded. 50 */ 51 52 #include <sys/param.h> 53 #include <sys/systm.h> 54 #include <sys/device.h> 55 56 #include <dev/rcons/raster.h> 57 #include <dev/wscons/wscons_raster.h> 58 #include <dev/wscons/wscons_rfont.h> 59 #include <dev/wscons/wsdisplayvar.h> 60 61 void rcons_init __P((struct rcons *, int, int)); 62 63 /* wscons emulator operations */ 64 static void om_cursor __P((void *, int, int, int)); 65 static int om_mapchar __P((void *, int, unsigned int *)); 66 static void om_putchar __P((void *, int, int, u_int, long)); 67 static void om_copycols __P((void *, int, int, int, int)); 68 static void om_copyrows __P((void *, int, int, int num)); 69 static void om_erasecols __P((void *, int, int, int, long)); 70 static void om_eraserows __P((void *, int, int, long)); 71 static int om_allocattr __P((void *, int, int, int, long *)); 72 73 struct wsdisplay_emulops omfb_emulops = { 74 om_cursor, 75 om_mapchar, 76 om_putchar, 77 om_copycols, 78 om_erasecols, 79 om_copyrows, 80 om_eraserows, 81 om_allocattr 82 }; 83 84 #define ALL1BITS (~0U) 85 #define ALL0BITS (0U) 86 #define BLITWIDTH (32) 87 #define ALIGNMASK (0x1f) 88 #define BYTESDONE (4) 89 90 #define W(p) (*(u_int32_t *)(p)) 91 #define R(p) (*(u_int32_t *)((caddr_t)(p) + 0x40000)) 92 93 /* 94 * Blit a character at the specified co-ordinates. 95 */ 96 static void 97 om_putchar(cookie, row, startcol, uc, attr) 98 void *cookie; 99 int row, startcol; 100 u_int uc; 101 long attr; 102 { 103 struct rcons *rc = cookie; 104 struct raster *rap = rc->rc_sp; 105 caddr_t p; 106 int scanspan, startx, height, width, align, y; 107 u_int32_t lmask, rmask, glyph, inverse; 108 u_int32_t *g; 109 110 scanspan = rap->linelongs * 4; 111 y = rc->rc_yorigin + rc->rc_font->height * row; 112 startx = rc->rc_xorigin + rc->rc_font->width * startcol; 113 height = rc->rc_font->height; 114 g = rc->rc_font->chars[uc].r->pixels; 115 inverse = (attr != 0) ? ALL1BITS : ALL0BITS; 116 117 p = (caddr_t)rap->pixels + y * scanspan + ((startx / 32) * 4); 118 align = startx & ALIGNMASK; 119 width = rc->rc_font->width + align; 120 lmask = ALL1BITS >> align; 121 rmask = ALL1BITS << (-width & ALIGNMASK); 122 if (width <= BLITWIDTH) { 123 lmask &= rmask; 124 while (height > 0) { 125 glyph = *g; 126 glyph = (glyph >> align) ^ inverse; 127 W(p) = (R(p) & ~lmask) | (glyph & lmask); 128 p += scanspan; 129 g += 1; 130 height--; 131 } 132 } 133 else { 134 caddr_t q = p; 135 u_int32_t lhalf, rhalf; 136 137 while (height > 0) { 138 glyph = *g; 139 lhalf = (glyph >> align) ^ inverse; 140 W(p) = (R(p) & ~lmask) | (lhalf & lmask); 141 p += BYTESDONE; 142 rhalf = (glyph << (BLITWIDTH - align)) ^ inverse; 143 W(p) = (rhalf & rmask) | (R(p) & ~rmask); 144 145 p = (q += scanspan); 146 g += 1; 147 height--; 148 } 149 } 150 } 151 152 static void 153 om_erasecols(cookie, row, startcol, ncols, attr) 154 void *cookie; 155 int row, startcol, ncols; 156 long attr; 157 { 158 struct rcons *rc = cookie; 159 struct raster *rap = rc->rc_sp; 160 caddr_t p; 161 int scanspan, startx, height, width, align, w, y; 162 u_int32_t lmask, rmask, fill; 163 164 scanspan = rap->linelongs * 4; 165 y = rc->rc_yorigin + rc->rc_font->height * row; 166 startx = rc->rc_xorigin + rc->rc_font->width * startcol; 167 height = rc->rc_font->height; 168 w = rc->rc_font->width * ncols; 169 fill = (attr != 0) ? ALL1BITS : ALL0BITS; 170 171 p = (caddr_t)rap->pixels + y * scanspan + ((startx / 32) * 4); 172 align = startx & ALIGNMASK; 173 width = w + align; 174 lmask = ALL1BITS >> align; 175 rmask = ALL1BITS << (-width & ALIGNMASK); 176 if (width <= BLITWIDTH) { 177 lmask &= rmask; 178 fill &= lmask; 179 while (height > 0) { 180 W(p) = (R(p) & ~lmask) | fill; 181 p += scanspan; 182 height--; 183 } 184 } 185 else { 186 caddr_t q = p; 187 while (height > 0) { 188 W(p) = (R(p) & ~lmask) | (fill & lmask); 189 width -= 2 * BLITWIDTH; 190 while (width > 0) { 191 p += BYTESDONE; 192 W(p) = fill; 193 width -= BLITWIDTH; 194 } 195 p += BYTESDONE; 196 W(p) = (fill & rmask) | (R(p) & ~rmask); 197 198 p = (q += scanspan); 199 width = w + align; 200 height--; 201 } 202 } 203 } 204 205 static void 206 om_eraserows(cookie, startrow, nrows, attr) 207 void *cookie; 208 int startrow, nrows; 209 long attr; 210 { 211 struct rcons *rc = cookie; 212 struct raster *rap = rc->rc_sp; 213 caddr_t p, q; 214 int scanspan, starty, height, width, w; 215 u_int32_t rmask, fill; 216 217 scanspan = rap->linelongs * 4; 218 starty = rc->rc_yorigin + rc->rc_font->height * startrow; 219 height = rc->rc_font->height * nrows; 220 w = rc->rc_font->width * rc->rc_maxcol; 221 fill = (attr == 1) ? ALL1BITS : ALL0BITS; 222 223 p = (caddr_t)rap->pixels + starty * scanspan; 224 p += (rc->rc_xorigin / 32) * 4; 225 width = w; 226 rmask = ALL1BITS << (-width & ALIGNMASK); 227 q = p; 228 while (height > 0) { 229 W(p) = fill; /* always aligned */ 230 width -= 2 * BLITWIDTH; 231 while (width > 0) { 232 p += BYTESDONE; 233 W(p) = fill; 234 width -= BLITWIDTH; 235 } 236 p += BYTESDONE; 237 W(p) = (fill & rmask) | (R(p) & ~rmask); 238 p = (q += scanspan); 239 width = w; 240 height--; 241 } 242 } 243 244 static void 245 om_copyrows(cookie, srcrow, dstrow, nrows) 246 void *cookie; 247 int srcrow, dstrow, nrows; 248 { 249 struct rcons *rc = cookie; 250 struct raster *rap = rc->rc_sp; 251 caddr_t p, q; 252 int scanspan, offset, srcy, height, width, w; 253 u_int32_t rmask; 254 255 scanspan = rap->linelongs * 4; 256 height = rc->rc_font->height * nrows; 257 offset = (dstrow - srcrow) * scanspan * rc->rc_font->height; 258 srcy = rc->rc_yorigin + rc->rc_font->height * srcrow; 259 if (srcrow < dstrow && srcrow + nrows > dstrow) { 260 scanspan = -scanspan; 261 srcy += height; 262 } 263 264 p = (caddr_t)rap->pixels + srcy * (rap->linelongs * 4); 265 p += (rc->rc_xorigin / 32) * 4; 266 w = rc->rc_font->width * rc->rc_maxcol; 267 width = w; 268 rmask = ALL1BITS << (-width & ALIGNMASK); 269 q = p; 270 while (height > 0) { 271 W(p + offset) = R(p); /* always aligned */ 272 width -= 2 * BLITWIDTH; 273 while (width > 0) { 274 p += BYTESDONE; 275 W(p + offset) = R(p); 276 width -= BLITWIDTH; 277 } 278 p += BYTESDONE; 279 W(p + offset) = (R(p) & rmask) | (R(p + offset) & ~rmask); 280 281 p = (q += scanspan); 282 width = w; 283 height--; 284 } 285 } 286 287 static void 288 om_copycols(cookie, startrow, srccol, dstcol, ncols) 289 void *cookie; 290 int startrow, srccol, dstcol, ncols; 291 { 292 struct rcons *rc = cookie; 293 struct raster *rap = rc->rc_sp; 294 caddr_t sp, dp, basep; 295 int scanspan, height, width, align, shift, w, y, srcx, dstx; 296 u_int32_t lmask, rmask; 297 298 scanspan = rap->linelongs * 4; 299 y = rc->rc_yorigin + rc->rc_font->height * startrow; 300 srcx = rc->rc_xorigin + rc->rc_font->width * srccol; 301 dstx = rc->rc_xorigin + rc->rc_font->width * dstcol; 302 height = rc->rc_font->height; 303 w = rc->rc_font->width * ncols; 304 basep = (caddr_t)rap->pixels + y * scanspan; 305 306 align = shift = srcx & ALIGNMASK; 307 width = w + align; 308 align = dstx & ALIGNMASK; 309 lmask = ALL1BITS >> align; 310 rmask = ALL1BITS << (-(w + align) & ALIGNMASK); 311 shift = align - shift; 312 sp = basep + (srcx / 32) * 4; 313 dp = basep + (dstx / 32) * 4; 314 315 if (shift != 0) 316 goto hardluckalignment; 317 318 /* alignments comfortably match */ 319 if (width <= BLITWIDTH) { 320 lmask &= rmask; 321 while (height > 0) { 322 W(dp) = (R(dp) & ~lmask) | (R(sp) & lmask); 323 dp += scanspan; 324 sp += scanspan; 325 height--; 326 } 327 } 328 /* copy forward (left-to-right) */ 329 else if (dstcol < srccol || srccol + ncols < dstcol) { 330 caddr_t sq = sp, dq = dp; 331 332 w = width; 333 while (height > 0) { 334 W(dp) = (R(dp) & ~lmask) | (R(sp) & lmask); 335 width -= 2 * BLITWIDTH; 336 while (width > 0) { 337 sp += BYTESDONE; 338 dp += BYTESDONE; 339 W(dp) = R(sp); 340 width -= BLITWIDTH; 341 } 342 sp += BYTESDONE; 343 dp += BYTESDONE; 344 W(dp) = (R(sp) & rmask) | (R(dp) & ~rmask); 345 sp = (sq += scanspan); 346 dp = (dq += scanspan); 347 width = w; 348 height--; 349 } 350 } 351 /* copy backward (right-to-left) */ 352 else { 353 caddr_t sq, dq; 354 355 sq = (sp += width / 32 * 4); 356 dq = (dp += width / 32 * 4); 357 w = width; 358 while (height > 0) { 359 W(dp) = (R(sp) & rmask) | (R(dp) & ~rmask); 360 width -= 2 * BLITWIDTH; 361 while (width > 0) { 362 sp -= BYTESDONE; 363 dp -= BYTESDONE; 364 W(dp) = R(sp); 365 width -= BLITWIDTH; 366 } 367 sp -= BYTESDONE; 368 dp -= BYTESDONE; 369 W(dp) = (R(dp) & ~lmask) | (R(sp) & lmask); 370 371 sp = (sq += scanspan); 372 dp = (dq += scanspan); 373 width = w; 374 height--; 375 } 376 } 377 return; 378 379 hardluckalignment: 380 /* alignments painfully disagree */ 381 return; 382 } 383 384 /* 385 * Map a character. 386 */ 387 static int 388 om_mapchar(cookie, c, cp) 389 void *cookie; 390 int c; 391 u_int *cp; 392 { 393 if (c < 128) { 394 *cp = c; 395 return (5); 396 } 397 *cp = ' '; 398 return (0); 399 } 400 401 /* 402 * Position|{enable|disable} the cursor at the specified location. 403 */ 404 static void 405 om_cursor(cookie, on, row, col) 406 void *cookie; 407 int on, row, col; 408 { 409 struct rcons *rc = cookie; 410 struct raster *rap = rc->rc_sp; 411 caddr_t p; 412 int scanspan, startx, height, width, align, y; 413 u_int32_t lmask, rmask, image; 414 415 if (!on) { 416 /* make sure it's on */ 417 if ((rc->rc_bits & RC_CURSOR) == 0) 418 return; 419 420 row = *rc->rc_crowp; 421 col = *rc->rc_ccolp; 422 } else { 423 /* unpaint the old copy. */ 424 *rc->rc_crowp = row; 425 *rc->rc_ccolp = col; 426 } 427 428 scanspan = rap->linelongs * 4; 429 y = rc->rc_yorigin + rc->rc_font->height * row; 430 startx = rc->rc_xorigin + rc->rc_font->width * col; 431 height = rc->rc_font->height; 432 433 p = (caddr_t)rap->pixels + y * scanspan + ((startx / 32) * 4); 434 align = startx & ALIGNMASK; 435 width = rc->rc_font->width + align; 436 lmask = ALL1BITS >> align; 437 rmask = ALL1BITS << (-width & ALIGNMASK); 438 if (width <= BLITWIDTH) { 439 lmask &= rmask; 440 while (height > 0) { 441 image = R(p); 442 W(p) = (image & ~lmask) | ((image ^ ALL1BITS) & lmask); 443 p += scanspan; 444 height--; 445 } 446 } 447 else { 448 caddr_t q = p; 449 450 while (height > 0) { 451 image = R(p); 452 W(p) = (image & ~lmask) | ((image ^ ALL1BITS) & lmask); 453 p += BYTESDONE; 454 image = R(p); 455 W(p) = ((image ^ ALL1BITS) & rmask) | (image & ~rmask); 456 457 p = (q += scanspan); 458 height--; 459 } 460 } 461 rc->rc_bits ^= RC_CURSOR; 462 } 463 464 /* 465 * Allocate attribute. We just pack these into an integer. 466 */ 467 static int 468 om_allocattr(id, fg, bg, flags, attrp) 469 void *id; 470 int fg, bg, flags; 471 long *attrp; 472 { 473 if (flags & (WSATTR_HILIT | WSATTR_BLINK | 474 WSATTR_UNDERLINE | WSATTR_WSCOLORS)) 475 return (EINVAL); 476 if (flags & WSATTR_REVERSE) 477 *attrp = 1; 478 else 479 *attrp = 0; 480 return (0); 481 } 482 483 void 484 rcons_init(rc, mrow, mcol) 485 struct rcons *rc; 486 int mrow, mcol; 487 { 488 struct raster *rp = rc->rc_sp; 489 int i; 490 491 rc->rc_font = &gallant19; /* 12x22 monospacing font */ 492 493 /* Get distance to top and bottom of font from font origin */ 494 rc->rc_font_ascent = -(rc->rc_font->chars)['a'].homey; 495 496 i = rp->height / rc->rc_font->height; 497 rc->rc_maxrow = min(i, mrow); 498 499 i = rp->width / rc->rc_font->width; 500 rc->rc_maxcol = min(i, mcol); 501 502 /* Center emulator screen (but align x origin to 32 bits) */ 503 rc->rc_xorigin = 504 ((rp->width - rc->rc_maxcol * rc->rc_font->width) / 2) & ~ALIGNMASK; 505 rc->rc_yorigin = 506 (rp->height - rc->rc_maxrow * rc->rc_font->height) / 2; 507 #if 0 508 /* Raster width used for row copies */ 509 rc->rc_raswidth = rc->rc_maxcol * rc->rc_font->width; 510 if (rc->rc_raswidth & ALIGNMASK) { 511 /* Pad to 32 bits */ 512 i = (rc->rc_raswidth + ALIGNMASK) & ~ALIGNMASK; 513 /* Make sure width isn't too wide */ 514 if (rc->rc_xorigin + i <= rp->width) 515 rc->rc_raswidth = i; 516 } 517 #endif 518 rc->rc_bits = 0; 519 } 520