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