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