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