1/* $NetBSD: ite_tv.c,v 1.20 2024/01/07 07:58:33 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.20 2024/01/07 07:58:33 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 72static u_int tv_top; 73static uint8_t *tv_row[PLANELINES]; 74static uint8_t *tv_font[256]; 75static volatile uint8_t *tv_kfont[0x7f]; 76 77uint8_t 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) \ 84 memcpy(&kern_font[(from) * 16],&kern_font[(to) * 16], 16) 85#define KFONTBASE(left) ((left) * 32 * 0x5e - 0x21 * 32) 86 87/* prototype */ 88static void tv_putc(struct ite_softc *, int, int, int, int); 89static void tv_cursor(struct ite_softc *, int); 90static void tv_clear(struct ite_softc *, int, int, int, int); 91static void tv_scroll(struct ite_softc *, int, int, int, int); 92 93static inline uint32_t expbits(uint32_t); 94static inline void txrascpy(uint8_t, uint8_t, int16_t, uint16_t); 95 96static inline void 97txrascpy(uint8_t src, uint8_t dst, int16_t size, uint16_t mode) 98{ 99 /*int s;*/ 100 uint16_t saved_r21 = CRTC.r21; 101 int8_t d; 102 103 d = ((mode & 0x8000) != 0) ? -1 : 1; 104 src *= FONTHEIGHT / 4; 105 dst *= FONTHEIGHT / 4; 106 size *= 4; 107 if (d < 0) { 108 src += (FONTHEIGHT / 4) - 1; 109 dst += (FONTHEIGHT / 4) - 1; 110 } 111 112 /* specify same time write mode & page */ 113 CRTC.r21 = (mode & 0x0f) | 0x0100; 114 /*mfp.ddr = 0;*/ /* port is input */ 115 116 /*s = splhigh();*/ 117 while (--size >= 0) { 118 /* wait for hsync */ 119 mfp_wait_for_hsync(); 120 CRTC.r22 = (src << 8) | dst; /* specify raster number */ 121 /* start raster copy */ 122 CRTC.crtctrl = 0x0008; 123 124 src += d; 125 dst += d; 126 } 127 /*splx(s);*/ 128 129 /* wait for hsync */ 130 mfp_wait_for_hsync(); 131 132 /* stop raster copy */ 133 CRTC.crtctrl = 0x0000; 134 135 CRTC.r21 = saved_r21; 136} 137 138/* 139 * Change glyphs from SRAM switch. 140 */ 141void 142ite_set_glyph(void) 143{ 144 uint8_t glyph = IODEVbase->io_sram[0x59]; 145 146 if ((glyph & 4) != 0) 147 SETGLYPH(0x82, '|'); 148 if ((glyph & 2) != 0) 149 SETGLYPH(0x81, '~'); 150 if ((glyph & 1) != 0) 151 SETGLYPH(0x80, '\\'); 152} 153 154/* 155 * Initialize 156 */ 157void 158tv_init(struct ite_softc *ip) 159{ 160 short i; 161 162 /* 163 * initialize private variables 164 */ 165 tv_top = 0; 166 for (i = 0; i < PLANELINES; i++) 167 tv_row[i] = 168 (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 * Initialize 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 216 ip->flags &= ~ITE_INITED; /* XXX? */ 217} 218 219static inline uint8_t *tv_getfont(int, int); 220typedef void tv_putcfunc(struct ite_softc *, int, char *); 221static tv_putcfunc tv_putc_nm; 222static tv_putcfunc tv_putc_in; 223static tv_putcfunc tv_putc_ul; 224static tv_putcfunc tv_putc_ul_in; 225static tv_putcfunc tv_putc_bd; 226static tv_putcfunc tv_putc_bd_in; 227static tv_putcfunc tv_putc_bd_ul; 228static tv_putcfunc tv_putc_bd_ul_in; 229 230static tv_putcfunc *putc_func[ATTR_ALL + 1] = { 231 [ATTR_NOR] = tv_putc_nm, 232 [ATTR_INV] = tv_putc_in, 233 [ATTR_UL] = tv_putc_ul, 234 [ATTR_INV | ATTR_UL] = tv_putc_ul_in, 235 [ATTR_BOLD] = tv_putc_bd, 236 [ATTR_BOLD | ATTR_INV] = tv_putc_bd_in, 237 [ATTR_BOLD | ATTR_UL] = tv_putc_bd_ul, 238 [ATTR_BOLD | ATTR_UL | ATTR_INV] = tv_putc_bd_ul_in, 239 /* no support for blink */ 240 [ATTR_BLINK] = tv_putc_nm, 241 [ATTR_BLINK | ATTR_INV] = tv_putc_in, 242 [ATTR_BLINK | ATTR_UL] = tv_putc_ul, 243 [ATTR_BLINK | ATTR_UL | ATTR_INV] = tv_putc_ul_in, 244 [ATTR_BLINK | ATTR_BOLD] = tv_putc_bd, 245 [ATTR_BLINK | ATTR_BOLD | ATTR_INV] = tv_putc_bd_in, 246 [ATTR_BLINK | ATTR_BOLD | ATTR_UL] = tv_putc_bd_ul, 247 [ATTR_BLINK | ATTR_BOLD | ATTR_UL | ATTR_INV] = tv_putc_bd_ul_in, 248}; 249 250/* 251 * simple put character function 252 */ 253static void 254tv_putc(struct ite_softc *ip, int ch, int y, int x, int mode) 255{ 256 uint8_t *p = CHADDR(y, x); 257 short fh; 258 259 /* multi page write mode */ 260 CRTC.r21 = 0x0100 | ip->fgcolor << 4; 261 262 /* draw plane */ 263 putc_func[mode](ip, ch, p); 264 265 /* erase plane */ 266 CRTC.r21 ^= 0x00f0; 267 if (ip->save_char) { 268 for (fh = 0; fh < FONTHEIGHT; fh++, p += ROWBYTES) 269 *(uint16_t *)p = 0; 270 } else { 271 for (fh = 0; fh < FONTHEIGHT; fh++, p += ROWBYTES) 272 *p = 0; 273 } 274 275 /* crtc mode reset */ 276 CRTC.r21 = 0; 277} 278 279static inline uint8_t * 280tv_getfont(int cset, int ch) 281{ 282 283 if (cset == CSET_JISKANA) { 284 ch |= 0x80; 285 } else if (cset == CSET_DECGRAPH) { 286 if (ch < 0x80) { 287 ch = ite_decgraph2ascii[ch]; 288 } 289 } 290 291 return tv_font[ch]; 292} 293 294static void 295tv_putc_nm(struct ite_softc *ip, int ch, char *p) 296{ 297 short fh, hi, lo; 298 volatile uint16_t *kf; 299 uint8_t *f; 300 301 hi = ip->save_char & 0x7f; 302 lo = ch & 0x7f; 303 304 if (hi >= 0x21 && hi <= 0x7e && lo >= 0x21 && lo <= 0x7e) { 305 /* multibyte character */ 306 kf = (volatile uint16_t *)tv_kfont[hi]; 307 kf += lo * FONTHEIGHT; 308 /* draw plane */ 309 for (fh = 0; fh < FONTHEIGHT; fh++, p += ROWBYTES) 310 *(uint16_t *)p = *kf++; 311 return; 312 } 313 314 /* singlebyte character */ 315 f = tv_getfont(*ip->GL, ch); 316 317 /* draw plane */ 318 for (fh = 0; fh < FONTHEIGHT; fh++, p += ROWBYTES) 319 *p = *f++; 320} 321 322static void 323tv_putc_in(struct ite_softc *ip, int ch, char *p) 324{ 325 short fh, hi, lo; 326 volatile uint16_t *kf; 327 uint8_t *f; 328 329 hi = ip->save_char & 0x7f; 330 lo = ch & 0x7f; 331 332 if (hi >= 0x21 && hi <= 0x7e && lo >= 0x21 && lo <= 0x7e) { 333 /* multibyte character */ 334 kf = (volatile uint16_t *)tv_kfont[hi]; 335 kf += lo * FONTHEIGHT; 336 /* draw plane */ 337 for (fh = 0; fh < FONTHEIGHT; fh++, p += ROWBYTES) 338 *(uint16_t *)p = ~*kf++; 339 return; 340 } 341 342 /* singlebyte character */ 343 f = tv_getfont(*ip->GL, ch); 344 345 /* draw plane */ 346 for (fh = 0; fh < FONTHEIGHT; fh++, p += ROWBYTES) 347 *p = ~*f++; 348} 349 350static void 351tv_putc_bd(struct ite_softc *ip, int ch, char *p) 352{ 353 short fh, hi, lo; 354 u_int data; 355 volatile uint16_t *kf; 356 uint8_t *f; 357 358 hi = ip->save_char & 0x7f; 359 lo = ch & 0x7f; 360 361 if (hi >= 0x21 && hi <= 0x7e && lo >= 0x21 && lo <= 0x7e) { 362 /* multibyte character */ 363 kf = (volatile uint16_t *)tv_kfont[hi]; 364 kf += lo * FONTHEIGHT; 365 /* draw plane */ 366 for (fh = 0; fh < FONTHEIGHT; fh++, p += ROWBYTES) { 367 data = *kf++; 368 *(uint16_t *)p = data | (data >> 1); 369 } 370 return; 371 } 372 373 /* singlebyte character */ 374 f = tv_getfont(*ip->GL, ch); 375 376 /* draw plane */ 377 for (fh = 0; fh < FONTHEIGHT; fh++, p += ROWBYTES) { 378 data = *f++; 379 *p = data | (data >> 1); 380 } 381} 382 383static inline uint32_t 384expbits(uint32_t data) 385{ 386 int i; 387 u_int nd = 0; 388 389 if ((data & 1) != 0) 390 nd |= 0x02; 391 for (i = 1; i < 32; i++) { 392 if ((data & (1 << i)) != 0) 393 nd |= 0x5 << (i - 1); 394 } 395 nd &= ~data; 396 return ~nd; 397} 398 399static void 400tv_putc_ul(struct ite_softc *ip, int ch, char *p) 401{ 402 short fh, hi, lo; 403 volatile uint16_t *kf; 404 uint8_t *f; 405 406 hi = ip->save_char & 0x7f; 407 lo = ch & 0x7f; 408 409 if (hi >= 0x21 && hi <= 0x7e && lo >= 0x21 && lo <= 0x7e) { 410 /* multibyte character */ 411 kf = (volatile uint16_t *)tv_kfont[hi]; 412 kf += lo * FONTHEIGHT; 413 /* draw plane */ 414 for (fh = 0; fh < UNDERLINE; fh++, p += ROWBYTES) 415 *(uint16_t *)p = *kf++; 416 *(uint16_t *)p = expbits(*kf++); 417 p += ROWBYTES; 418 for (fh++; fh < FONTHEIGHT; fh++, p += ROWBYTES) 419 *(uint16_t *)p = *kf++; 420 return; 421 } 422 423 /* singlebyte character */ 424 f = tv_getfont(*ip->GL, ch); 425 426 /* draw plane */ 427 for (fh = 0; fh < UNDERLINE; fh++, p += ROWBYTES) 428 *p = *f++; 429 *p = expbits(*f++); 430 p += ROWBYTES; 431 for (fh++; fh < FONTHEIGHT; fh++, p += ROWBYTES) 432 *p = *f++; 433} 434 435static void 436tv_putc_bd_in(struct ite_softc *ip, int ch, char *p) 437{ 438 short fh, hi, lo; 439 u_int data; 440 volatile uint16_t *kf; 441 uint8_t *f; 442 443 hi = ip->save_char & 0x7f; 444 lo = ch & 0x7f; 445 446 if (hi >= 0x21 && hi <= 0x7e && lo >= 0x21 && lo <= 0x7e) { 447 /* multibyte character */ 448 kf = (volatile uint16_t *)tv_kfont[hi]; 449 kf += lo * FONTHEIGHT; 450 /* draw plane */ 451 for (fh = 0; fh < FONTHEIGHT; fh++, p += ROWBYTES) { 452 data = *kf++; 453 *(uint16_t *)p = ~(data | (data >> 1)); 454 } 455 return; 456 } 457 458 /* singlebyte character */ 459 f = tv_getfont(*ip->GL, ch); 460 461 /* draw plane */ 462 for (fh = 0; fh < FONTHEIGHT; fh++, p += ROWBYTES) { 463 data = *f++; 464 *p = ~(data | (data >> 1)); 465 } 466} 467 468static void 469tv_putc_ul_in(struct ite_softc *ip, int ch, char *p) 470{ 471 short fh, hi, lo; 472 volatile uint16_t *kf; 473 uint8_t *f; 474 475 hi = ip->save_char & 0x7f; 476 lo = ch & 0x7f; 477 478 if (hi >= 0x21 && hi <= 0x7e && lo >= 0x21 && lo <= 0x7e) { 479 /* multibyte character */ 480 kf = (volatile uint16_t *)tv_kfont[hi]; 481 kf += lo * FONTHEIGHT; 482 /* draw plane */ 483 for (fh = 0; fh < UNDERLINE; fh++, p += ROWBYTES) 484 *(uint16_t *)p = ~*kf++; 485 *(uint16_t *)p = ~expbits(*kf++); 486 p += ROWBYTES; 487 for (fh++; fh < FONTHEIGHT; fh++, p += ROWBYTES) 488 *(uint16_t *)p = ~*kf++; 489 return; 490 } 491 492 /* singlebyte character */ 493 f = tv_getfont(*ip->GL, ch); 494 495 /* draw plane */ 496 for (fh = 0; fh < UNDERLINE; fh++, p += ROWBYTES) 497 *p = ~*f++; 498 *p = ~expbits(*f++); 499 p += ROWBYTES; 500 for (fh++; fh < FONTHEIGHT; fh++, p += ROWBYTES) 501 *p = ~*f++; 502} 503 504static void 505tv_putc_bd_ul(struct ite_softc *ip, int ch, char *p) 506{ 507 short fh, hi, lo; 508 u_int data; 509 volatile uint16_t *kf; 510 uint8_t *f; 511 512 hi = ip->save_char & 0x7f; 513 lo = ch & 0x7f; 514 515 if (hi >= 0x21 && hi <= 0x7e && lo >= 0x21 && lo <= 0x7e) { 516 /* multibyte character */ 517 kf = (volatile uint16_t *)tv_kfont[hi]; 518 kf += lo * FONTHEIGHT; 519 /* draw plane */ 520 for (fh = 0; fh < UNDERLINE; fh++, p += ROWBYTES) { 521 data = *kf++; 522 *(uint16_t *)p = data | (data >> 1); 523 } 524 data = *kf++; 525 *(uint16_t *)p = expbits(data | (data >> 1)); 526 p += ROWBYTES; 527 for (fh++; fh < FONTHEIGHT; fh++, p += ROWBYTES) { 528 data = *kf++; 529 *(uint16_t *)p = data | (data >> 1); 530 } 531 return; 532 } 533 534 /* singlebyte character */ 535 f = tv_getfont(*ip->GL, ch); 536 537 /* draw plane */ 538 for (fh = 0; fh < UNDERLINE; fh++, p += ROWBYTES) { 539 data = *f++; 540 *p = data | (data >> 1); 541 } 542 data = *f++; 543 *p = expbits(data | (data >> 1)); 544 p += ROWBYTES; 545 for (fh++; fh < FONTHEIGHT; fh++, p += ROWBYTES) { 546 data = *f++; 547 *p = data | (data >> 1); 548 } 549} 550 551static void 552tv_putc_bd_ul_in(struct ite_softc *ip, int ch, char *p) 553{ 554 short fh, hi, lo; 555 u_int data; 556 volatile uint16_t *kf; 557 uint8_t *f; 558 559 hi = ip->save_char & 0x7f; 560 lo = ch & 0x7f; 561 562 if (hi >= 0x21 && hi <= 0x7e && lo >= 0x21 && lo <= 0x7e) { 563 /* multibyte character */ 564 kf = (volatile uint16_t *)tv_kfont[hi]; 565 kf += lo * FONTHEIGHT; 566 /* draw plane */ 567 for (fh = 0; fh < UNDERLINE; fh++, p += ROWBYTES) { 568 data = *kf++; 569 *(uint16_t *)p = ~(data | (data >> 1)); 570 } 571 data = *kf++; 572 *(uint16_t *)p = ~expbits(data | (data >> 1)); 573 p += ROWBYTES; 574 for (fh++; fh < FONTHEIGHT; fh++, p += ROWBYTES) { 575 data = *kf++; 576 *(uint16_t *)p = ~(data | (data >> 1)); 577 } 578 return; 579 } 580 581 /* singlebyte character */ 582 f = tv_getfont(*ip->GL, ch); 583 584 /* draw plane */ 585 for (fh = 0; fh < UNDERLINE; fh++, p += ROWBYTES) { 586 data = *f++; 587 *p = ~(data | (data >> 1)); 588 } 589 data = *f++; 590 *p = ~expbits(data | (data >> 1)); 591 p += ROWBYTES; 592 for (fh++; fh < FONTHEIGHT; fh++, p += ROWBYTES) { 593 data = *f++; 594 data |= data >> 1; 595 *p = ~(data | (data >> 1)); 596 } 597} 598 599/* 600 * draw/erase/move cursor 601 */ 602static void 603tv_cursor(struct ite_softc *ip, int flag) 604{ 605 uint8_t *p; 606 short fh; 607 608 /* erase */ 609 switch (flag) { 610 /*case DRAW_CURSOR:*/ 611 /*case ERASE_CURSOR:*/ 612 /*case MOVE_CURSOR:*/ 613 case START_CURSOROPT: 614 /* 615 * old: ip->cursorx, ip->cursory 616 * new: ip->curx, ip->cury 617 */ 618 p = CHADDR(ip->cursory, ip->cursorx); 619 for (fh = 0; fh < FONTHEIGHT; fh++, p += ROWBYTES) 620 *p = ~*p; 621 break; 622 } 623 624 /* draw */ 625 switch (flag) { 626 /*case MOVE_CURSOR:*/ 627 case END_CURSOROPT: 628 /* 629 * Use exclusive-or. 630 */ 631 p = CHADDR(ip->cury, ip->curx); 632 for (fh = 0; fh < FONTHEIGHT; fh++, p += ROWBYTES) 633 *p = ~*p; 634 635 ip->cursorx = ip->curx; 636 ip->cursory = ip->cury; 637 break; 638 } 639} 640 641/* 642 * clear rectangle 643 */ 644static void 645tv_clear(struct ite_softc *ip, int y, int x, int height, int width) 646{ 647 uint8_t *p; 648 short fh; 649 650 /* XXX: reset scroll register on clearing whole screen */ 651 if (y == 0 && x == 0 && height == ip->rows && width == ip->cols) { 652 CRTC.r10 = 0; 653 CRTC.r11 = tv_top * FONTHEIGHT; 654 } 655 656 CRTC.r21 = 0x01f0; 657 while (height--) { 658 p = CHADDR(y++, x); 659 for (fh = 0; fh < FONTHEIGHT; fh++, p += ROWBYTES) 660 memset(p, 0, width); 661 } 662 /* crtc mode reset */ 663 CRTC.r21 = 0; 664} 665 666/* 667 * scroll lines/columns 668 */ 669static void 670tv_scroll(struct ite_softc *ip, int srcy, int srcx, int count, int dir) 671{ 672 int dst, siz, pl; 673 674 switch (dir) { 675 case SCROLL_UP: 676 /* 677 * src: srcy 678 * dst: (srcy - count) 679 * siz: (ip->bottom_margin - sy + 1) 680 */ 681 dst = srcy - count; 682 siz = ip->bottom_margin - srcy + 1; 683 if (dst == 0 && ip->bottom_margin == ip->rows - 1) { 684 /* special case, hardware scroll */ 685 tv_top = (tv_top + count) % PLANELINES; 686 CRTC.r11 = tv_top * FONTHEIGHT; 687 } else { 688 srcy = PHYSLINE(srcy); 689 dst = PHYSLINE(dst); 690 txrascpy(srcy, dst, siz, 0x0f); 691 } 692 break; 693 694 case SCROLL_DOWN: 695 /* 696 * src: srcy 697 * dst: (srcy + count) 698 * siz: (ip->bottom_margin - dy + 1) 699 */ 700 dst = srcy + count; 701 siz = ip->bottom_margin - dst + 1; 702 if (srcy == 0 && ip->bottom_margin == ip->rows - 1) { 703 /* special case, hardware scroll */ 704 tv_top = (tv_top + PLANELINES - count) % PLANELINES; 705 CRTC.r11 = tv_top * FONTHEIGHT; 706 } else { 707 srcy = PHYSLINE(srcy) + siz - 1; 708 dst = PHYSLINE(dst) + siz - 1; 709 txrascpy(srcy, dst, siz, 0x0f | 0x8000); 710 } 711 break; 712 713 case SCROLL_LEFT: 714 for (pl = 0; pl < PLANESIZE * 4; pl += PLANESIZE) { 715 short fh; 716 uint8_t *src = CHADDR(srcy, srcx) + pl; 717 uint8_t *dest = CHADDR(srcy, srcx - count) + pl; 718 719 siz = ip->cols - srcx; 720 for (fh = 0; fh < FONTHEIGHT; fh++) { 721 memcpy(dest, src, siz); 722 src += ROWBYTES; 723 dest += ROWBYTES; 724 } 725 } 726 break; 727 728 case SCROLL_RIGHT: 729 for (pl = 0; pl < PLANESIZE * 4; pl += PLANESIZE) { 730 short fh; 731 uint8_t *src = CHADDR(srcy, srcx) + pl; 732 uint8_t *dest = CHADDR(srcy, srcx + count) + pl; 733 734 siz = ip->cols - (srcx + count); 735 for (fh = 0; fh < FONTHEIGHT; fh++) { 736 memcpy(dest, src, siz); 737 src += ROWBYTES; 738 dest += ROWBYTES; 739 } 740 } 741 break; 742 } 743} 744