1 /* $NetBSD: omrasops.c,v 1.1 2000/01/05 08:48:56 nisimura 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.1 2000/01/05 08:48:56 nisimura 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_alloc_attr __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_alloc_attr 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 } 382 383 /* 384 * Map a character. 385 */ 386 static int 387 om_mapchar(cookie, c, cp) 388 void *cookie; 389 int c; 390 u_int *cp; 391 { 392 if (c < 128) { 393 *cp = c; 394 return (5); 395 } 396 *cp = ' '; 397 return (0); 398 } 399 400 /* 401 * Position|{enable|disable} the cursor at the specified location. 402 */ 403 static void 404 om_cursor(cookie, on, row, col) 405 void *cookie; 406 int on, row, col; 407 { 408 struct rcons *rc = cookie; 409 struct raster *rap = rc->rc_sp; 410 caddr_t p; 411 int scanspan, startx, height, width, align, y; 412 u_int32_t lmask, rmask, image; 413 414 if (!on) { 415 /* make sure it's on */ 416 if ((rc->rc_bits & RC_CURSOR) == 0) 417 return; 418 419 row = *rc->rc_crowp; 420 col = *rc->rc_ccolp; 421 } else { 422 /* unpaint the old copy. */ 423 *rc->rc_crowp = row; 424 *rc->rc_ccolp = col; 425 } 426 427 scanspan = rap->linelongs * 4; 428 y = rc->rc_yorigin + rc->rc_font->height * row; 429 startx = rc->rc_xorigin + rc->rc_font->width * col; 430 height = rc->rc_font->height; 431 432 p = (caddr_t)rap->pixels + y * scanspan + ((startx / 32) * 4); 433 align = startx & ALIGNMASK; 434 width = rc->rc_font->width + align; 435 lmask = ALL1BITS >> align; 436 rmask = ALL1BITS << (-width & ALIGNMASK); 437 if (width <= BLITWIDTH) { 438 lmask &= rmask; 439 while (height > 0) { 440 image = R(p); 441 W(p) = (image & ~lmask) | ((image ^ ALL1BITS) & lmask); 442 p += scanspan; 443 height--; 444 } 445 } 446 else { 447 caddr_t q = p; 448 449 while (height > 0) { 450 image = R(p); 451 W(p) = (image & ~lmask) | ((image ^ ALL1BITS) & lmask); 452 p += BYTESDONE; 453 image = R(p); 454 W(p) = ((image ^ ALL1BITS) & rmask) | (image & ~rmask); 455 456 p = (q += scanspan); 457 height--; 458 } 459 } 460 rc->rc_bits ^= RC_CURSOR; 461 } 462 463 /* 464 * Allocate attribute. We just pack these into an integer. 465 */ 466 static int 467 om_alloc_attr(id, fg, bg, flags, attrp) 468 void *id; 469 int fg, bg, flags; 470 long *attrp; 471 { 472 if (flags & (WSATTR_HILIT | WSATTR_BLINK | 473 WSATTR_UNDERLINE | WSATTR_WSCOLORS)) 474 return (EINVAL); 475 if (flags & WSATTR_REVERSE) 476 *attrp = 1; 477 else 478 *attrp = 0; 479 return (0); 480 } 481 482 void 483 rcons_init(rc, mrow, mcol) 484 struct rcons *rc; 485 int mrow, mcol; 486 { 487 struct raster *rp = rc->rc_sp; 488 int i; 489 490 rc->rc_font = &gallant19; /* 12x22 monospacing font */ 491 492 /* Get distance to top and bottom of font from font origin */ 493 rc->rc_font_ascent = -(rc->rc_font->chars)['a'].homey; 494 495 i = rp->height / rc->rc_font->height; 496 rc->rc_maxrow = min(i, mrow); 497 498 i = rp->width / rc->rc_font->width; 499 rc->rc_maxcol = min(i, mcol); 500 501 /* Center emulator screen (but align x origin to 32 bits) */ 502 rc->rc_xorigin = 503 ((rp->width - rc->rc_maxcol * rc->rc_font->width) / 2) & ~ALIGNMASK; 504 rc->rc_yorigin = 505 (rp->height - rc->rc_maxrow * rc->rc_font->height) / 2; 506 #if 0 507 /* Raster width used for row copies */ 508 rc->rc_raswidth = rc->rc_maxcol * rc->rc_font->width; 509 if (rc->rc_raswidth & ALIGNMASK) { 510 /* Pad to 32 bits */ 511 i = (rc->rc_raswidth + ALIGNMASK) & ~ALIGNMASK; 512 /* Make sure width isn't too wide */ 513 if (rc->rc_xorigin + i <= rp->width) 514 rc->rc_raswidth = i; 515 } 516 #endif 517 rc->rc_bits = 0; 518 } 519