1 /* $NetBSD: bmd.c,v 1.10 2024/07/05 19:28:36 andvar Exp $ */
2
3 /*
4 * Copyright (c) 1992 OMRON Corporation.
5 *
6 * This code is derived from software contributed to Berkeley by
7 * OMRON Corporation.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by the University of
20 * California, Berkeley and its contributors.
21 * 4. Neither the name of the University nor the names of its contributors
22 * may be used to endorse or promote products derived from this software
23 * without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 *
37 * @(#)bmd.c 8.2 (Berkeley) 8/15/93
38 */
39 /*
40 * Copyright (c) 1992, 1993
41 * The Regents of the University of California. All rights reserved.
42 *
43 * This code is derived from software contributed to Berkeley by
44 * OMRON Corporation.
45 *
46 * Redistribution and use in source and binary forms, with or without
47 * modification, are permitted provided that the following conditions
48 * are met:
49 * 1. Redistributions of source code must retain the above copyright
50 * notice, this list of conditions and the following disclaimer.
51 * 2. Redistributions in binary form must reproduce the above copyright
52 * notice, this list of conditions and the following disclaimer in the
53 * documentation and/or other materials provided with the distribution.
54 * 3. Neither the name of the University nor the names of its contributors
55 * may be used to endorse or promote products derived from this software
56 * without specific prior written permission.
57 *
58 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
59 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
60 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
61 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
62 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
63 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
64 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
65 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
66 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
67 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
68 * SUCH DAMAGE.
69 *
70 * @(#)bmd.c 8.2 (Berkeley) 8/15/93
71 */
72 /*
73
74 * bmd.c --- Bitmap-Display raw-level driver routines
75 *
76 * by A.Fujita, SEP-09-1992
77 */
78
79
80 #include <sys/param.h>
81 #include <luna68k/stand/boot/samachdep.h>
82 #include <machine/board.h>
83
84 /*
85 * RFCNT register
86 */
87
88 union bmd_rfcnt {
89 struct {
90 int16_t rfc_hcnt;
91 int16_t rfc_vcnt;
92 } p;
93 uint32_t u;
94 };
95
96 #define isprint(c) ((c) >= 0x20 && (c) < 0x7f)
97
98 /*
99 * Width & Height
100 */
101
102 #define BMAP_OFFSET 8
103
104 #define PB_WIDTH 2048 /* Plane Width (Bit) */
105 #define PB_HEIGHT 1024 /* Plane Height (Bit) */
106 #define PL_WIDTH 64 /* Plane Width (long) */
107 #define PS_WIDTH 128 /* Plane Width (long) */
108 #define P_WIDTH 256 /* Plane Width (Byte) */
109
110 #define SB_WIDTH 1280 /* Screen Width (Bit) */
111 #define SB_HEIGHT 1024 /* Screen Height (Bit) */
112 #define SL_WIDTH 40 /* Screen Width (Long) */
113 #define S_WIDTH 160 /* Screen Width (Byte) */
114
115 #define FB_WIDTH 12 /* Font Width (Bit) */
116 #define FB_HEIGHT 20 /* Font Height (Bit) */
117
118
119 #define NEXT_LINE(addr) (addr + (PL_WIDTH * FB_HEIGHT))
120 #define SKIP_NEXT_LINE(addr) (addr += (PL_WIDTH - SL_WIDTH))
121
122
123 static void bmd_draw_char(uint8_t *, uint8_t *, int, int, int);
124 static void bmd_reverse_char(uint8_t *, uint8_t *, int, int);
125 static void bmd_erase_char(uint8_t *, uint8_t *, int, int);
126 static void bmd_erase_screen(volatile uint32_t *);
127 static void bmd_scroll_screen(volatile uint32_t *, volatile uint32_t *,
128 int, int, int, int);
129
130
131 struct bmd_linec {
132 struct bmd_linec *bl_next;
133 struct bmd_linec *bl_prev;
134 int bl_col;
135 int bl_end;
136 uint8_t bl_line[128];
137 };
138
139 struct bmd_softc {
140 int bc_stat;
141 uint8_t *bc_raddr;
142 uint8_t *bc_waddr;
143 int bc_xmin;
144 int bc_xmax;
145 int bc_ymin;
146 int bc_ymax;
147 int bc_col;
148 int bc_row;
149 struct bmd_linec *bc_bl;
150 char bc_escseq[8];
151 char *bc_esc;
152 void (*bc_escape)(int);
153 };
154
155 #define STAT_NORMAL 0x0000
156 #define STAT_ESCAPE 0x0001
157 #define STAT_INSERT 0x0100
158
159 static struct bmd_softc bmd_softc;
160 static struct bmd_linec bmd_linec[52];
161
162 static void bmd_escape(int);
163 static void bmd_escape_0(int);
164 #if 0
165 static void bmd_escape_1(int);
166 #endif
167
168
169 /*
170 * Escape-Sequence
171 */
172
173 static void
bmd_escape(int c)174 bmd_escape(int c)
175 {
176 struct bmd_softc *bp = &bmd_softc;
177
178 switch (c) {
179
180 case '[':
181 bp->bc_escape = bmd_escape_0;
182 break;
183
184 default:
185 bp->bc_stat &= ~STAT_ESCAPE;
186 bp->bc_esc = &bp->bc_escseq[0];
187 bp->bc_escape = bmd_escape;
188 break;
189 }
190 }
191
192 static void
bmd_escape_0(int c)193 bmd_escape_0(int c)
194 {
195 struct bmd_softc *bp = &bmd_softc;
196 struct bmd_linec *bq = bp->bc_bl;
197
198 switch (c) {
199
200 case 'A':
201 if (bp->bc_row > bp->bc_ymin) {
202 bp->bc_row--;
203 }
204 break;
205
206 case 'C':
207 if (bq->bl_col < bp->bc_xmax - 1) {
208 bq->bl_col++;
209 }
210 break;
211
212 case 'K':
213 if (bq->bl_col < bp->bc_xmax) {
214 int col;
215 for (col = bq->bl_col; col < bp->bc_xmax; col++)
216 bmd_erase_char(bp->bc_raddr,
217 bp->bc_waddr,
218 col, bp->bc_row);
219 }
220 bq->bl_end = bq->bl_col;
221 break;
222
223 case 'H':
224 bq->bl_col = bq->bl_end = bp->bc_xmin;
225 bp->bc_row = bp->bc_ymin;
226 break;
227
228 default:
229 #if 0
230 *bp->bc_esc++ = c;
231 bp->bc_escape = bmd_escape_1;
232 return;
233 #endif
234 break;
235 }
236
237 bp->bc_stat &= ~STAT_ESCAPE;
238 bp->bc_esc = &bp->bc_escseq[0];
239 bp->bc_escape = bmd_escape;
240 }
241
242 #if 0
243 static void
244 bmd_escape_1(int c)
245 {
246 struct bmd_softc *bp = &bmd_softc;
247 struct bmd_linec *bq = bp->bc_bl;
248 int col = 0, row = 0;
249 char *p;
250
251 switch (c) {
252
253 case 'J':
254 bp->bc_stat &= ~STAT_ESCAPE;
255 bp->bc_esc = &bp->bc_escseq[0];
256 bp->bc_escape = bmd_escape;
257 break;
258
259 case 'H':
260 for (p = &bp->bc_escseq[0]; *p != ';'; p++)
261 row = (row * 10) + (*p - 0x30);
262 p++;
263 for (p = &bp->bc_escseq[0]; p != bp->bc_esc; p++)
264 col = (col * 10) + (*p - 0x30);
265
266 bq->bl_col = col + bp->bc_xmin;
267 bp->bc_row = row + bp->bc_ymin;
268
269 bp->bc_stat &= ~STAT_ESCAPE;
270 bp->bc_esc = &bp->bc_escseq[0];
271 bp->bc_escape = bmd_escape;
272 break;
273
274 default:
275 *bp->bc_esc++ = c;
276 break;
277 }
278 }
279 #endif
280
281 /*
282 * Entry Routine
283 */
284
285 void
bmdinit(void)286 bmdinit(void)
287 {
288 volatile uint32_t *bmd_rfcnt = (uint32_t *)BMAP_RFCNT;
289 volatile uint32_t *bmd_bmsel = (uint32_t *)BMAP_BMSEL;
290 struct bmd_softc *bp = &bmd_softc;
291 struct bmd_linec *bq;
292 int i;
293 union bmd_rfcnt rfcnt;
294
295 /*
296 * adjust plane position
297 */
298
299 /* plane-0 hardware address */
300 bp->bc_raddr = (uint8_t *)(BMAP_BMAP0 + BMAP_OFFSET);
301 /* common bitmap hardware address */
302 bp->bc_waddr = (uint8_t *)(BMAP_BMP + BMAP_OFFSET);
303
304 rfcnt.p.rfc_hcnt = 7; /* shift left 16 dot */
305 rfcnt.p.rfc_vcnt = -27; /* shift down 1 dot */
306 *bmd_rfcnt = rfcnt.u;
307
308 bp->bc_stat = STAT_NORMAL;
309
310 bp->bc_xmin = 8;
311 bp->bc_xmax = 96;
312 bp->bc_ymin = 2;
313 bp->bc_ymax = 48;
314
315 bp->bc_row = bp->bc_ymin;
316
317 for (i = bp->bc_ymin; i < bp->bc_ymax; i++) {
318 bmd_linec[i].bl_next = &bmd_linec[i + 1];
319 bmd_linec[i].bl_prev = &bmd_linec[i - 1];
320 }
321 bmd_linec[bp->bc_ymax - 1].bl_next = &bmd_linec[bp->bc_ymin];
322 bmd_linec[bp->bc_ymin].bl_prev = &bmd_linec[bp->bc_ymax - 1];
323
324 bq = bp->bc_bl = &bmd_linec[bp->bc_ymin];
325 bq->bl_col = bq->bl_end = bp->bc_xmin;
326
327 bp->bc_col = bp->bc_xmin;
328
329 bp->bc_esc = &bp->bc_escseq[0];
330 bp->bc_escape = bmd_escape;
331
332 *bmd_bmsel = 0xff; /* all planes */
333 bmd_erase_screen((uint32_t *)bp->bc_waddr); /* clear screen */
334 *bmd_bmsel = 0x01; /* 1 plane */
335
336 /* turn on cursor */
337 bmd_reverse_char(bp->bc_raddr,
338 bp->bc_waddr,
339 bq->bl_col, bp->bc_row);
340 }
341
342 void
bmdadjust(int16_t hcnt,int16_t vcnt)343 bmdadjust(int16_t hcnt, int16_t vcnt)
344 {
345 volatile uint32_t *bmd_rfcnt = (uint32_t *)BMAP_RFCNT;
346 union bmd_rfcnt rfcnt;
347
348 printf("bmdadjust: hcnt = %d, vcnt = %d\n", hcnt, vcnt);
349
350 rfcnt.p.rfc_hcnt = hcnt; /* shift left 16 dot */
351 rfcnt.p.rfc_vcnt = vcnt; /* shift down 1 dot */
352
353 *bmd_rfcnt = rfcnt.u;
354 }
355
356 int
bmdputc(int c)357 bmdputc(int c)
358 {
359 struct bmd_softc *bp = &bmd_softc;
360 struct bmd_linec *bq = bp->bc_bl;
361 int i;
362
363 c &= 0x7F;
364
365 /* turn off cursor */
366 bmd_reverse_char(bp->bc_raddr,
367 bp->bc_waddr,
368 bq->bl_col, bp->bc_row);
369
370 /* do escape-sequence */
371 if (bp->bc_stat & STAT_ESCAPE) {
372 *bp->bc_esc++ = c;
373 (*bp->bc_escape)(c);
374 goto done;
375 }
376
377 if (isprint(c)) {
378 bmd_draw_char(bp->bc_raddr, bp->bc_waddr,
379 bq->bl_col, bp->bc_row, c);
380 bq->bl_col++;
381 bq->bl_end++;
382 if (bq->bl_col >= bp->bc_xmax) {
383 bq->bl_col = bq->bl_end = bp->bc_xmin;
384 bp->bc_row++;
385 if (bp->bc_row >= bp->bc_ymax) {
386 bmd_scroll_screen((uint32_t *)bp->bc_raddr,
387 (uint32_t *)bp->bc_waddr,
388 bp->bc_xmin, bp->bc_xmax,
389 bp->bc_ymin, bp->bc_ymax);
390
391 bp->bc_row = bp->bc_ymax - 1;
392 }
393 }
394 } else {
395 switch (c) {
396 case 0x08: /* BS */
397 if (bq->bl_col > bp->bc_xmin) {
398 bq->bl_col--;
399 }
400 break;
401
402 case 0x09: /* HT */
403 case 0x0B: /* VT */
404 i = ((bq->bl_col / 8) + 1) * 8;
405 if (i < bp->bc_xmax) {
406 bq->bl_col = bq->bl_end = i;
407 }
408 break;
409
410 case 0x0A: /* NL */
411 bp->bc_row++;
412 if (bp->bc_row >= bp->bc_ymax) {
413 bmd_scroll_screen((uint32_t *)bp->bc_raddr,
414 (uint32_t *)bp->bc_waddr,
415 bp->bc_xmin, bp->bc_xmax,
416 bp->bc_ymin, bp->bc_ymax);
417
418 bp->bc_row = bp->bc_ymax - 1;
419 }
420 break;
421
422 case 0x0D: /* CR */
423 bq->bl_col = bp->bc_xmin;
424 break;
425
426 case 0x1B: /* ESC */
427 bp->bc_stat |= STAT_ESCAPE;
428 *bp->bc_esc++ = 0x1b;
429 break;
430
431 case 0x7F: /* DEL */
432 if (bq->bl_col > bp->bc_xmin) {
433 bq->bl_col--;
434 bmd_erase_char(bp->bc_raddr,
435 bp->bc_waddr,
436 bq->bl_col, bp->bc_row);
437 }
438 break;
439
440 default:
441 break;
442 }
443 }
444
445 done:
446 /* turn on cursor */
447 bmd_reverse_char(bp->bc_raddr,
448 bp->bc_waddr,
449 bq->bl_col, bp->bc_row);
450
451 return c;
452 }
453
454 void
bmdclear(void)455 bmdclear(void)
456 {
457 struct bmd_softc *bp = &bmd_softc;
458 struct bmd_linec *bq = bp->bc_bl;
459
460 /* clear screen */
461 bmd_erase_screen((uint32_t *)bp->bc_waddr);
462
463 bq->bl_col = bq->bl_end = bp->bc_xmin;
464 bp->bc_row = bp->bc_ymin;
465
466 /* turn on cursor */
467 bmd_reverse_char(bp->bc_raddr,
468 bp->bc_waddr,
469 bq->bl_col, bp->bc_row);
470 }
471
472
473 /*
474 * character operation routines
475 */
476
477 static void
bmd_draw_char(uint8_t * raddr,uint8_t * waddr,int col,int row,int c)478 bmd_draw_char(uint8_t *raddr, uint8_t *waddr, int col, int row, int c)
479 {
480 volatile uint16_t *p, *q;
481 volatile uint32_t *lp, *lq;
482 const uint16_t *fp;
483 int i;
484
485 fp = &bmdfont[c][0];
486
487 switch (col % 4) {
488
489 case 0:
490 p = (uint16_t *)(raddr + ((row * FB_HEIGHT) << 8)
491 + ((col / 4) * 6));
492 q = (uint16_t *)(waddr + ((row * FB_HEIGHT) << 8)
493 + ((col / 4) * 6));
494 for (i = 0; i < FB_HEIGHT; i++) {
495 *q = (*p & 0x000F) | (*fp & 0xFFF0);
496 p += 128;
497 q += 128;
498 fp++;
499 }
500 break;
501
502 case 1:
503 lp = (uint32_t *)(raddr + ((row * FB_HEIGHT) << 8)
504 + ((col / 4) * 6));
505 lq = (uint32_t *)(waddr + ((row * FB_HEIGHT) << 8)
506 + ((col / 4) * 6));
507 for (i = 0; i < FB_HEIGHT; i++) {
508 *lq = (*lp & 0xFFF000FF) |
509 ((uint32_t)(*fp & 0xFFF0) << 4);
510 lp += 64;
511 lq += 64;
512 fp++;
513 }
514 break;
515
516 case 2:
517 lp = (uint32_t *)(raddr + ((row * FB_HEIGHT) << 8)
518 + ((col / 4) * 6) + 2);
519 lq = (uint32_t *)(waddr + ((row * FB_HEIGHT) << 8)
520 + ((col / 4) * 6) + 2);
521 for (i = 0; i < FB_HEIGHT; i++) {
522 *lq = (*lp & 0xFF000FFF) |
523 ((uint32_t)(*fp & 0xFFF0) << 8);
524 lp += 64;
525 lq += 64;
526 fp++;
527 }
528 break;
529
530 case 3:
531 p = (uint16_t *)(raddr + ((row * FB_HEIGHT) << 8)
532 + ((col / 4) * 6) + 4);
533 q = (uint16_t *)(waddr + ((row * FB_HEIGHT) << 8)
534 + ((col / 4) * 6) + 4);
535 for (i = 0; i < FB_HEIGHT; i++) {
536 *q = (*p & 0xF000) | ((*fp & 0xFFF0) >> 4);
537 p += 128;
538 q += 128;
539 fp++;
540 }
541 break;
542
543 default:
544 break;
545 }
546 }
547
548 static void
bmd_reverse_char(uint8_t * raddr,uint8_t * waddr,int col,int row)549 bmd_reverse_char(uint8_t *raddr, uint8_t *waddr, int col, int row)
550 {
551 volatile uint16_t *p, *q;
552 volatile uint32_t *lp, *lq;
553 int i;
554
555 switch (col % 4) {
556
557 case 0:
558 p = (uint16_t *)(raddr + ((row * FB_HEIGHT) << 8)
559 + ((col / 4) * 6));
560 q = (uint16_t *)(waddr + ((row * FB_HEIGHT) << 8)
561 + ((col / 4) * 6));
562 for (i = 0; i < FB_HEIGHT; i++) {
563 *q = (*p & 0x000F) | (~(*p) & 0xFFF0);
564 p += 128;
565 q += 128;
566 }
567 break;
568
569 case 1:
570 lp = (uint32_t *)(raddr + ((row * FB_HEIGHT) << 8)
571 + ((col / 4) * 6));
572 lq = (uint32_t *)(waddr + ((row * FB_HEIGHT) << 8)
573 + ((col / 4) * 6));
574 for (i = 0; i < FB_HEIGHT; i++) {
575 *lq = (*lp & 0xFFF000FF) | (~(*lp) & 0x000FFF00);
576 lp += 64;
577 lq += 64;
578 }
579 break;
580
581 case 2:
582 lp = (uint32_t *)(raddr + ((row * FB_HEIGHT) << 8)
583 + ((col / 4) * 6) + 2);
584 lq = (uint32_t *)(waddr + ((row * FB_HEIGHT) << 8)
585 + ((col / 4) * 6) + 2);
586 for (i = 0; i < FB_HEIGHT; i++) {
587 *lq = (*lp & 0xFF000FFF) | (~(*lp) & 0x00FFF000);
588 lp += 64;
589 lq += 64;
590 }
591 break;
592
593 case 3:
594 p = (uint16_t *)(raddr + ((row * FB_HEIGHT) << 8)
595 + ((col / 4) * 6) + 4);
596 q = (uint16_t *)(waddr + ((row * FB_HEIGHT) << 8)
597 + ((col / 4) * 6) + 4);
598 for (i = 0; i < FB_HEIGHT; i++) {
599 *q = (*p & 0xF000) | (~(*p) & 0x0FFF);
600 p += 128;
601 q += 128;
602 }
603 break;
604
605 default:
606 break;
607 }
608 }
609
610 static void
bmd_erase_char(uint8_t * raddr,uint8_t * waddr,int col,int row)611 bmd_erase_char(uint8_t *raddr, uint8_t *waddr, int col, int row)
612 {
613
614 bmd_draw_char(raddr, waddr, col, row, 0);
615 }
616
617
618 /*
619 * screen operation routines
620 */
621
622 static void
bmd_erase_screen(volatile uint32_t * lp)623 bmd_erase_screen(volatile uint32_t *lp)
624 {
625 int i, j;
626
627 for (i = 0; i < SB_HEIGHT; i++) {
628 for (j = 0; j < SL_WIDTH; j++)
629 *lp++ = 0;
630 SKIP_NEXT_LINE(lp);
631 }
632 }
633
634 static void
bmd_scroll_screen(volatile uint32_t * lp,volatile uint32_t * lq,int xmin,int xmax,int ymin,int ymax)635 bmd_scroll_screen(volatile uint32_t *lp, volatile uint32_t *lq,
636 int xmin, int xmax, int ymin, int ymax)
637 {
638 int i, j;
639
640 lp += ((PL_WIDTH * FB_HEIGHT) * (ymin + 1));
641 lq += ((PL_WIDTH * FB_HEIGHT) * ymin);
642
643 for (i = 0; i < ((ymax - ymin -1) * FB_HEIGHT); i++) {
644 for (j = 0; j < SL_WIDTH; j++) {
645 *lq++ = *lp++;
646 }
647 lp += (PL_WIDTH - SL_WIDTH);
648 lq += (PL_WIDTH - SL_WIDTH);
649 }
650
651 for (i = 0; i < FB_HEIGHT; i++) {
652 for (j = 0; j < SL_WIDTH; j++) {
653 *lq++ = 0;
654 }
655 lq += (PL_WIDTH - SL_WIDTH);
656 }
657 }
658