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