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