1 /* $NetBSD: ite_cc.c,v 1.47 2023/01/06 10:28:28 tsutsui Exp $ */ 2 3 /* 4 * Copyright (c) 1996 Leo Weppelman 5 * Copyright (c) 1994 Christian E. Hopps 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by Christian E. Hopps. 19 * 4. The name of the author may not be used to endorse or promote products 20 * derived from this software without specific prior written permission 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include <sys/cdefs.h> 35 __KERNEL_RCSID(0, "$NetBSD: ite_cc.c,v 1.47 2023/01/06 10:28:28 tsutsui Exp $"); 36 37 #include <sys/param.h> 38 #include <sys/conf.h> 39 #include <sys/proc.h> 40 #include <sys/ioctl.h> 41 #include <sys/tty.h> 42 #include <sys/systm.h> 43 #include <sys/queue.h> 44 #include <sys/termios.h> 45 #include <sys/malloc.h> 46 #include <sys/device.h> 47 #include <sys/device_impl.h> /* XXX autoconf abuse */ 48 #include <dev/cons.h> 49 #include <machine/cpu.h> 50 #include <atari/atari/device.h> 51 #include <atari/dev/itevar.h> 52 #include <atari/dev/iteioctl.h> 53 #include <atari/dev/grfioctl.h> 54 #include <atari/dev/grfabs_reg.h> 55 #include <atari/dev/grfvar.h> 56 #include <atari/dev/font.h> 57 #include <atari/dev/viewioctl.h> 58 #include <atari/dev/viewvar.h> 59 60 #include "grfcc.h" 61 62 /* 63 * This is what ip->priv points to; 64 * it contains local variables for custom-chip ites. 65 */ 66 struct ite_priv { 67 u_char **row_ptr; /* array of pointers into the bitmap */ 68 u_long row_bytes; 69 u_long cursor_opt; 70 u_short *column_offset; /* array of offsets for columns */ 71 u_int row_offset; /* the row offset */ 72 u_short width; /* the bitmap width */ 73 u_short underline; /* where the underline goes */ 74 u_short ft_x; /* the font width */ 75 u_short ft_y; /* the font height */ 76 u_char *font_cell[256];/* the font pointer */ 77 }; 78 typedef struct ite_priv ipriv_t; 79 80 /* 81 * We need the following space to get an ite-console setup before 82 * the VM-system is brought up. We setup for a 1280x960 monitor with 83 * an 8x8 font. 84 */ 85 #define CONS_MAXROW 120 /* Max. number of rows on console */ 86 #define CONS_MAXCOL 160 /* Max. number of columns on console */ 87 static u_short con_columns[CONS_MAXCOL]; 88 static u_char *con_rows[CONS_MAXROW]; 89 static ipriv_t con_ipriv; 90 91 extern font_info font_info_8x8; 92 extern font_info font_info_8x16; 93 94 static void view_init(struct ite_softc *); 95 static void view_deinit(struct ite_softc *); 96 static int itecc_ioctl(struct ite_softc *, u_long, void *, int, 97 struct lwp *); 98 static int ite_newsize(struct ite_softc *, struct itewinsize *); 99 static void cursor32(struct ite_softc *, int); 100 static void putc8(struct ite_softc *, int, int, int, int); 101 static void clear8(struct ite_softc *, int, int, int, int); 102 static void scroll8(struct ite_softc *, int, int, int, int); 103 static void scrollbmap(bmap_t *, u_short, u_short, u_short, u_short, 104 short, short); 105 106 /* 107 * grfcc config stuff 108 */ 109 static void grfccattach(device_t, device_t, void *); 110 static int grfccmatch(device_t, cfdata_t, void *); 111 static int grfccprint(void *, const char *); 112 113 CFATTACH_DECL_NEW(grfcc, sizeof(struct grf_softc), 114 grfccmatch, grfccattach, NULL, NULL); 115 116 /* 117 * only used in console init. 118 */ 119 static struct cfdata *cfdata_grf = NULL; 120 121 /* 122 * Probe functions we can use: 123 */ 124 #ifdef TT_VIDEO 125 void tt_probe_video(MODES *); 126 #endif /* TT_VIDEO */ 127 #ifdef FALCON_VIDEO 128 void falcon_probe_video(MODES *); 129 #endif /* FALCON_VIDEO */ 130 131 static int 132 grfccmatch(device_t parent, cfdata_t cf, void *aux) 133 { 134 static int did_consinit = 0; 135 static int must_probe = 1; 136 grf_auxp_t *grf_auxp = aux; 137 extern const struct cdevsw view_cdevsw; 138 139 if (must_probe) { 140 /* 141 * Check if the layers we depend on exist 142 */ 143 if (!(machineid & (ATARI_TT|ATARI_FALCON))) 144 return 0; 145 #ifdef TT_VIDEO 146 if ((machineid & ATARI_TT) && !grfabs_probe(&tt_probe_video)) 147 return 0; 148 #endif /* TT_VIDEO */ 149 #ifdef FALCON_VIDEO 150 if ((machineid & ATARI_FALCON) && 151 !grfabs_probe(&falcon_probe_video)) 152 return 0; 153 #endif /* FALCON_VIDEO */ 154 155 viewprobe(); 156 must_probe = 0; 157 } 158 159 if (atari_realconfig == 0) { 160 /* 161 * Early console init. Only match first unit. 162 */ 163 if (did_consinit) 164 return 0; 165 if ((*view_cdevsw.d_open)(cf->cf_unit, 0, 0, NULL)) 166 return 0; 167 cfdata_grf = cf; 168 did_consinit = 1; 169 return 1; 170 } 171 172 /* 173 * Normal config. When we are called directly from the grfbus, 174 * we only match the first unit. The attach function will call us for 175 * the other configured units. 176 */ 177 if (grf_auxp->from_bus_match && (did_consinit > 1)) 178 return 0; 179 180 if (!grf_auxp->from_bus_match && (grf_auxp->unit != cf->cf_unit)) 181 return 0; 182 183 /* 184 * Final constraint: each grf needs a view.... 185 */ 186 if ((cfdata_grf == NULL) || (did_consinit > 1)) { 187 if ((*view_cdevsw.d_open)(cf->cf_unit, 0, 0, NULL)) 188 return 0; 189 } 190 did_consinit = 2; 191 return 1; 192 } 193 194 /* 195 * attach: initialize the grf-structure and try to attach an ite to us. 196 * note : self is NULL during early console init. 197 */ 198 static void 199 grfccattach(device_t parent, device_t self, void *aux) 200 { 201 static struct grf_softc congrf; 202 static int first_attach = 1; 203 grf_auxp_t *grf_bus_auxp = aux; 204 grf_auxp_t grf_auxp; 205 struct grf_softc *sc; 206 int maj; 207 extern const struct cdevsw grf_cdevsw; 208 209 /* 210 * find our major device number 211 */ 212 maj = cdevsw_lookup_major(&grf_cdevsw); 213 214 /* 215 * Handle exception case: early console init 216 */ 217 if (self == NULL) { 218 struct device itedev; 219 220 memset(&itedev, 0, sizeof(itedev)); 221 itedev.dv_private = &congrf; 222 223 congrf.g_unit = cfdata_grf->cf_unit; 224 congrf.g_grfdev = makedev(maj, congrf.g_unit); 225 congrf.g_itedev = (dev_t)-1; 226 congrf.g_flags = GF_ALIVE; 227 congrf.g_mode = grf_mode; 228 congrf.g_conpri = grfcc_cnprobe(); 229 congrf.g_viewdev = congrf.g_unit; 230 grfcc_iteinit(&congrf); 231 grf_viewsync(&congrf); 232 233 /* Attach console ite */ 234 atari_config_found(cfdata_grf, &itedev, &congrf, grfccprint, 235 CFARGS_NONE); 236 return; 237 } 238 239 sc = device_private(self); 240 sc->g_device = self; 241 sc->g_unit = device_unit(self); 242 grfsp[sc->g_unit] = sc; 243 244 if ((cfdata_grf != NULL) && (sc->g_unit == congrf.g_unit)) { 245 /* 246 * We inited earlier just copy the info, take care 247 * not to copy the device struct though. 248 */ 249 memcpy(&sc->g_display, &congrf.g_display, 250 (char *)&sc[1] - (char *)&sc->g_display); 251 } else { 252 sc->g_grfdev = makedev(maj, sc->g_unit); 253 sc->g_itedev = (dev_t)-1; 254 sc->g_flags = GF_ALIVE; 255 sc->g_mode = grf_mode; 256 sc->g_conpri = 0; 257 sc->g_viewdev = sc->g_unit; 258 grfcc_iteinit(sc); 259 grf_viewsync(sc); 260 } 261 262 aprint_normal(": width %d height %d", sc->g_display.gd_dwidth, 263 sc->g_display.gd_dheight); 264 if (sc->g_display.gd_colors == 2) 265 aprint_normal(" monochrome\n"); 266 else 267 aprint_normal(" colors %d\n", sc->g_display.gd_colors); 268 269 /* 270 * try and attach an ite 271 */ 272 config_found(self, sc /* XXX */, grfccprint, CFARGS_NONE); 273 274 /* 275 * If attaching the first unit, go ahead and 'find' the rest of us 276 */ 277 if (first_attach) { 278 first_attach = 0; 279 grf_auxp.from_bus_match = 0; 280 for (grf_auxp.unit=1; grf_auxp.unit < NGRFCC; grf_auxp.unit++) { 281 config_found(parent, &grf_auxp, grf_bus_auxp->busprint, 282 CFARGS_NONE); 283 } 284 } 285 } 286 287 static int 288 grfccprint(void *aux, const char *pnp) 289 { 290 291 if (pnp) 292 aprint_normal("ite at %s", pnp); 293 return UNCONF; 294 } 295 296 /* 297 * called from grf_cc to return console priority 298 */ 299 int 300 grfcc_cnprobe(void) 301 { 302 return CN_INTERNAL; 303 } 304 /* 305 * called from grf_cc to init ite portion of 306 * grf_softc struct 307 */ 308 void 309 grfcc_iteinit(struct grf_softc *sc) 310 { 311 312 sc->g_itecursor = cursor32; 313 sc->g_iteputc = putc8; 314 sc->g_iteclear = clear8; 315 sc->g_itescroll = scroll8; 316 sc->g_iteinit = view_init; 317 sc->g_itedeinit = view_deinit; 318 } 319 320 static void 321 view_deinit(struct ite_softc *ip) 322 { 323 ip->flags &= ~ITE_INITED; 324 } 325 326 static void 327 view_init(register struct ite_softc *ip) 328 { 329 struct itewinsize wsz; 330 ipriv_t *cci; 331 332 if ((cci = ip->priv) != NULL) 333 return; 334 335 ip->itexx_ioctl = itecc_ioctl; 336 337 #if defined(KFONT_8X8) 338 ip->font = font_info_8x8; 339 #else 340 ip->font = font_info_8x16; 341 #endif 342 343 /* Find the correct set of rendering routines for this font. */ 344 if (ip->font.width != 8) 345 panic("kernel font size not supported"); 346 347 if (!atari_realconfig) 348 ip->priv = cci = &con_ipriv; 349 else 350 ip->priv = cci = malloc(sizeof(*cci), M_DEVBUF, M_WAITOK); 351 if (cci == NULL) 352 panic("No memory for ite-view"); 353 memset(cci, 0, sizeof(*cci)); 354 355 cci->cursor_opt = 0; 356 cci->row_ptr = NULL; 357 cci->column_offset = NULL; 358 359 wsz.x = ite_default_x; 360 wsz.y = ite_default_y; 361 wsz.width = ite_default_width; 362 wsz.height = ite_default_height; 363 wsz.depth = ite_default_depth; 364 365 ite_newsize (ip, &wsz); 366 367 /* 368 * Only console will be turned on by default.. 369 */ 370 if (ip->flags & ITE_ISCONS) 371 ip->grf->g_mode(ip->grf, GM_GRFON, NULL, 0, 0); 372 } 373 374 static int 375 ite_newsize(struct ite_softc *ip, struct itewinsize *winsz) 376 { 377 struct view_size vs; 378 ipriv_t *cci = ip->priv; 379 u_long i, j; 380 int error = 0; 381 view_t *view; 382 extern const struct cdevsw view_cdevsw; 383 384 vs.x = winsz->x; 385 vs.y = winsz->y; 386 vs.width = winsz->width; 387 vs.height = winsz->height; 388 vs.depth = winsz->depth; 389 390 error = (*view_cdevsw.d_ioctl)(ip->grf->g_viewdev, VIOCSSIZE, 391 (void *)&vs, 0, NOLWP); 392 view = viewview(ip->grf->g_viewdev); 393 394 /* 395 * Reinitialize our structs 396 */ 397 ip->cols = view->display.width / ip->font.width; 398 ip->rows = view->display.height / ip->font.height; 399 400 /* 401 * save new values so that future opens use them 402 * this may not be correct when we implement Virtual Consoles 403 */ 404 ite_default_height = view->display.height; 405 ite_default_width = view->display.width; 406 ite_default_x = view->display.x; 407 ite_default_y = view->display.y; 408 ite_default_depth = view->bitmap->depth; 409 410 if (cci->row_ptr && (cci->row_ptr != con_rows)) { 411 free(cci->row_ptr, M_DEVBUF); 412 cci->row_ptr = NULL; 413 } 414 if (cci->column_offset && (cci->column_offset != con_columns)) { 415 free(cci->column_offset, M_DEVBUF); 416 cci->column_offset = NULL; 417 } 418 419 if (!atari_realconfig) { 420 cci->row_ptr = con_rows; 421 cci->column_offset = con_columns; 422 } else { 423 cci->row_ptr = malloc(sizeof(u_char *) * ip->rows, 424 M_DEVBUF, M_NOWAIT); 425 cci->column_offset = malloc(sizeof(u_int) * ip->cols, 426 M_DEVBUF, M_NOWAIT); 427 } 428 429 if (!cci->row_ptr || !cci->column_offset) 430 panic("No memory for ite-view"); 431 432 cci->width = view->bitmap->bytes_per_row << 3; 433 cci->underline = ip->font.baseline + 1; 434 cci->row_offset = view->bitmap->bytes_per_row; 435 cci->ft_x = ip->font.width; 436 cci->ft_y = ip->font.height; 437 cci->row_bytes = cci->row_offset * cci->ft_y; 438 cci->row_ptr[0] = view->bitmap->plane; 439 for (i = 1; i < ip->rows; i++) 440 cci->row_ptr[i] = cci->row_ptr[i - 1] + cci->row_bytes; 441 442 /* 443 * Initialize the column offsets to point at the correct location 444 * in the first plane. This definitely assumes a font width of 8! 445 */ 446 j = view->bitmap->depth * 2; 447 cci->column_offset[0] = 0; 448 for (i = 1; i < ip->cols; i++) 449 cci->column_offset[i] = ((i >> 1) * j) + (i & 1); 450 451 /* initialize the font cell pointers */ 452 cci->font_cell[ip->font.font_lo] = ip->font.font_p; 453 for (i = ip->font.font_lo + 1; i <= ip->font.font_hi; i++) 454 cci->font_cell[i] = cci->font_cell[i - 1] + ip->font.height; 455 456 return error; 457 } 458 459 int 460 itecc_ioctl(struct ite_softc *ip, u_long cmd, void * addr, int flag, 461 struct lwp *l) 462 { 463 struct winsize ws; 464 struct itewinsize *is; 465 int error = 0; 466 view_t *view = viewview(ip->grf->g_viewdev); 467 extern const struct cdevsw ite_cdevsw; 468 extern const struct cdevsw view_cdevsw; 469 470 switch (cmd) { 471 case ITEIOCSWINSZ: 472 is = (struct itewinsize *)addr; 473 474 if (ite_newsize(ip, is)) 475 error = ENOMEM; 476 else { 477 view = viewview(ip->grf->g_viewdev); 478 ws.ws_row = ip->rows; 479 ws.ws_col = ip->cols; 480 ws.ws_xpixel = view->display.width; 481 ws.ws_ypixel = view->display.height; 482 ite_reset(ip); 483 /* 484 * XXX tell tty about the change 485 * XXX this is messy, but works 486 */ 487 (*ite_cdevsw.d_ioctl)(ip->grf->g_itedev, TIOCSWINSZ, 488 (void *)&ws, 0, l); 489 } 490 break; 491 case VIOCSCMAP: 492 case VIOCGCMAP: 493 /* 494 * XXX watchout for that NOLWP. its not really the kernel 495 * XXX talking these two commands don't use the proc pointer 496 * XXX though. 497 */ 498 error = (*view_cdevsw.d_ioctl)(ip->grf->g_viewdev, cmd, addr, 499 flag, NOLWP); 500 break; 501 default: 502 error = EPASSTHROUGH; 503 break; 504 } 505 return error; 506 } 507 508 static void 509 cursor32(struct ite_softc *ip, int flag) 510 { 511 int cend; 512 u_char *pl; 513 ipriv_t *cci; 514 515 cci = ip->priv; 516 517 if (flag == END_CURSOROPT) 518 cci->cursor_opt--; 519 else if (flag == START_CURSOROPT) { 520 if (!cci->cursor_opt) 521 cursor32(ip, ERASE_CURSOR); 522 cci->cursor_opt++; 523 return; /* if we are already opted. */ 524 } 525 526 if (cci->cursor_opt) 527 return; /* if we are still nested. */ 528 /* else we draw the cursor. */ 529 530 if (flag != DRAW_CURSOR && flag != END_CURSOROPT) { 531 /* 532 * erase the cursor 533 */ 534 cend = ip->font.height - 1; 535 pl = cci->column_offset[ip->cursorx] 536 + cci->row_ptr[ip->cursory]; 537 __asm volatile 538 ("1: notb %0@ ; addaw %4,%0\n\t" 539 "dbra %1,1b" 540 : "=a" (pl), "=d" (cend) 541 : "0" (pl), "1" (cend), 542 "d" (cci->row_offset) 543 ); 544 } 545 546 if (flag != DRAW_CURSOR && flag != MOVE_CURSOR && flag != END_CURSOROPT) 547 return; 548 549 /* 550 * draw the cursor 551 */ 552 cend = uimin(ip->curx, ip->cols - 1); 553 if (flag == DRAW_CURSOR 554 && ip->cursorx == cend && ip->cursory == ip->cury) 555 return; 556 ip->cursorx = cend; 557 ip->cursory = ip->cury; 558 cend = ip->font.height - 1; 559 pl = cci->column_offset[ip->cursorx] 560 + cci->row_ptr[ip->cursory]; 561 562 __asm volatile 563 ("1: notb %0@ ; addaw %4,%0\n\t" 564 "dbra %1,1b" 565 : "=a" (pl), "=d" (cend) 566 : "0" (pl), "1" (cend), 567 "d" (cci->row_offset) 568 ); 569 } 570 571 static void 572 putc8(struct ite_softc *ip, int c, int dy, int dx, int mode) 573 { 574 ipriv_t *cci = (ipriv_t *)ip->priv; 575 u_char *pl = cci->column_offset[dx] + cci->row_ptr[dy]; 576 u_int fh = cci->ft_y; 577 u_int ro = cci->row_offset; 578 u_char eor_mask; 579 u_char bl, tmp, ul; 580 u_char *ft; 581 582 if (c < ip->font.font_lo || c > ip->font.font_hi) 583 return; 584 585 /* 586 * Handle DEC special graphics character by 'ESC ( B' sequence. 587 * Note we assume all font data (fontdata_8x8 and fontdata_8x16) 588 * contain DEC graphics glyph (for 0x5f to 0x7e) at 0x00 to 0x1F. 589 */ 590 if (*ip->GL == CSET_DECGRAPH) { 591 if (ip->font.font_lo == 0 && c >= 0x5f && c <= 0x7e) 592 c -= 0x5f; 593 } 594 ft = cci->font_cell[c]; 595 596 if (!mode) { 597 while (fh--) { 598 *pl = *ft++; pl += ro; 599 } 600 return; 601 } 602 603 eor_mask = (mode & ATTR_INV) ? 0xff : 0x00; 604 bl = (mode & ATTR_BOLD) ? 1 : 0; 605 ul = (mode & ATTR_UL) ? fh - cci->underline : fh; 606 for (; fh--; pl += ro) { 607 if (fh != ul) { 608 tmp = *ft++; 609 if (bl) 610 tmp |= (tmp >> 1); 611 *pl = tmp ^ eor_mask; 612 } else { 613 *pl = 0xff ^ eor_mask; 614 ft++; 615 } 616 } 617 } 618 619 static void 620 clear8(struct ite_softc *ip, int sy, int sx, int h, int w) 621 { 622 ipriv_t *cci = (ipriv_t *) ip->priv; 623 view_t *v = viewview(ip->grf->g_viewdev); 624 bmap_t *bm = v->bitmap; 625 626 if ((sx == 0) && (w == ip->cols)) { 627 /* common case: clearing whole lines */ 628 while (h--) { 629 int i; 630 u_char *ptr = cci->row_ptr[sy]; 631 for (i = 0; i < ip->font.height; i++) { 632 memset(ptr, 0, bm->bytes_per_row); 633 ptr += bm->bytes_per_row; 634 } 635 sy++; 636 } 637 } else { 638 /* 639 * clearing only part of a line 640 * XXX could be optimized MUCH better, but is it worth the 641 * trouble? 642 */ 643 644 int i; 645 u_char *pls, *ple; 646 647 pls = cci->row_ptr[sy]; 648 ple = pls + cci->column_offset[sx + w - 1]; 649 pls = pls + cci->column_offset[sx]; 650 651 for (i = ((ip->font.height) * h) - 1; i >= 0; i--) { 652 u_char *p = pls; 653 while (p <= ple) 654 *p++ = 0; 655 pls += bm->bytes_per_row; 656 ple += bm->bytes_per_row; 657 } 658 } 659 } 660 661 /* Note: sx is only relevant for SCROLL_LEFT or SCROLL_RIGHT. */ 662 static void 663 scroll8(register struct ite_softc *ip, register int sy, int sx, int count, 664 int dir) 665 { 666 bmap_t *bm = viewview(ip->grf->g_viewdev)->bitmap; 667 u_char *pl = ((ipriv_t *)ip->priv)->row_ptr[sy]; 668 669 if (dir == SCROLL_UP) { 670 int dy = sy - count; 671 672 cursor32(ip, ERASE_CURSOR); 673 scrollbmap(bm, 0, dy * ip->font.height, bm->bytes_per_row >> 3, 674 (ip->bottom_margin - dy + 1) * ip->font.height, 675 0, -(count * ip->font.height)); 676 } else if (dir == SCROLL_DOWN) { 677 cursor32(ip, ERASE_CURSOR); 678 scrollbmap(bm, 0, sy * ip->font.height, bm->bytes_per_row >> 3, 679 (ip->bottom_margin - sy + 1) * ip->font.height, 680 0, count * ip->font.height); 681 } else if (dir == SCROLL_RIGHT) { 682 int sofs = (ip->cols - count) * ip->font.width; 683 int dofs = (ip->cols) * ip->font.width; 684 int i, j; 685 686 cursor32(ip, ERASE_CURSOR); 687 for (j = ip->font.height - 1; j >= 0; j--) { 688 int sofs2 = sofs, dofs2 = dofs; 689 for (i = (ip->cols - (sx + count)) - 1; i >= 0; i--) { 690 int t; 691 sofs2 -= ip->font.width; 692 dofs2 -= ip->font.width; 693 __asm("bfextu %1@{%2:%3}, %0" : "=d" (t) 694 : "a" (pl), "d" (sofs2), 695 "d" (ip->font.width)); 696 __asm("bfins %3, %0@{%1:%2}" : 697 : "a" (pl), "d" (dofs2), 698 "d" (ip->font.width), "d" (t)); 699 } 700 pl += bm->bytes_per_row; 701 } 702 } else { /* SCROLL_LEFT */ 703 int sofs = (sx) * ip->font.width; 704 int dofs = (sx - count) * ip->font.width; 705 int i, j; 706 707 cursor32(ip, ERASE_CURSOR); 708 for (j = ip->font.height - 1; j >= 0; j--) { 709 int sofs2 = sofs, dofs2 = dofs; 710 for (i = (ip->cols - sx) - 1; i >= 0; i--) { 711 int t; 712 713 __asm("bfextu %1@{%2:%3}, %0" : "=d" (t) 714 : "a" (pl), "d" (sofs2), 715 "d" (ip->font.width)); 716 __asm("bfins %3, %0@{%1:%2}" : 717 : "a" (pl), "d" (dofs2), 718 "d" (ip->font.width), "d" (t)); 719 sofs2 += ip->font.width; 720 dofs2 += ip->font.width; 721 } 722 pl += bm->bytes_per_row; 723 } 724 } 725 } 726 727 static void 728 scrollbmap (bmap_t *bm, u_short x, u_short y, u_short width, u_short height, 729 short dx, short dy) 730 { 731 u_short lwpr = bm->bytes_per_row >> 2; 732 733 if (dx) { 734 /* FIX: */ 735 panic ("delta x not supported in scroll bitmap yet."); 736 } 737 738 if (dy == 0) { 739 return; 740 } 741 if (dy > 0) { 742 u_long *pl = (u_long *)bm->plane; 743 u_long *src_y = pl + (lwpr * y); 744 u_long *dest_y = pl + (lwpr * (y + dy)); 745 u_long count = lwpr * (height - dy); 746 u_long *clr_y = src_y; 747 u_long clr_count = dest_y - src_y; 748 u_long bc, cbc; 749 750 src_y += count - 1; 751 dest_y += count - 1; 752 753 bc = count >> 4; 754 count &= 0xf; 755 756 while (bc--) { 757 *dest_y-- = *src_y--; *dest_y-- = *src_y--; 758 *dest_y-- = *src_y--; *dest_y-- = *src_y--; 759 *dest_y-- = *src_y--; *dest_y-- = *src_y--; 760 *dest_y-- = *src_y--; *dest_y-- = *src_y--; 761 *dest_y-- = *src_y--; *dest_y-- = *src_y--; 762 *dest_y-- = *src_y--; *dest_y-- = *src_y--; 763 *dest_y-- = *src_y--; *dest_y-- = *src_y--; 764 *dest_y-- = *src_y--; *dest_y-- = *src_y--; 765 } 766 while (count--) 767 *dest_y-- = *src_y--; 768 769 cbc = clr_count >> 4; 770 clr_count &= 0xf; 771 772 while (cbc--) { 773 *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; 774 *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; 775 *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; 776 *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; 777 } 778 while (clr_count--) 779 *clr_y++ = 0; 780 } else { 781 u_long *pl = (u_long *)bm->plane; 782 u_long *src_y = pl + (lwpr * (y - dy)); 783 u_long *dest_y = pl + (lwpr * y); 784 long count = lwpr * (height + dy); 785 u_long *clr_y = dest_y + count; 786 u_long clr_count = src_y - dest_y; 787 u_long bc, cbc; 788 789 bc = count >> 4; 790 count &= 0xf; 791 792 while (bc--) { 793 *dest_y++ = *src_y++; *dest_y++ = *src_y++; 794 *dest_y++ = *src_y++; *dest_y++ = *src_y++; 795 *dest_y++ = *src_y++; *dest_y++ = *src_y++; 796 *dest_y++ = *src_y++; *dest_y++ = *src_y++; 797 *dest_y++ = *src_y++; *dest_y++ = *src_y++; 798 *dest_y++ = *src_y++; *dest_y++ = *src_y++; 799 *dest_y++ = *src_y++; *dest_y++ = *src_y++; 800 *dest_y++ = *src_y++; *dest_y++ = *src_y++; 801 } 802 while (count--) 803 *dest_y++ = *src_y++; 804 805 cbc = clr_count >> 4; 806 clr_count &= 0xf; 807 808 while (cbc--) { 809 *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; 810 *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; 811 *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; 812 *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; 813 } 814 while (clr_count--) 815 *clr_y++ = 0; 816 } 817 } 818