Home | History | Annotate | Line # | Download | only in dev
ite_tv.c revision 1.15
      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 
     72 u_int  tv_top;
     73 u_char *tv_row[PLANELINES];
     74 char   *tv_font[256];
     75 volatile char *tv_kfont[0x7f];
     76 
     77 u_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 */
     87 void tv_init(struct ite_softc *);
     88 void tv_deinit(struct ite_softc *);
     89 void tv_putc(struct ite_softc *, int, int, int, int);
     90 void tv_cursor(struct ite_softc *, int);
     91 void tv_clear(struct ite_softc *, int, int, int, int);
     92 void tv_scroll(struct ite_softc *, int, int, int, int);
     93 
     94 inline static int expbits(int);
     95 inline static void txrascpy(u_char, u_char, short, signed short);
     96 
     97 static inline void
     98 txrascpy(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  */
    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(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  */
    212 void
    213 tv_deinit(struct ite_softc *ip)
    214 {
    215 	ip->flags &= ~ITE_INITED; /* XXX? */
    216 }
    217 
    218 typedef void tv_putcfunc(struct ite_softc *, int, char *);
    219 static tv_putcfunc tv_putc_nm;
    220 static tv_putcfunc tv_putc_in;
    221 static tv_putcfunc tv_putc_ul;
    222 static tv_putcfunc tv_putc_ul_in;
    223 static tv_putcfunc tv_putc_bd;
    224 static tv_putcfunc tv_putc_bd_in;
    225 static tv_putcfunc tv_putc_bd_ul;
    226 static tv_putcfunc tv_putc_bd_ul_in;
    227 
    228 static 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  */
    251 void
    252 tv_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 
    277 void
    278 tv_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) {
    287 		/* multibyte character */
    288 		kf = (volatile short *)tv_kfont[hi];
    289 		kf += (ch & 0x7f) * 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 
    306 void
    307 tv_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) {
    316 		/* multibyte character */
    317 		kf = (volatile short *)tv_kfont[hi];
    318 		kf += (ch & 0x7f) * 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 
    335 void
    336 tv_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) {
    345 		/* multibyte character */
    346 		kf = (volatile short *)tv_kfont[hi];
    347 		kf += (ch & 0x7f) * 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 
    368 inline static int
    369 expbits(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 
    382 void
    383 tv_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) {
    392 		/* multibyte character */
    393 		kf = (volatile short *)tv_kfont[hi];
    394 		kf += (ch & 0x7f) * 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 
    419 void
    420 tv_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) {
    429 		/* multibyte character */
    430 		kf = (volatile short *)tv_kfont[hi];
    431 		kf += (ch & 0x7f) * 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 
    452 void
    453 tv_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) {
    462 		/* multibyte character */
    463 		kf = (volatile short *)tv_kfont[hi];
    464 		kf += (ch & 0x7f) * 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 
    489 void
    490 tv_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) {
    499 		/* multibyte character */
    500 		kf = (volatile short *)tv_kfont[hi];
    501 		kf += (ch & 0x7f) * 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 
    536 void
    537 tv_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) {
    546 		/* multibyte character */
    547 		kf = (volatile short *)tv_kfont[hi];
    548 		kf += (ch & 0x7f) * 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  */
    587 void
    588 tv_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  */
    629 void
    630 tv_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  */
    654 void
    655 tv_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