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