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