ite_tv.c revision 1.12 1 /* $NetBSD: ite_tv.c,v 1.12 2005/06/13 00:14:52 he 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.12 2005/06/13 00:14:52 he 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 u_int tv_top;
73 u_char *tv_row[PLANELINES];
74 char *tv_font[256];
75 __volatile char *tv_kfont[0x7f];
76
77 u_char 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) memcpy(&kern_font[(from)*16],&kern_font[(to)*16], 16)
84 #define KFONTBASE(left) ((left) * 32 * 0x5e - 0x21 * 32)
85
86 /* prototype */
87 void tv_init(struct ite_softc *);
88 void tv_deinit(struct ite_softc *);
89 void tv_putc(struct ite_softc *, int, int, int, int);
90 void tv_cursor(struct ite_softc *, int);
91 void tv_clear(struct ite_softc *, int, int, int, int);
92 void tv_scroll(struct ite_softc *, int, int, int, int);
93
94 __inline static int expbits(int);
95 __inline static void txrascpy(u_char, u_char, short, signed short);
96
97 static __inline void
98 txrascpy(u_char src, u_char dst, short size, 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(struct ite_softc *ip)
160 {
161 short i;
162
163 /*
164 * initialize private variables
165 */
166 tv_top = 0;
167 for (i = 0; i < PLANELINES; i++)
168 tv_row[i] = (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 * Intialize 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 ip->flags &= ~ITE_INITED; /* XXX? */
216 }
217
218 typedef void tv_putcfunc(struct ite_softc *, int, char *);
219 static tv_putcfunc tv_putc_nm;
220 static tv_putcfunc tv_putc_in;
221 static tv_putcfunc tv_putc_ul;
222 static tv_putcfunc tv_putc_ul_in;
223 static tv_putcfunc tv_putc_bd;
224 static tv_putcfunc tv_putc_bd_in;
225 static tv_putcfunc tv_putc_bd_ul;
226 static tv_putcfunc tv_putc_bd_ul_in;
227
228 static tv_putcfunc *putc_func[ATTR_ALL + 1] = {
229 tv_putc_nm,
230 tv_putc_in,
231 tv_putc_ul,
232 tv_putc_ul_in,
233 tv_putc_bd,
234 tv_putc_bd_in,
235 tv_putc_bd_ul,
236 tv_putc_bd_ul_in,
237 /* no support for blink */
238 tv_putc_nm,
239 tv_putc_in,
240 tv_putc_ul,
241 tv_putc_ul_in,
242 tv_putc_bd,
243 tv_putc_bd_in,
244 tv_putc_bd_ul,
245 tv_putc_bd_ul_in,
246 };
247
248 /*
249 * simple put character function
250 */
251 void
252 tv_putc(struct ite_softc *ip, int ch, int y, int x, int mode)
253 {
254 char *p = CHADDR(y, x);
255 short fh;
256
257 /* multi page write mode */
258 CRTC.r21 = 0x0100 | ip->fgcolor << 4;
259
260 /* draw plane */
261 putc_func[mode](ip, ch, p);
262
263 /* erase plane */
264 CRTC.r21 ^= 0x00f0;
265 if (ip->save_char) {
266 for (fh = 0; fh < FONTHEIGHT; fh++, p += ROWBYTES)
267 *(u_short *)p = 0;
268 } else {
269 for (fh = 0; fh < FONTHEIGHT; fh++, p += ROWBYTES)
270 *p = 0;
271 }
272
273 /* crtc mode reset */
274 CRTC.r21 = 0;
275 }
276
277 void
278 tv_putc_nm(struct ite_softc *ip, int ch, char *p)
279 {
280 short fh, hi;
281 char *f;
282 volatile short *kf;
283
284 hi = ip->save_char & 0x7f;
285
286 if (hi >= 0x21 && hi <= 0x7e) {
287 /* multibyte character */
288 kf = (volatile 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(struct ite_softc *ip, int ch, char *p)
308 {
309 short fh, hi;
310 char *f;
311 volatile short *kf;
312
313 hi = ip->save_char & 0x7f;
314
315 if (hi >= 0x21 && hi <= 0x7e) {
316 /* multibyte character */
317 kf = (volatile short *)tv_kfont[hi];
318 kf += (ch & 0x7f) * FONTHEIGHT;
319 /* draw plane */
320 for (fh = 0; fh < FONTHEIGHT; fh++, p += ROWBYTES)
321 *(u_short *)p = ~*kf++;
322 return;
323 }
324
325 /* singlebyte character */
326 if (*ip->GL == CSET_JISKANA)
327 ch |= 0x80;
328 f = tv_font[ch];
329
330 /* draw plane */
331 for (fh = 0; fh < FONTHEIGHT; fh++, p += ROWBYTES)
332 *p = ~*f++;
333 }
334
335 void
336 tv_putc_bd(struct ite_softc *ip, int ch, char *p)
337 {
338 short fh, hi;
339 char *f;
340 volatile short *kf;
341
342 hi = ip->save_char & 0x7f;
343
344 if (hi >= 0x21 && hi <= 0x7e) {
345 /* multibyte character */
346 kf = (volatile short *)tv_kfont[hi];
347 kf += (ch & 0x7f) * FONTHEIGHT;
348 /* draw plane */
349 for (fh = 0; fh < FONTHEIGHT; fh++, p += ROWBYTES) {
350 ch = *kf++;
351 *(u_short *)p = ch | (ch >> 1);
352 }
353 return;
354 }
355
356 /* singlebyte character */
357 if (*ip->GL == CSET_JISKANA)
358 ch |= 0x80;
359 f = tv_font[ch];
360
361 /* draw plane */
362 for (fh = 0; fh < FONTHEIGHT; fh++, p += ROWBYTES) {
363 ch = *f++;
364 *p = ch | (ch >> 1);
365 }
366 }
367
368 __inline static int
369 expbits(int data)
370 {
371 int i, nd = 0;
372 if (data & 1)
373 nd |= 0x02;
374 for (i=1; i < 32; i++) {
375 if (data & (1 << i))
376 nd |= 0x5 << (i-1);
377 }
378 nd &= ~data;
379 return (~nd);
380 }
381
382 void
383 tv_putc_ul(struct ite_softc *ip, int ch, char *p)
384 {
385 short fh, hi;
386 char *f;
387 volatile short *kf;
388
389 hi = ip->save_char & 0x7f;
390
391 if (hi >= 0x21 && hi <= 0x7e) {
392 /* multibyte character */
393 kf = (volatile short *)tv_kfont[hi];
394 kf += (ch & 0x7f) * FONTHEIGHT;
395 /* draw plane */
396 for (fh = 0; fh < UNDERLINE; fh++, p += ROWBYTES)
397 *(u_short *)p = *kf++;
398 *(u_short *)p = expbits(*kf++);
399 p += ROWBYTES;
400 for (fh++; fh < FONTHEIGHT; fh++, p += ROWBYTES)
401 *(u_short *)p = *kf++;
402 return;
403 }
404
405 /* singlebyte character */
406 if (*ip->GL == CSET_JISKANA)
407 ch |= 0x80;
408 f = tv_font[ch];
409
410 /* draw plane */
411 for (fh = 0; fh < UNDERLINE; fh++, p += ROWBYTES)
412 *p = *f++;
413 *p = expbits(*f++);
414 p += ROWBYTES;
415 for (fh++; fh < FONTHEIGHT; fh++, p += ROWBYTES)
416 *p = *f++;
417 }
418
419 void
420 tv_putc_bd_in(struct ite_softc *ip, int ch, char *p)
421 {
422 short fh, hi;
423 char *f;
424 volatile short *kf;
425
426 hi = ip->save_char & 0x7f;
427
428 if (hi >= 0x21 && hi <= 0x7e) {
429 /* multibyte character */
430 kf = (volatile short *)tv_kfont[hi];
431 kf += (ch & 0x7f) * FONTHEIGHT;
432 /* draw plane */
433 for (fh = 0; fh < FONTHEIGHT; fh++, p += ROWBYTES) {
434 ch = *kf++;
435 *(u_short *)p = ~(ch | (ch >> 1));
436 }
437 return;
438 }
439
440 /* singlebyte character */
441 if (*ip->GL == CSET_JISKANA)
442 ch |= 0x80;
443 f = tv_font[ch];
444
445 /* draw plane */
446 for (fh = 0; fh < FONTHEIGHT; fh++, p += ROWBYTES) {
447 ch = *f++;
448 *p = ~(ch | (ch >> 1));
449 }
450 }
451
452 void
453 tv_putc_ul_in(struct ite_softc *ip, int ch, char *p)
454 {
455 short fh, hi;
456 char *f;
457 volatile short *kf;
458
459 hi = ip->save_char & 0x7f;
460
461 if (hi >= 0x21 && hi <= 0x7e) {
462 /* multibyte character */
463 kf = (volatile short *)tv_kfont[hi];
464 kf += (ch & 0x7f) * FONTHEIGHT;
465 /* draw plane */
466 for (fh = 0; fh < UNDERLINE; fh++, p += ROWBYTES)
467 *(u_short *)p = ~*kf++;
468 *(u_short *)p = ~expbits(*kf++);
469 p += ROWBYTES;
470 for (fh++; fh < FONTHEIGHT; fh++, p += ROWBYTES)
471 *(u_short *)p = ~*kf++;
472 return;
473 }
474
475 /* singlebyte character */
476 if (*ip->GL == CSET_JISKANA)
477 ch |= 0x80;
478 f = tv_font[ch];
479
480 /* draw plane */
481 for (fh = 0; fh < UNDERLINE; fh++, p += ROWBYTES)
482 *p = ~*f++;
483 *p = ~expbits(*f++);
484 p += ROWBYTES;
485 for (fh++; fh < FONTHEIGHT; fh++, p += ROWBYTES)
486 *p = ~*f++;
487 }
488
489 void
490 tv_putc_bd_ul(struct ite_softc *ip, int ch, char *p)
491 {
492 short fh, hi;
493 char *f;
494 volatile short *kf;
495
496 hi = ip->save_char & 0x7f;
497
498 if (hi >= 0x21 && hi <= 0x7e) {
499 /* multibyte character */
500 kf = (volatile short *)tv_kfont[hi];
501 kf += (ch & 0x7f) * FONTHEIGHT;
502 /* draw plane */
503 for (fh = 0; fh < UNDERLINE; fh++, p += ROWBYTES) {
504 ch = *kf++;
505 *(u_short *)p = ch | (ch >> 1);
506 }
507 ch = *kf++;
508 *(u_short *)p = expbits(ch | (ch >> 1));
509 p += ROWBYTES;
510 for (fh++; fh < FONTHEIGHT; fh++, p += ROWBYTES) {
511 ch = *kf++;
512 *(u_short *)p = ch | (ch >> 1);
513 }
514 return;
515 }
516
517 /* singlebyte character */
518 if (*ip->GL == CSET_JISKANA)
519 ch |= 0x80;
520 f = tv_font[ch];
521
522 /* draw plane */
523 for (fh = 0; fh < UNDERLINE; fh++, p += ROWBYTES) {
524 ch = *f++;
525 *p = ch | (ch >> 1);
526 }
527 ch = *f++;
528 *p = expbits(ch | (ch >> 1));
529 p += ROWBYTES;
530 for (fh++; fh < FONTHEIGHT; fh++, p += ROWBYTES) {
531 ch = *f++;
532 *p = ch | (ch >> 1);
533 }
534 }
535
536 void
537 tv_putc_bd_ul_in(struct ite_softc *ip, int ch, char *p)
538 {
539 short fh, hi;
540 char *f;
541 volatile short *kf;
542
543 hi = ip->save_char & 0x7f;
544
545 if (hi >= 0x21 && hi <= 0x7e) {
546 /* multibyte character */
547 kf = (volatile short *)tv_kfont[hi];
548 kf += (ch & 0x7f) * FONTHEIGHT;
549 /* draw plane */
550 for (fh = 0; fh < UNDERLINE; fh++, p += ROWBYTES) {
551 ch = *kf++;
552 *(u_short *)p = ~(ch | (ch >> 1));
553 }
554 ch = *kf++;
555 *(u_short *)p = ~expbits(ch | (ch >> 1));
556 p += ROWBYTES;
557 for (fh++; fh < FONTHEIGHT; fh++, p += ROWBYTES) {
558 ch = *kf++;
559 *(u_short *)p = ~(ch | (ch >> 1));
560 }
561 return;
562 }
563
564 /* singlebyte character */
565 if (*ip->GL == CSET_JISKANA)
566 ch |= 0x80;
567 f = tv_font[ch];
568
569 /* draw plane */
570 for (fh = 0; fh < UNDERLINE; fh++, p += ROWBYTES) {
571 ch = *f++;
572 *p = ~(ch | (ch >> 1));
573 }
574 ch = *f++;
575 *p = ~expbits(ch | (ch >> 1));
576 p += ROWBYTES;
577 for (fh++; fh < FONTHEIGHT; fh++, p += ROWBYTES) {
578 ch = *f++;
579 ch |= ch >> 1;
580 *p = ~(ch | (ch >> 1));
581 }
582 }
583
584 /*
585 * draw/erase/move cursor
586 */
587 void
588 tv_cursor(struct ite_softc *ip, int flag)
589 {
590 u_char *p;
591 short fh;
592
593 /* erase */
594 switch (flag) {
595 /*case DRAW_CURSOR:*/
596 /*case ERASE_CURSOR:*/
597 /*case MOVE_CURSOR:*/
598 case START_CURSOROPT:
599 /*
600 * old: ip->cursorx, ip->cursory
601 * new: ip->curx, ip->cury
602 */
603 p = CHADDR(ip->cursory, ip->cursorx);
604 for (fh = 0; fh < FONTHEIGHT; fh++, p += ROWBYTES)
605 *p = ~*p;
606 break;
607 }
608
609 /* draw */
610 switch (flag) {
611 /*case MOVE_CURSOR:*/
612 case END_CURSOROPT:
613 /*
614 * Use exclusive-or.
615 */
616 p = CHADDR(ip->cury, ip->curx);
617 for (fh = 0; fh < FONTHEIGHT; fh++, p += ROWBYTES)
618 *p = ~*p;
619
620 ip->cursorx = ip->curx;
621 ip->cursory = ip->cury;
622 break;
623 }
624 }
625
626 /*
627 * clear rectangle
628 */
629 void
630 tv_clear(struct ite_softc *ip, int y, int x, int height, int width)
631 {
632 char *p;
633 short fh;
634
635 /* XXX: reset scroll register on clearing whole screen */
636 if (y == 0 && x == 0 && height == ip->rows && width == ip->cols) {
637 CRTC.r10 = 0;
638 CRTC.r11 = tv_top * FONTHEIGHT;
639 }
640
641 CRTC.r21 = 0x01f0;
642 while (height--) {
643 p = CHADDR(y++, x);
644 for (fh = 0; fh < FONTHEIGHT; fh++, p += ROWBYTES)
645 memset(p, 0, width);
646 }
647 /* crtc mode reset */
648 CRTC.r21 = 0;
649 }
650
651 /*
652 * scroll lines/columns
653 */
654 void
655 tv_scroll(struct ite_softc *ip, int srcy, int srcx, int count, int dir)
656 {
657 int dst, siz, pl;
658
659 switch (dir) {
660 case SCROLL_UP:
661 /*
662 * src: srcy
663 * dst: (srcy - count)
664 * siz: (ip->bottom_margin - sy + 1)
665 */
666 dst = srcy - count;
667 siz = ip->bottom_margin - srcy + 1;
668 if (dst == 0 && ip->bottom_margin == ip->rows - 1) {
669 /* special case, hardware scroll */
670 tv_top = (tv_top + count) % PLANELINES;
671 CRTC.r11 = tv_top * FONTHEIGHT;
672 } else {
673 srcy = PHYSLINE(srcy);
674 dst = PHYSLINE(dst);
675 txrascpy(srcy, dst, siz, 0x0f);
676 }
677 break;
678
679 case SCROLL_DOWN:
680 /*
681 * src: srcy
682 * dst: (srcy + count)
683 * siz: (ip->bottom_margin - dy + 1)
684 */
685 dst = srcy + count;
686 siz = ip->bottom_margin - dst + 1;
687 if (srcy == 0 && ip->bottom_margin == ip->rows - 1) {
688 /* special case, hardware scroll */
689 tv_top = (tv_top + PLANELINES - count) % PLANELINES;
690 CRTC.r11 = tv_top * FONTHEIGHT;
691 } else {
692 srcy = PHYSLINE(srcy) + siz - 1;
693 dst = PHYSLINE(dst) + siz - 1;
694 txrascpy(srcy, dst, siz, 0x0f | 0x8000);
695 }
696 break;
697
698 case SCROLL_LEFT:
699 for (pl = 0; pl < PLANESIZE * 4; pl += PLANESIZE) {
700 short fh;
701 char *src = CHADDR(srcy, srcx) + pl;
702 char *dest = CHADDR(srcy, srcx - count) + pl;
703
704 siz = ip->cols - srcx;
705 for (fh = 0; fh < FONTHEIGHT; fh++) {
706 memcpy(dest, src, siz);
707 src += ROWBYTES;
708 dest += ROWBYTES;
709 }
710 }
711 break;
712
713 case SCROLL_RIGHT:
714 for (pl = 0; pl < PLANESIZE * 4; pl += PLANESIZE) {
715 short fh;
716 char *src = CHADDR(srcy, srcx) + pl;
717 char *dest = CHADDR(srcy, srcx + count) + pl;
718
719 siz = ip->cols - (srcx + count);
720 for (fh = 0; fh < FONTHEIGHT; fh++) {
721 memcpy(dest, src, siz);
722 src += ROWBYTES;
723 dest += ROWBYTES;
724 }
725 }
726 break;
727 }
728 }
729