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