xref: /netbsd-src/sys/arch/x68k/dev/ite_tv.c (revision 867d70fc718005c0918b8b8b2f9d7f2d52d0a0db)
1 /*	$NetBSD: ite_tv.c,v 1.19 2022/06/25 03:57:17 tsutsui 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.19 2022/06/25 03:57:17 tsutsui 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