ite_tv.c revision 1.2
1/*	$NetBSD: ite_tv.c,v 1.2 1997/02/03 21:40:45 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
66u_int  tv_top;
67u_char *tv_row[PLANELINES];
68char   *tv_font[256];
69__volatile char *tv_kfont[0x7f];
70
71u_char kern_font[256 * FONTHEIGHT];
72u_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) * FONTHEIGHT * 0x5e - 0x21 * FONTHEIGHT)
80
81/* prototype */
82void tv_init	__P((struct ite_softc *));
83void tv_deinit	__P((struct ite_softc *));
84void tv_putc	__P((struct ite_softc *, int, int, int, int));
85void tv_cursor	__P((struct ite_softc *, int));
86void tv_clear	__P((struct ite_softc *, int, int, int, int));
87void tv_scroll	__P((struct ite_softc *, int, int, int, int));
88
89
90static __inline void
91txrascpy (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 */
143void
144tv_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 */
205void
206tv_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
213typedef void tv_putcfunc __P((struct ite_softc *, int, char *));
214static tv_putcfunc tv_putc_nm;
215static tv_putcfunc tv_putc_in;
216static tv_putcfunc tv_putc_ul;
217static tv_putcfunc tv_putc_ul_in;
218static tv_putcfunc tv_putc_bd;
219static tv_putcfunc tv_putc_bd_in;
220static tv_putcfunc tv_putc_bd_ul;
221static tv_putcfunc tv_putc_bd_ul_in;
222
223static 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 */
246void
247tv_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
274void
275tv_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
306void
307tv_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
338void
339tv_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
374static __inline int
375expbits (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
389void
390tv_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
429void
430tv_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
465void
466tv_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
505void
506tv_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
555void
556tv_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 */
609void
610tv_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 */
653void
654tv_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 */
674void
675tv_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