1 /* $NetBSD: ite_tv.c,v 1.9 2001/12/27 02:23:25 wiz Exp $ */ 2 3 /* 4 * Copyright (c) 1997 Masaru Oki. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Masaru Oki. 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include <sys/param.h> 34 #include <sys/device.h> 35 #include <sys/proc.h> 36 #include <sys/systm.h> 37 38 #include <machine/bus.h> 39 #include <machine/grfioctl.h> 40 41 #include <arch/x68k/x68k/iodevice.h> 42 #include <arch/x68k/dev/itevar.h> 43 #include <arch/x68k/dev/grfvar.h> 44 #include <arch/x68k/dev/mfp.h> 45 46 /* 47 * ITE device dependent routine for X680x0 Text-Video framebuffer. 48 * Use X680x0 ROM fixed width font (8x16) 49 */ 50 51 #define CRTC (IODEVbase->io_crtc) 52 53 /* 54 * font constant 55 */ 56 #define FONTWIDTH 8 57 #define FONTHEIGHT 16 58 #define UNDERLINE 14 59 60 /* 61 * framebuffer constant 62 */ 63 #define PLANEWIDTH 1024 64 #define PLANEHEIGHT 1024 65 #define PLANELINES (PLANEHEIGHT / FONTHEIGHT) 66 #define ROWBYTES (PLANEWIDTH / FONTWIDTH) 67 #define PLANESIZE (PLANEHEIGHT * ROWBYTES) 68 69 u_int tv_top; 70 u_char *tv_row[PLANELINES]; 71 char *tv_font[256]; 72 __volatile char *tv_kfont[0x7f]; 73 74 u_char kern_font[256 * FONTHEIGHT]; 75 76 #define PHYSLINE(y) ((tv_top + (y)) % PLANELINES) 77 #define ROWOFFSET(y) ((y) * FONTHEIGHT * ROWBYTES) 78 #define CHADDR(y, x) (tv_row[PHYSLINE(y)] + (x)) 79 80 #define SETGLYPH(to,from) memcpy(&kern_font[(from)*16],&kern_font[(to)*16], 16) 81 #define KFONTBASE(left) ((left) * 32 * 0x5e - 0x21 * 32) 82 83 /* prototype */ 84 void tv_init __P((struct ite_softc *)); 85 void tv_deinit __P((struct ite_softc *)); 86 void tv_putc __P((struct ite_softc *, int, int, int, int)); 87 void tv_cursor __P((struct ite_softc *, int)); 88 void tv_clear __P((struct ite_softc *, int, int, int, int)); 89 void tv_scroll __P((struct ite_softc *, int, int, int, int)); 90 91 __inline static int expbits __P((int)); 92 __inline static void txrascpy __P((u_char, u_char, short, signed short)); 93 94 static __inline void 95 txrascpy (src, dst, size, mode) 96 u_char src, dst; 97 short size; 98 signed short mode; 99 { 100 /*int s;*/ 101 u_short saved_r21 = CRTC.r21; 102 char d; 103 104 d = (mode < 0) ? -1 : 1; 105 src *= FONTHEIGHT / 4; 106 dst *= FONTHEIGHT / 4; 107 size *= 4; 108 if (d < 0) { 109 src += (FONTHEIGHT / 4) - 1; 110 dst += (FONTHEIGHT / 4) - 1; 111 } 112 113 /* specify same time write mode & page */ 114 CRTC.r21 = (mode & 0x0f) | 0x0100; 115 /*mfp.ddr = 0;*/ /* port is input */ 116 117 /*s = splhigh();*/ 118 while (--size >= 0) { 119 /* wait for hsync */ 120 mfp_wait_for_hsync (); 121 CRTC.r22 = (src << 8) | dst; /* specify raster number */ 122 /* start raster copy */ 123 CRTC.crtctrl = 8; 124 125 src += d; 126 dst += d; 127 } 128 /*splx(s);*/ 129 130 /* wait for hsync */ 131 mfp_wait_for_hsync (); 132 133 /* stop raster copy */ 134 CRTC.crtctrl = 0; 135 136 CRTC.r21 = saved_r21; 137 } 138 139 /* 140 * Change glyphs from SRAM switch. 141 */ 142 void 143 ite_set_glyph(void) 144 { 145 u_char glyph = IODEVbase->io_sram[0x59]; 146 147 if (glyph & 4) 148 SETGLYPH(0x82, '|'); 149 if (glyph & 2) 150 SETGLYPH(0x81, '~'); 151 if (glyph & 1) 152 SETGLYPH(0x80, '\\'); 153 } 154 155 /* 156 * Initialize 157 */ 158 void 159 tv_init(ip) 160 struct ite_softc *ip; 161 { 162 short i; 163 164 /* 165 * initialize private variables 166 */ 167 tv_top = 0; 168 for (i = 0; i < PLANELINES; i++) 169 tv_row[i] = (void *)&IODEVbase->tvram[ROWOFFSET(i)]; 170 /* shadow ANK font */ 171 memcpy(kern_font, (void *)&IODEVbase->cgrom0_8x16, 256 * FONTHEIGHT); 172 ite_set_glyph(); 173 /* set font address cache */ 174 for (i = 0; i < 256; i++) 175 tv_font[i] = &kern_font[i * FONTHEIGHT]; 176 for (i = 0x21; i < 0x30; i++) 177 tv_kfont[i] = &IODEVbase->cgrom0_16x16[KFONTBASE(i-0x21)]; 178 for (; i < 0x50; i++) 179 tv_kfont[i] = &IODEVbase->cgrom1_16x16[KFONTBASE(i-0x30)]; 180 for (; i < 0x7f; i++) 181 tv_kfont[i] = &IODEVbase->cgrom2_16x16[KFONTBASE(i-0x50)]; 182 183 /* 184 * initialize part of ip 185 */ 186 ip->cols = ip->grf->g_display.gd_dwidth / FONTWIDTH; 187 ip->rows = ip->grf->g_display.gd_dheight / FONTHEIGHT; 188 /* set draw routine dynamically */ 189 ip->isw->ite_putc = tv_putc; 190 ip->isw->ite_cursor = tv_cursor; 191 ip->isw->ite_clear = tv_clear; 192 ip->isw->ite_scroll = tv_scroll; 193 194 /* 195 * Intialize colormap 196 */ 197 #define RED (0x1f << 6) 198 #define BLUE (0x1f << 1) 199 #define GREEN (0x1f << 11) 200 IODEVbase->tpalet[0] = 0; /* black */ 201 IODEVbase->tpalet[1] = 1 | RED; /* red */ 202 IODEVbase->tpalet[2] = 1 | GREEN; /* green */ 203 IODEVbase->tpalet[3] = 1 | RED | GREEN; /* yellow */ 204 IODEVbase->tpalet[4] = 1 | BLUE; /* blue */ 205 IODEVbase->tpalet[5] = 1 | BLUE | RED; /* magenta */ 206 IODEVbase->tpalet[6] = 1 | BLUE | GREEN; /* cyan */ 207 IODEVbase->tpalet[7] = 1 | BLUE | RED | GREEN; /* white */ 208 } 209 210 /* 211 * Deinitialize 212 */ 213 void 214 tv_deinit(ip) 215 struct ite_softc *ip; 216 { 217 ip->flags &= ~ITE_INITED; /* XXX? */ 218 } 219 220 typedef void tv_putcfunc __P((struct ite_softc *, int, char *)); 221 static tv_putcfunc tv_putc_nm; 222 static tv_putcfunc tv_putc_in; 223 static tv_putcfunc tv_putc_ul; 224 static tv_putcfunc tv_putc_ul_in; 225 static tv_putcfunc tv_putc_bd; 226 static tv_putcfunc tv_putc_bd_in; 227 static tv_putcfunc tv_putc_bd_ul; 228 static tv_putcfunc tv_putc_bd_ul_in; 229 230 static tv_putcfunc *putc_func[ATTR_ALL + 1] = { 231 tv_putc_nm, 232 tv_putc_in, 233 tv_putc_ul, 234 tv_putc_ul_in, 235 tv_putc_bd, 236 tv_putc_bd_in, 237 tv_putc_bd_ul, 238 tv_putc_bd_ul_in, 239 /* no support for blink */ 240 tv_putc_nm, 241 tv_putc_in, 242 tv_putc_ul, 243 tv_putc_ul_in, 244 tv_putc_bd, 245 tv_putc_bd_in, 246 tv_putc_bd_ul, 247 tv_putc_bd_ul_in, 248 }; 249 250 /* 251 * simple put character function 252 */ 253 void 254 tv_putc(ip, ch, y, x, mode) 255 struct ite_softc *ip; 256 int ch, y, x, mode; 257 { 258 char *p = CHADDR(y, x); 259 short fh; 260 261 /* multi page write mode */ 262 CRTC.r21 = 0x0100 | ip->fgcolor << 4; 263 264 /* draw plane */ 265 putc_func[mode](ip, ch, p); 266 267 /* erase plane */ 268 CRTC.r21 ^= 0x00f0; 269 if (ip->save_char) { 270 for (fh = 0; fh < FONTHEIGHT; fh++, p += ROWBYTES) 271 *(u_short *)p = 0; 272 } else { 273 for (fh = 0; fh < FONTHEIGHT; fh++, p += ROWBYTES) 274 *p = 0; 275 } 276 277 /* crtc mode reset */ 278 CRTC.r21 = 0; 279 } 280 281 void 282 tv_putc_nm(ip, ch, p) 283 struct ite_softc *ip; 284 int ch; 285 char *p; 286 { 287 short fh, hi; 288 char *f; 289 short *kf; 290 291 hi = ip->save_char & 0x7f; 292 293 if (hi >= 0x21 && hi <= 0x7e) { 294 /* multibyte character */ 295 kf = (short *)tv_kfont[hi]; 296 kf += (ch & 0x7f) * FONTHEIGHT; 297 /* draw plane */ 298 for (fh = 0; fh < FONTHEIGHT; fh++, p += ROWBYTES) 299 *(u_short *)p = *kf++; 300 return; 301 } 302 303 /* singlebyte character */ 304 if (*ip->GL == CSET_JISKANA) 305 ch |= 0x80; 306 f = tv_font[ch]; 307 308 /* draw plane */ 309 for (fh = 0; fh < FONTHEIGHT; fh++, p += ROWBYTES) 310 *p = *f++; 311 } 312 313 void 314 tv_putc_in(ip, ch, p) 315 struct ite_softc *ip; 316 int ch; 317 char *p; 318 { 319 short fh, hi; 320 char *f; 321 short *kf; 322 323 hi = ip->save_char & 0x7f; 324 325 if (hi >= 0x21 && hi <= 0x7e) { 326 /* multibyte character */ 327 kf = (short *)tv_kfont[hi]; 328 kf += (ch & 0x7f) * FONTHEIGHT; 329 /* draw plane */ 330 for (fh = 0; fh < FONTHEIGHT; fh++, p += ROWBYTES) 331 *(u_short *)p = ~*kf++; 332 return; 333 } 334 335 /* singlebyte character */ 336 if (*ip->GL == CSET_JISKANA) 337 ch |= 0x80; 338 f = tv_font[ch]; 339 340 /* draw plane */ 341 for (fh = 0; fh < FONTHEIGHT; fh++, p += ROWBYTES) 342 *p = ~*f++; 343 } 344 345 void 346 tv_putc_bd(ip, ch, p) 347 struct ite_softc *ip; 348 int ch; 349 char *p; 350 { 351 short fh, hi; 352 char *f; 353 short *kf; 354 355 hi = ip->save_char & 0x7f; 356 357 if (hi >= 0x21 && hi <= 0x7e) { 358 /* multibyte character */ 359 kf = (short *)tv_kfont[hi]; 360 kf += (ch & 0x7f) * FONTHEIGHT; 361 /* draw plane */ 362 for (fh = 0; fh < FONTHEIGHT; fh++, p += ROWBYTES) { 363 ch = *kf++; 364 *(u_short *)p = ch | (ch >> 1); 365 } 366 return; 367 } 368 369 /* singlebyte character */ 370 if (*ip->GL == CSET_JISKANA) 371 ch |= 0x80; 372 f = tv_font[ch]; 373 374 /* draw plane */ 375 for (fh = 0; fh < FONTHEIGHT; fh++, p += ROWBYTES) { 376 ch = *f++; 377 *p = ch | (ch >> 1); 378 } 379 } 380 381 __inline static int 382 expbits (data) 383 int data; 384 { 385 int i, nd = 0; 386 if (data & 1) 387 nd |= 0x02; 388 for (i=1; i < 32; i++) { 389 if (data & (1 << i)) 390 nd |= 0x5 << (i-1); 391 } 392 nd &= ~data; 393 return (~nd); 394 } 395 396 void 397 tv_putc_ul(ip, ch, p) 398 struct ite_softc *ip; 399 int ch; 400 char *p; 401 { 402 short fh, hi; 403 char *f; 404 short *kf; 405 406 hi = ip->save_char & 0x7f; 407 408 if (hi >= 0x21 && hi <= 0x7e) { 409 /* multibyte character */ 410 kf = (short *)tv_kfont[hi]; 411 kf += (ch & 0x7f) * FONTHEIGHT; 412 /* draw plane */ 413 for (fh = 0; fh < UNDERLINE; fh++, p += ROWBYTES) 414 *(u_short *)p = *kf++; 415 *(u_short *)p = expbits(*kf++); 416 p += ROWBYTES; 417 for (fh++; fh < FONTHEIGHT; fh++, p += ROWBYTES) 418 *(u_short *)p = *kf++; 419 return; 420 } 421 422 /* singlebyte character */ 423 if (*ip->GL == CSET_JISKANA) 424 ch |= 0x80; 425 f = tv_font[ch]; 426 427 /* draw plane */ 428 for (fh = 0; fh < UNDERLINE; fh++, p += ROWBYTES) 429 *p = *f++; 430 *p = expbits(*f++); 431 p += ROWBYTES; 432 for (fh++; fh < FONTHEIGHT; fh++, p += ROWBYTES) 433 *p = *f++; 434 } 435 436 void 437 tv_putc_bd_in(ip, ch, p) 438 struct ite_softc *ip; 439 int ch; 440 char *p; 441 { 442 short fh, hi; 443 char *f; 444 short *kf; 445 446 hi = ip->save_char & 0x7f; 447 448 if (hi >= 0x21 && hi <= 0x7e) { 449 /* multibyte character */ 450 kf = (short *)tv_kfont[hi]; 451 kf += (ch & 0x7f) * FONTHEIGHT; 452 /* draw plane */ 453 for (fh = 0; fh < FONTHEIGHT; fh++, p += ROWBYTES) { 454 ch = *kf++; 455 *(u_short *)p = ~(ch | (ch >> 1)); 456 } 457 return; 458 } 459 460 /* singlebyte character */ 461 if (*ip->GL == CSET_JISKANA) 462 ch |= 0x80; 463 f = tv_font[ch]; 464 465 /* draw plane */ 466 for (fh = 0; fh < FONTHEIGHT; fh++, p += ROWBYTES) { 467 ch = *f++; 468 *p = ~(ch | (ch >> 1)); 469 } 470 } 471 472 void 473 tv_putc_ul_in(ip, ch, p) 474 struct ite_softc *ip; 475 int ch; 476 char *p; 477 { 478 short fh, hi; 479 char *f; 480 short *kf; 481 482 hi = ip->save_char & 0x7f; 483 484 if (hi >= 0x21 && hi <= 0x7e) { 485 /* multibyte character */ 486 kf = (short *)tv_kfont[hi]; 487 kf += (ch & 0x7f) * FONTHEIGHT; 488 /* draw plane */ 489 for (fh = 0; fh < UNDERLINE; fh++, p += ROWBYTES) 490 *(u_short *)p = ~*kf++; 491 *(u_short *)p = ~expbits(*kf++); 492 p += ROWBYTES; 493 for (fh++; fh < FONTHEIGHT; fh++, p += ROWBYTES) 494 *(u_short *)p = ~*kf++; 495 return; 496 } 497 498 /* singlebyte character */ 499 if (*ip->GL == CSET_JISKANA) 500 ch |= 0x80; 501 f = tv_font[ch]; 502 503 /* draw plane */ 504 for (fh = 0; fh < UNDERLINE; fh++, p += ROWBYTES) 505 *p = ~*f++; 506 *p = ~expbits(*f++); 507 p += ROWBYTES; 508 for (fh++; fh < FONTHEIGHT; fh++, p += ROWBYTES) 509 *p = ~*f++; 510 } 511 512 void 513 tv_putc_bd_ul(ip, ch, p) 514 struct ite_softc *ip; 515 int ch; 516 char *p; 517 { 518 short fh, hi; 519 char *f; 520 short *kf; 521 522 hi = ip->save_char & 0x7f; 523 524 if (hi >= 0x21 && hi <= 0x7e) { 525 /* multibyte character */ 526 kf = (short *)tv_kfont[hi]; 527 kf += (ch & 0x7f) * FONTHEIGHT; 528 /* draw plane */ 529 for (fh = 0; fh < UNDERLINE; fh++, p += ROWBYTES) { 530 ch = *kf++; 531 *(u_short *)p = ch | (ch >> 1); 532 } 533 ch = *kf++; 534 *(u_short *)p = expbits(ch | (ch >> 1)); 535 p += ROWBYTES; 536 for (fh++; fh < FONTHEIGHT; fh++, p += ROWBYTES) { 537 ch = *kf++; 538 *(u_short *)p = ch | (ch >> 1); 539 } 540 return; 541 } 542 543 /* singlebyte character */ 544 if (*ip->GL == CSET_JISKANA) 545 ch |= 0x80; 546 f = tv_font[ch]; 547 548 /* draw plane */ 549 for (fh = 0; fh < UNDERLINE; fh++, p += ROWBYTES) { 550 ch = *f++; 551 *p = ch | (ch >> 1); 552 } 553 ch = *f++; 554 *p = expbits(ch | (ch >> 1)); 555 p += ROWBYTES; 556 for (fh++; fh < FONTHEIGHT; fh++, p += ROWBYTES) { 557 ch = *f++; 558 *p = ch | (ch >> 1); 559 } 560 } 561 562 void 563 tv_putc_bd_ul_in(ip, ch, p) 564 struct ite_softc *ip; 565 int ch; 566 char *p; 567 { 568 short fh, hi; 569 char *f; 570 short *kf; 571 572 hi = ip->save_char & 0x7f; 573 574 if (hi >= 0x21 && hi <= 0x7e) { 575 /* multibyte character */ 576 kf = (short *)tv_kfont[hi]; 577 kf += (ch & 0x7f) * FONTHEIGHT; 578 /* draw plane */ 579 for (fh = 0; fh < UNDERLINE; fh++, p += ROWBYTES) { 580 ch = *kf++; 581 *(u_short *)p = ~(ch | (ch >> 1)); 582 } 583 ch = *kf++; 584 *(u_short *)p = ~expbits(ch | (ch >> 1)); 585 p += ROWBYTES; 586 for (fh++; fh < FONTHEIGHT; fh++, p += ROWBYTES) { 587 ch = *kf++; 588 *(u_short *)p = ~(ch | (ch >> 1)); 589 } 590 return; 591 } 592 593 /* singlebyte character */ 594 if (*ip->GL == CSET_JISKANA) 595 ch |= 0x80; 596 f = tv_font[ch]; 597 598 /* draw plane */ 599 for (fh = 0; fh < UNDERLINE; fh++, p += ROWBYTES) { 600 ch = *f++; 601 *p = ~(ch | (ch >> 1)); 602 } 603 ch = *f++; 604 *p = ~expbits(ch | (ch >> 1)); 605 p += ROWBYTES; 606 for (fh++; fh < FONTHEIGHT; fh++, p += ROWBYTES) { 607 ch = *f++; 608 ch |= ch >> 1; 609 *p = ~(ch | (ch >> 1)); 610 } 611 } 612 613 /* 614 * draw/erase/move cursor 615 */ 616 void 617 tv_cursor(ip, flag) 618 struct ite_softc *ip; 619 int flag; 620 { 621 u_char *p; 622 short fh; 623 624 /* erase */ 625 switch (flag) { 626 /*case DRAW_CURSOR:*/ 627 /*case ERASE_CURSOR:*/ 628 /*case MOVE_CURSOR:*/ 629 case START_CURSOROPT: 630 /* 631 * old: ip->cursorx, ip->cursory 632 * new: ip->curx, ip->cury 633 */ 634 p = CHADDR(ip->cursory, ip->cursorx); 635 for (fh = 0; fh < FONTHEIGHT; fh++, p += ROWBYTES) 636 *p = ~*p; 637 break; 638 } 639 640 /* draw */ 641 switch (flag) { 642 /*case MOVE_CURSOR:*/ 643 case END_CURSOROPT: 644 /* 645 * Use exclusive-or. 646 */ 647 p = CHADDR(ip->cury, ip->curx); 648 for (fh = 0; fh < FONTHEIGHT; fh++, p += ROWBYTES) 649 *p = ~*p; 650 651 ip->cursorx = ip->curx; 652 ip->cursory = ip->cury; 653 break; 654 } 655 } 656 657 /* 658 * clear rectangle 659 */ 660 void 661 tv_clear(ip, y, x, height, width) 662 struct ite_softc *ip; 663 int y, x, height, width; 664 { 665 char *p; 666 short fh; 667 668 /* XXX: reset scroll register on clearing whole screen */ 669 if (y == 0 && x == 0 && height == ip->rows && width == ip->cols) { 670 CRTC.r10 = 0; 671 CRTC.r11 = tv_top * FONTHEIGHT; 672 } 673 674 CRTC.r21 = 0x01f0; 675 while (height--) { 676 p = CHADDR(y++, x); 677 for (fh = 0; fh < FONTHEIGHT; fh++, p += ROWBYTES) 678 memset(p, 0, width); 679 } 680 /* crtc mode reset */ 681 CRTC.r21 = 0; 682 } 683 684 /* 685 * scroll lines/columns 686 */ 687 void 688 tv_scroll(ip, srcy, srcx, count, dir) 689 struct ite_softc *ip; 690 int srcy, srcx, count, dir; 691 { 692 int dst, siz, pl; 693 694 switch (dir) { 695 case SCROLL_UP: 696 /* 697 * src: srcy 698 * dst: (srcy - count) 699 * siz: (ip->bottom_margin - sy + 1) 700 */ 701 dst = srcy - count; 702 siz = ip->bottom_margin - srcy + 1; 703 if (dst == 0 && ip->bottom_margin == ip->rows - 1) { 704 /* special case, hardware scroll */ 705 tv_top = (tv_top + count) % PLANELINES; 706 CRTC.r11 = tv_top * FONTHEIGHT; 707 } else { 708 srcy = PHYSLINE(srcy); 709 dst = PHYSLINE(dst); 710 txrascpy(srcy, dst, siz, 0x0f); 711 } 712 break; 713 714 case SCROLL_DOWN: 715 /* 716 * src: srcy 717 * dst: (srcy + count) 718 * siz: (ip->bottom_margin - dy + 1) 719 */ 720 dst = srcy + count; 721 siz = ip->bottom_margin - dst + 1; 722 if (srcy == 0 && ip->bottom_margin == ip->rows - 1) { 723 /* special case, hardware scroll */ 724 tv_top = (tv_top + PLANELINES - count) % PLANELINES; 725 CRTC.r11 = tv_top * FONTHEIGHT; 726 } else { 727 srcy = PHYSLINE(srcy) + siz - 1; 728 dst = PHYSLINE(dst) + siz - 1; 729 txrascpy(srcy, dst, siz, 0x0f | 0x8000); 730 } 731 break; 732 733 case SCROLL_LEFT: 734 for (pl = 0; pl < PLANESIZE * 4; pl += PLANESIZE) { 735 short fh; 736 char *src = CHADDR(srcy, srcx) + pl; 737 char *dst = CHADDR(srcy, srcx - count) + pl; 738 739 siz = ip->cols - srcx; 740 for (fh = 0; fh < FONTHEIGHT; fh++) { 741 memcpy(dst, src, siz); 742 src += ROWBYTES; 743 dst += ROWBYTES; 744 } 745 } 746 break; 747 748 case SCROLL_RIGHT: 749 for (pl = 0; pl < PLANESIZE * 4; pl += PLANESIZE) { 750 short fh; 751 char *src = CHADDR(srcy, srcx) + pl; 752 char *dst = CHADDR(srcy, srcx + count) + pl; 753 754 siz = ip->cols - (srcx + count); 755 for (fh = 0; fh < FONTHEIGHT; fh++) { 756 memcpy(dst, src, siz); 757 src += ROWBYTES; 758 dst += ROWBYTES; 759 } 760 } 761 break; 762 } 763 } 764