1/* $NetBSD: ite_tv.c,v 1.15 2007/03/11 06:01:05 isaki 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/cdefs.h> 34__KERNEL_RCSID(0, "$NetBSD: ite_tv.c,v 1.15 2007/03/11 06:01:05 isaki Exp $"); 35 36#include <sys/param.h> 37#include <sys/device.h> 38#include <sys/proc.h> 39#include <sys/systm.h> 40 41#include <machine/bus.h> 42#include <machine/grfioctl.h> 43 44#include <arch/x68k/x68k/iodevice.h> 45#include <arch/x68k/dev/itevar.h> 46#include <arch/x68k/dev/grfvar.h> 47#include <arch/x68k/dev/mfp.h> 48 49/* 50 * ITE device dependent routine for X680x0 Text-Video framebuffer. 51 * Use X680x0 ROM fixed width font (8x16) 52 */ 53 54#define CRTC (IODEVbase->io_crtc) 55 56/* 57 * font constant 58 */ 59#define FONTWIDTH 8 60#define FONTHEIGHT 16 61#define UNDERLINE 14 62 63/* 64 * framebuffer constant 65 */ 66#define PLANEWIDTH 1024 67#define PLANEHEIGHT 1024 68#define PLANELINES (PLANEHEIGHT / FONTHEIGHT) 69#define ROWBYTES (PLANEWIDTH / FONTWIDTH) 70#define PLANESIZE (PLANEHEIGHT * ROWBYTES) 71 72u_int tv_top; 73u_char *tv_row[PLANELINES]; 74char *tv_font[256]; 75volatile char *tv_kfont[0x7f]; 76 77u_char kern_font[256 * FONTHEIGHT]; 78 79#define PHYSLINE(y) ((tv_top + (y)) % PLANELINES) 80#define ROWOFFSET(y) ((y) * FONTHEIGHT * ROWBYTES) 81#define CHADDR(y, x) (tv_row[PHYSLINE(y)] + (x)) 82 83#define SETGLYPH(to,from) memcpy(&kern_font[(from)*16],&kern_font[(to)*16], 16) 84#define KFONTBASE(left) ((left) * 32 * 0x5e - 0x21 * 32) 85 86/* prototype */ 87void tv_init(struct ite_softc *); 88void tv_deinit(struct ite_softc *); 89void tv_putc(struct ite_softc *, int, int, int, int); 90void tv_cursor(struct ite_softc *, int); 91void tv_clear(struct ite_softc *, int, int, int, int); 92void tv_scroll(struct ite_softc *, int, int, int, int); 93 94inline static int expbits(int); 95inline static void txrascpy(u_char, u_char, short, signed short); 96 97static inline void 98txrascpy(u_char src, u_char dst, short size, 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 */ 142void 143ite_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 */ 158void 159tv_init(struct ite_softc *ip) 160{ 161 short i; 162 163 /* 164 * initialize private variables 165 */ 166 tv_top = 0; 167 for (i = 0; i < PLANELINES; i++) 168 tv_row[i] = (void *)__UNVOLATILE(&IODEVbase->tvram[ROWOFFSET(i)]); 169 /* shadow ANK font */ 170 memcpy(kern_font, (void *)&IODEVbase->cgrom0_8x16, 256 * FONTHEIGHT); 171 ite_set_glyph(); 172 /* set font address cache */ 173 for (i = 0; i < 256; i++) 174 tv_font[i] = &kern_font[i * FONTHEIGHT]; 175 for (i = 0x21; i < 0x30; i++) 176 tv_kfont[i] = &IODEVbase->cgrom0_16x16[KFONTBASE(i-0x21)]; 177 for (; i < 0x50; i++) 178 tv_kfont[i] = &IODEVbase->cgrom1_16x16[KFONTBASE(i-0x30)]; 179 for (; i < 0x7f; i++) 180 tv_kfont[i] = &IODEVbase->cgrom2_16x16[KFONTBASE(i-0x50)]; 181 182 /* 183 * initialize part of ip 184 */ 185 ip->cols = ip->grf->g_display.gd_dwidth / FONTWIDTH; 186 ip->rows = ip->grf->g_display.gd_dheight / FONTHEIGHT; 187 /* set draw routine dynamically */ 188 ip->isw->ite_putc = tv_putc; 189 ip->isw->ite_cursor = tv_cursor; 190 ip->isw->ite_clear = tv_clear; 191 ip->isw->ite_scroll = tv_scroll; 192 193 /* 194 * Intialize colormap 195 */ 196#define RED (0x1f << 6) 197#define BLUE (0x1f << 1) 198#define GREEN (0x1f << 11) 199 IODEVbase->tpalet[0] = 0; /* black */ 200 IODEVbase->tpalet[1] = 1 | RED; /* red */ 201 IODEVbase->tpalet[2] = 1 | GREEN; /* green */ 202 IODEVbase->tpalet[3] = 1 | RED | GREEN; /* yellow */ 203 IODEVbase->tpalet[4] = 1 | BLUE; /* blue */ 204 IODEVbase->tpalet[5] = 1 | BLUE | RED; /* magenta */ 205 IODEVbase->tpalet[6] = 1 | BLUE | GREEN; /* cyan */ 206 IODEVbase->tpalet[7] = 1 | BLUE | RED | GREEN; /* white */ 207} 208 209/* 210 * Deinitialize 211 */ 212void 213tv_deinit(struct ite_softc *ip) 214{ 215 ip->flags &= ~ITE_INITED; /* XXX? */ 216} 217 218typedef void tv_putcfunc(struct ite_softc *, int, char *); 219static tv_putcfunc tv_putc_nm; 220static tv_putcfunc tv_putc_in; 221static tv_putcfunc tv_putc_ul; 222static tv_putcfunc tv_putc_ul_in; 223static tv_putcfunc tv_putc_bd; 224static tv_putcfunc tv_putc_bd_in; 225static tv_putcfunc tv_putc_bd_ul; 226static tv_putcfunc tv_putc_bd_ul_in; 227 228static tv_putcfunc *putc_func[ATTR_ALL + 1] = { 229 tv_putc_nm, 230 tv_putc_in, 231 tv_putc_ul, 232 tv_putc_ul_in, 233 tv_putc_bd, 234 tv_putc_bd_in, 235 tv_putc_bd_ul, 236 tv_putc_bd_ul_in, 237 /* no support for blink */ 238 tv_putc_nm, 239 tv_putc_in, 240 tv_putc_ul, 241 tv_putc_ul_in, 242 tv_putc_bd, 243 tv_putc_bd_in, 244 tv_putc_bd_ul, 245 tv_putc_bd_ul_in, 246}; 247 248/* 249 * simple put character function 250 */ 251void 252tv_putc(struct ite_softc *ip, int ch, int y, int x, int mode) 253{ 254 char *p = CHADDR(y, x); 255 short fh; 256 257 /* multi page write mode */ 258 CRTC.r21 = 0x0100 | ip->fgcolor << 4; 259 260 /* draw plane */ 261 putc_func[mode](ip, ch, p); 262 263 /* erase plane */ 264 CRTC.r21 ^= 0x00f0; 265 if (ip->save_char) { 266 for (fh = 0; fh < FONTHEIGHT; fh++, p += ROWBYTES) 267 *(u_short *)p = 0; 268 } else { 269 for (fh = 0; fh < FONTHEIGHT; fh++, p += ROWBYTES) 270 *p = 0; 271 } 272 273 /* crtc mode reset */ 274 CRTC.r21 = 0; 275} 276 277void 278tv_putc_nm(struct ite_softc *ip, int ch, char *p) 279{ 280 short fh, hi; 281 char *f; 282 volatile short *kf; 283 284 hi = ip->save_char & 0x7f; 285 286 if (hi >= 0x21 && hi <= 0x7e && ch >= 0x21 && ch <= 0x7e) { 287 /* multibyte character */ 288 kf = (volatile short *)tv_kfont[hi]; 289 kf += ch * FONTHEIGHT; 290 /* draw plane */ 291 for (fh = 0; fh < FONTHEIGHT; fh++, p += ROWBYTES) 292 *(u_short *)p = *kf++; 293 return; 294 } 295 296 /* singlebyte character */ 297 if (*ip->GL == CSET_JISKANA) 298 ch |= 0x80; 299 f = tv_font[ch]; 300 301 /* draw plane */ 302 for (fh = 0; fh < FONTHEIGHT; fh++, p += ROWBYTES) 303 *p = *f++; 304} 305 306void 307tv_putc_in(struct ite_softc *ip, int ch, char *p) 308{ 309 short fh, hi; 310 char *f; 311 volatile short *kf; 312 313 hi = ip->save_char & 0x7f; 314 315 if (hi >= 0x21 && hi <= 0x7e && ch >= 0x21 && ch <= 0x7e) { 316 /* multibyte character */ 317 kf = (volatile short *)tv_kfont[hi]; 318 kf += ch * FONTHEIGHT; 319 /* draw plane */ 320 for (fh = 0; fh < FONTHEIGHT; fh++, p += ROWBYTES) 321 *(u_short *)p = ~*kf++; 322 return; 323 } 324 325 /* singlebyte character */ 326 if (*ip->GL == CSET_JISKANA) 327 ch |= 0x80; 328 f = tv_font[ch]; 329 330 /* draw plane */ 331 for (fh = 0; fh < FONTHEIGHT; fh++, p += ROWBYTES) 332 *p = ~*f++; 333} 334 335void 336tv_putc_bd(struct ite_softc *ip, int ch, char *p) 337{ 338 short fh, hi; 339 char *f; 340 volatile short *kf; 341 342 hi = ip->save_char & 0x7f; 343 344 if (hi >= 0x21 && hi <= 0x7e && ch >= 0x21 && ch <= 0x7e) { 345 /* multibyte character */ 346 kf = (volatile short *)tv_kfont[hi]; 347 kf += ch * FONTHEIGHT; 348 /* draw plane */ 349 for (fh = 0; fh < FONTHEIGHT; fh++, p += ROWBYTES) { 350 ch = *kf++; 351 *(u_short *)p = ch | (ch >> 1); 352 } 353 return; 354 } 355 356 /* singlebyte character */ 357 if (*ip->GL == CSET_JISKANA) 358 ch |= 0x80; 359 f = tv_font[ch]; 360 361 /* draw plane */ 362 for (fh = 0; fh < FONTHEIGHT; fh++, p += ROWBYTES) { 363 ch = *f++; 364 *p = ch | (ch >> 1); 365 } 366} 367 368inline static int 369expbits(int data) 370{ 371 int i, nd = 0; 372 if (data & 1) 373 nd |= 0x02; 374 for (i=1; i < 32; i++) { 375 if (data & (1 << i)) 376 nd |= 0x5 << (i-1); 377 } 378 nd &= ~data; 379 return (~nd); 380} 381 382void 383tv_putc_ul(struct ite_softc *ip, int ch, char *p) 384{ 385 short fh, hi; 386 char *f; 387 volatile short *kf; 388 389 hi = ip->save_char & 0x7f; 390 391 if (hi >= 0x21 && hi <= 0x7e && ch >= 0x21 && ch <= 0x7e) { 392 /* multibyte character */ 393 kf = (volatile short *)tv_kfont[hi]; 394 kf += ch * FONTHEIGHT; 395 /* draw plane */ 396 for (fh = 0; fh < UNDERLINE; fh++, p += ROWBYTES) 397 *(u_short *)p = *kf++; 398 *(u_short *)p = expbits(*kf++); 399 p += ROWBYTES; 400 for (fh++; fh < FONTHEIGHT; fh++, p += ROWBYTES) 401 *(u_short *)p = *kf++; 402 return; 403 } 404 405 /* singlebyte character */ 406 if (*ip->GL == CSET_JISKANA) 407 ch |= 0x80; 408 f = tv_font[ch]; 409 410 /* draw plane */ 411 for (fh = 0; fh < UNDERLINE; fh++, p += ROWBYTES) 412 *p = *f++; 413 *p = expbits(*f++); 414 p += ROWBYTES; 415 for (fh++; fh < FONTHEIGHT; fh++, p += ROWBYTES) 416 *p = *f++; 417} 418 419void 420tv_putc_bd_in(struct ite_softc *ip, int ch, char *p) 421{ 422 short fh, hi; 423 char *f; 424 volatile short *kf; 425 426 hi = ip->save_char & 0x7f; 427 428 if (hi >= 0x21 && hi <= 0x7e && ch >= 0x21 && ch <= 0x7e) { 429 /* multibyte character */ 430 kf = (volatile short *)tv_kfont[hi]; 431 kf += ch * FONTHEIGHT; 432 /* draw plane */ 433 for (fh = 0; fh < FONTHEIGHT; fh++, p += ROWBYTES) { 434 ch = *kf++; 435 *(u_short *)p = ~(ch | (ch >> 1)); 436 } 437 return; 438 } 439 440 /* singlebyte character */ 441 if (*ip->GL == CSET_JISKANA) 442 ch |= 0x80; 443 f = tv_font[ch]; 444 445 /* draw plane */ 446 for (fh = 0; fh < FONTHEIGHT; fh++, p += ROWBYTES) { 447 ch = *f++; 448 *p = ~(ch | (ch >> 1)); 449 } 450} 451 452void 453tv_putc_ul_in(struct ite_softc *ip, int ch, char *p) 454{ 455 short fh, hi; 456 char *f; 457 volatile short *kf; 458 459 hi = ip->save_char & 0x7f; 460 461 if (hi >= 0x21 && hi <= 0x7e && ch >= 0x21 && ch <= 0x7e) { 462 /* multibyte character */ 463 kf = (volatile short *)tv_kfont[hi]; 464 kf += ch * FONTHEIGHT; 465 /* draw plane */ 466 for (fh = 0; fh < UNDERLINE; fh++, p += ROWBYTES) 467 *(u_short *)p = ~*kf++; 468 *(u_short *)p = ~expbits(*kf++); 469 p += ROWBYTES; 470 for (fh++; fh < FONTHEIGHT; fh++, p += ROWBYTES) 471 *(u_short *)p = ~*kf++; 472 return; 473 } 474 475 /* singlebyte character */ 476 if (*ip->GL == CSET_JISKANA) 477 ch |= 0x80; 478 f = tv_font[ch]; 479 480 /* draw plane */ 481 for (fh = 0; fh < UNDERLINE; fh++, p += ROWBYTES) 482 *p = ~*f++; 483 *p = ~expbits(*f++); 484 p += ROWBYTES; 485 for (fh++; fh < FONTHEIGHT; fh++, p += ROWBYTES) 486 *p = ~*f++; 487} 488 489void 490tv_putc_bd_ul(struct ite_softc *ip, int ch, char *p) 491{ 492 short fh, hi; 493 char *f; 494 volatile short *kf; 495 496 hi = ip->save_char & 0x7f; 497 498 if (hi >= 0x21 && hi <= 0x7e && ch >= 0x21 && ch <= 0x7e) { 499 /* multibyte character */ 500 kf = (volatile short *)tv_kfont[hi]; 501 kf += ch * FONTHEIGHT; 502 /* draw plane */ 503 for (fh = 0; fh < UNDERLINE; fh++, p += ROWBYTES) { 504 ch = *kf++; 505 *(u_short *)p = ch | (ch >> 1); 506 } 507 ch = *kf++; 508 *(u_short *)p = expbits(ch | (ch >> 1)); 509 p += ROWBYTES; 510 for (fh++; fh < FONTHEIGHT; fh++, p += ROWBYTES) { 511 ch = *kf++; 512 *(u_short *)p = ch | (ch >> 1); 513 } 514 return; 515 } 516 517 /* singlebyte character */ 518 if (*ip->GL == CSET_JISKANA) 519 ch |= 0x80; 520 f = tv_font[ch]; 521 522 /* draw plane */ 523 for (fh = 0; fh < UNDERLINE; fh++, p += ROWBYTES) { 524 ch = *f++; 525 *p = ch | (ch >> 1); 526 } 527 ch = *f++; 528 *p = expbits(ch | (ch >> 1)); 529 p += ROWBYTES; 530 for (fh++; fh < FONTHEIGHT; fh++, p += ROWBYTES) { 531 ch = *f++; 532 *p = ch | (ch >> 1); 533 } 534} 535 536void 537tv_putc_bd_ul_in(struct ite_softc *ip, int ch, char *p) 538{ 539 short fh, hi; 540 char *f; 541 volatile short *kf; 542 543 hi = ip->save_char & 0x7f; 544 545 if (hi >= 0x21 && hi <= 0x7e && ch >= 0x21 && ch <= 0x7e) { 546 /* multibyte character */ 547 kf = (volatile short *)tv_kfont[hi]; 548 kf += ch * FONTHEIGHT; 549 /* draw plane */ 550 for (fh = 0; fh < UNDERLINE; fh++, p += ROWBYTES) { 551 ch = *kf++; 552 *(u_short *)p = ~(ch | (ch >> 1)); 553 } 554 ch = *kf++; 555 *(u_short *)p = ~expbits(ch | (ch >> 1)); 556 p += ROWBYTES; 557 for (fh++; fh < FONTHEIGHT; fh++, p += ROWBYTES) { 558 ch = *kf++; 559 *(u_short *)p = ~(ch | (ch >> 1)); 560 } 561 return; 562 } 563 564 /* singlebyte character */ 565 if (*ip->GL == CSET_JISKANA) 566 ch |= 0x80; 567 f = tv_font[ch]; 568 569 /* draw plane */ 570 for (fh = 0; fh < UNDERLINE; fh++, p += ROWBYTES) { 571 ch = *f++; 572 *p = ~(ch | (ch >> 1)); 573 } 574 ch = *f++; 575 *p = ~expbits(ch | (ch >> 1)); 576 p += ROWBYTES; 577 for (fh++; fh < FONTHEIGHT; fh++, p += ROWBYTES) { 578 ch = *f++; 579 ch |= ch >> 1; 580 *p = ~(ch | (ch >> 1)); 581 } 582} 583 584/* 585 * draw/erase/move cursor 586 */ 587void 588tv_cursor(struct ite_softc *ip, int flag) 589{ 590 u_char *p; 591 short fh; 592 593 /* erase */ 594 switch (flag) { 595 /*case DRAW_CURSOR:*/ 596 /*case ERASE_CURSOR:*/ 597 /*case MOVE_CURSOR:*/ 598 case START_CURSOROPT: 599 /* 600 * old: ip->cursorx, ip->cursory 601 * new: ip->curx, ip->cury 602 */ 603 p = CHADDR(ip->cursory, ip->cursorx); 604 for (fh = 0; fh < FONTHEIGHT; fh++, p += ROWBYTES) 605 *p = ~*p; 606 break; 607 } 608 609 /* draw */ 610 switch (flag) { 611 /*case MOVE_CURSOR:*/ 612 case END_CURSOROPT: 613 /* 614 * Use exclusive-or. 615 */ 616 p = CHADDR(ip->cury, ip->curx); 617 for (fh = 0; fh < FONTHEIGHT; fh++, p += ROWBYTES) 618 *p = ~*p; 619 620 ip->cursorx = ip->curx; 621 ip->cursory = ip->cury; 622 break; 623 } 624} 625 626/* 627 * clear rectangle 628 */ 629void 630tv_clear(struct ite_softc *ip, int y, int x, int height, int width) 631{ 632 char *p; 633 short fh; 634 635 /* XXX: reset scroll register on clearing whole screen */ 636 if (y == 0 && x == 0 && height == ip->rows && width == ip->cols) { 637 CRTC.r10 = 0; 638 CRTC.r11 = tv_top * FONTHEIGHT; 639 } 640 641 CRTC.r21 = 0x01f0; 642 while (height--) { 643 p = CHADDR(y++, x); 644 for (fh = 0; fh < FONTHEIGHT; fh++, p += ROWBYTES) 645 memset(p, 0, width); 646 } 647 /* crtc mode reset */ 648 CRTC.r21 = 0; 649} 650 651/* 652 * scroll lines/columns 653 */ 654void 655tv_scroll(struct ite_softc *ip, int srcy, int srcx, int count, int dir) 656{ 657 int dst, siz, pl; 658 659 switch (dir) { 660 case SCROLL_UP: 661 /* 662 * src: srcy 663 * dst: (srcy - count) 664 * siz: (ip->bottom_margin - sy + 1) 665 */ 666 dst = srcy - count; 667 siz = ip->bottom_margin - srcy + 1; 668 if (dst == 0 && ip->bottom_margin == ip->rows - 1) { 669 /* special case, hardware scroll */ 670 tv_top = (tv_top + count) % PLANELINES; 671 CRTC.r11 = tv_top * FONTHEIGHT; 672 } else { 673 srcy = PHYSLINE(srcy); 674 dst = PHYSLINE(dst); 675 txrascpy(srcy, dst, siz, 0x0f); 676 } 677 break; 678 679 case SCROLL_DOWN: 680 /* 681 * src: srcy 682 * dst: (srcy + count) 683 * siz: (ip->bottom_margin - dy + 1) 684 */ 685 dst = srcy + count; 686 siz = ip->bottom_margin - dst + 1; 687 if (srcy == 0 && ip->bottom_margin == ip->rows - 1) { 688 /* special case, hardware scroll */ 689 tv_top = (tv_top + PLANELINES - count) % PLANELINES; 690 CRTC.r11 = tv_top * FONTHEIGHT; 691 } else { 692 srcy = PHYSLINE(srcy) + siz - 1; 693 dst = PHYSLINE(dst) + siz - 1; 694 txrascpy(srcy, dst, siz, 0x0f | 0x8000); 695 } 696 break; 697 698 case SCROLL_LEFT: 699 for (pl = 0; pl < PLANESIZE * 4; pl += PLANESIZE) { 700 short fh; 701 char *src = CHADDR(srcy, srcx) + pl; 702 char *dest = CHADDR(srcy, srcx - count) + pl; 703 704 siz = ip->cols - srcx; 705 for (fh = 0; fh < FONTHEIGHT; fh++) { 706 memcpy(dest, src, siz); 707 src += ROWBYTES; 708 dest += ROWBYTES; 709 } 710 } 711 break; 712 713 case SCROLL_RIGHT: 714 for (pl = 0; pl < PLANESIZE * 4; pl += PLANESIZE) { 715 short fh; 716 char *src = CHADDR(srcy, srcx) + pl; 717 char *dest = CHADDR(srcy, srcx + count) + pl; 718 719 siz = ip->cols - (srcx + count); 720 for (fh = 0; fh < FONTHEIGHT; fh++) { 721 memcpy(dest, src, siz); 722 src += ROWBYTES; 723 dest += ROWBYTES; 724 } 725 } 726 break; 727 } 728} 729