Home | History | Annotate | Line # | Download | only in dev
ite_tv.c revision 1.20
      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 
     72 static u_int  tv_top;
     73 static uint8_t *tv_row[PLANELINES];
     74 static uint8_t *tv_font[256];
     75 static volatile uint8_t *tv_kfont[0x7f];
     76 
     77 uint8_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 */
     88 static void tv_putc(struct ite_softc *, int, int, int, int);
     89 static void tv_cursor(struct ite_softc *, int);
     90 static void tv_clear(struct ite_softc *, int, int, int, int);
     91 static void tv_scroll(struct ite_softc *, int, int, int, int);
     92 
     93 static inline uint32_t expbits(uint32_t);
     94 static inline void txrascpy(uint8_t, uint8_t, int16_t, uint16_t);
     95 
     96 static inline void
     97 txrascpy(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  */
    141 void
    142 ite_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  */
    157 void
    158 tv_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  */
    212 void
    213 tv_deinit(struct ite_softc *ip)
    214 {
    215 
    216 	ip->flags &= ~ITE_INITED; /* XXX? */
    217 }
    218 
    219 static inline uint8_t *tv_getfont(int, int);
    220 typedef void tv_putcfunc(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 	[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  */
    253 static void
    254 tv_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 
    279 static inline uint8_t *
    280 tv_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 
    294 static void
    295 tv_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 
    322 static void
    323 tv_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 
    350 static void
    351 tv_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 
    383 static inline uint32_t
    384 expbits(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 
    399 static void
    400 tv_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 
    435 static void
    436 tv_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 
    468 static void
    469 tv_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 
    504 static void
    505 tv_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 
    551 static void
    552 tv_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  */
    602 static void
    603 tv_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  */
    644 static void
    645 tv_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  */
    669 static void
    670 tv_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